glimmer-dsl-swt 0.1.3 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3b097c051f15a0fd1a52677fd65d542a67532a2e1a51fc928fc22acd8e729953
4
- data.tar.gz: 203b4cd8bad18d912e83067fce0175e5667f7db503cfa67bf9beac6e72752508
3
+ metadata.gz: e33ae73c95946ba7fce0d3dc221cee2ca817968a03bbfe678ff9e0ecfbaf5a65
4
+ data.tar.gz: c95f41b789e3dee67c94dbf79d6e8367d5ad7a1fb94749e784a8c3b13ef8a4aa
5
5
  SHA512:
6
- metadata.gz: edb0568d6bcf252b89332050f2de545917bb6ce2bd687dae961e1aa1afb66d9a051420ea00745db028a93d3869ab5ca9229192d806daa3e0db652a5fffdc1df5
7
- data.tar.gz: 745dae7d8a1999c0267b4d4e7a66a37209bb59c29e4c0f9c7ccf31dc87b2bcd0903eef7c2a0bc6cb46a498200468ce9bcb28d1b5752b54a5a0340be350793e0e
6
+ metadata.gz: c4784a352196f496c4fce136da828352c9c92c2f7092e917f9c47a403bd91964566a2d493680b35f13d240a87dd37830153f3a37ea050ea0d84aa8b02071cfdc
7
+ data.tar.gz: 9080d1bdc15f375db58fa8719d5c6fb8d2017313fe52ea7e2ad7b4dd042f47daa8bf87edecffa819c6e1596839af619f989335839fa757dd2e645ce6c6e13fdb
data/README.md CHANGED
@@ -1,10 +1,12 @@
1
- # <img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 /> Glimmer DSL for SWT 0.1.3 (Desktop GUI)
1
+ # <img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 /> Glimmer DSL for SWT 0.2.4 (Desktop GUI)
2
2
  [![Gem Version](https://badge.fury.io/rb/glimmer-dsl-swt.svg)](http://badge.fury.io/rb/glimmer-dsl-swt)
3
3
  [![Travis CI](https://travis-ci.com/AndyObtiva/glimmer-dsl-swt.svg?branch=master)](https://travis-ci.com/github/AndyObtiva/glimmer-dsl-swt)
4
4
  [![Coverage Status](https://coveralls.io/repos/github/AndyObtiva/glimmer-dsl-swt/badge.svg?branch=master)](https://coveralls.io/github/AndyObtiva/glimmer-dsl-swt?branch=master)
5
5
  [![Join the chat at https://gitter.im/AndyObtiva/glimmer](https://badges.gitter.im/AndyObtiva/glimmer.svg)](https://gitter.im/AndyObtiva/glimmer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
6
6
 
7
- [Glimmer](https://github.com/AndyObtiva/glimmer) DSL for SWT enables desktop development with Glimmer.
7
+ [Glimmer](https://github.com/AndyObtiva/glimmer) DSL for [SWT](https://www.eclipse.org/swt/) enables desktop development with [Glimmer](https://github.com/AndyObtiva/glimmer).
8
+
9
+ [Glimmer](https://github.com/AndyObtiva/glimmer) is a native-GUI cross-platform desktop development library written in Ruby. Glimmer's main innovation is a JRuby DSL that enables productive and efficient authoring of desktop application user-interfaces while relying on the robust Eclipse SWT library. Glimmer additionally innovates by having built-in data-binding support to greatly facilitate synchronizing the GUI with domain models. As a result, that achieves true decoupling of object oriented components, enabling developers to solve business problems without worrying about GUI concerns, or alternatively drive development GUI-first, and then write clean business models test-first afterwards.
8
10
 
9
11
  You may find full setup/usage instructions at the main [Glimmer project page](https://github.com/AndyObtiva/glimmer).
10
12
 
@@ -13,6 +15,23 @@ Other Glimmer DSL gems:
13
15
  - [glimmer-dsl-xml](https://github.com/AndyObtiva/glimmer-dsl-xml): Glimmer DSL for XML (& HTML)
14
16
  - [glimmer-dsl-css](https://github.com/AndyObtiva/glimmer-dsl-css): Glimmer DSL for CSS (Cascading Style Sheets)
15
17
 
18
+ ## Example
19
+
20
+ ```ruby
21
+ include Glimmer
22
+
23
+ shell {
24
+ text 'Glimmer'
25
+ label {
26
+ text 'Hello, World!'
27
+ }
28
+ }.open
29
+ ```
30
+
31
+ ![Glimmer DSL for SWT Hello World](https://github.com/AndyObtiva/glimmer/blob/master/images/glimmer-hello-world.png)
32
+
33
+ Learn more at the main [Glimmer project page](https://github.com/AndyObtiva/glimmer).
34
+
16
35
  ## Help
17
36
 
18
37
  ### Issues
@@ -1 +1 @@
1
- jruby-9.2.11.1
1
+ jruby-9.2.12.0
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.3
1
+ 0.2.4
@@ -3,11 +3,18 @@ require 'glimmer/swt/packages'
3
3
  module Glimmer
4
4
  class << self
5
5
  def included(klass)
6
+ if Object.const_defined?(:ActiveSupport) && ActiveSupport.const_defined?(:Dependencies)
7
+ begin
8
+ ActiveSupport::Dependencies.unhook!
9
+ rescue => e
10
+ # noop TODO support logging unimportant details below debug level
11
+ end
12
+ end
6
13
  if Config.import_swt_packages
7
14
  klass.include(SWT::Packages)
8
15
  klass.extend(SWT::Packages)
9
- klass.extend(Glimmer)
10
16
  end
17
+ klass.extend(Glimmer)
11
18
  end
12
19
  end
13
20
  end
@@ -1,16 +1,24 @@
1
1
  module Glimmer
2
2
  module Config
3
+ DEFAULT_IMPORT_SWT_PACKAGES = [
4
+ 'org.eclipse.swt',
5
+ 'org.eclipse.swt.widgets',
6
+ 'org.eclipse.swt.layout',
7
+ 'org.eclipse.swt.graphics',
8
+ 'org.eclipse.swt.browser',
9
+ 'org.eclipse.swt.custom',
10
+ 'org.eclipse.swt.dnd',
11
+ ]
12
+
3
13
  class << self
4
14
  # Tells Glimmer to import SWT packages into including class (default: true)
5
15
  def import_swt_packages=(value)
6
- @@import_swt_packages = !!value
16
+ @@import_swt_packages = value
7
17
  end
8
18
 
9
19
  # Returns whether Glimmer will import SWT packages into including class
10
20
  def import_swt_packages
11
- unless defined? @@import_swt_packages
12
- @@import_swt_packages = true
13
- end
21
+ @@import_swt_packages = DEFAULT_IMPORT_SWT_PACKAGES if !defined?(@@import_swt_packages) || (defined?(@@import_swt_packages) && @@import_swt_packages == true)
14
22
  @@import_swt_packages
15
23
  end
16
24
  end
@@ -2,9 +2,14 @@ $LOAD_PATH.unshift(File.expand_path('..', __FILE__))
2
2
 
3
3
  # External requires
4
4
  require 'java'
5
- require 'nested_inherited_jruby_include_package'
6
- require 'super_module'
7
- require 'glimmer'
5
+ if ENV['BUNDLER_REQUIRE'].to_s.downcase == 'true'
6
+ require 'bundler'
7
+ Bundler.require
8
+ else
9
+ require 'nested_inherited_jruby_include_package'
10
+ require 'super_module'
11
+ require 'glimmer'
12
+ end
8
13
 
9
14
  # Internal requires
10
15
  require 'ext/glimmer/config'
@@ -15,6 +15,7 @@ module Glimmer
15
15
  def initialize(parent, model_binding, column_properties)
16
16
  @table = parent
17
17
  @model_binding = model_binding
18
+ @table.swt_widget.data = @model_binding
18
19
  @column_properties = column_properties
19
20
  if @table.respond_to?(:column_properties=)
20
21
  @table.column_properties = @column_properties
@@ -22,14 +23,14 @@ module Glimmer
22
23
  @table.body_root.column_properties = @column_properties
23
24
  end
24
25
  call(@model_binding.evaluate_property)
25
- model = model_binding.base_model
26
- observe(model, model_binding.property_name_expression)
26
+ observe(model_binding)
27
27
  @table.on_widget_disposed do |dispose_event|
28
28
  unregister_all_observables
29
29
  end
30
30
  end
31
31
 
32
32
  def call(new_model_collection=nil)
33
+ new_model_collection = @model_binding.evaluate_property # this ensures applying converters (e.g. :on_read)
33
34
  if new_model_collection and new_model_collection.is_a?(Array)
34
35
  observe(new_model_collection, @column_properties)
35
36
  @model_collection = new_model_collection
@@ -0,0 +1,20 @@
1
+ require 'glimmer/dsl/expression'
2
+
3
+ module Glimmer
4
+ module DSL
5
+ module SWT
6
+ class BlockPropertyExpression < Expression
7
+ def can_interpret?(parent, keyword, *args, &block)
8
+ block_given? and
9
+ args.size == 0 and
10
+ parent.respond_to?("#{keyword}_block=")
11
+ end
12
+
13
+ def interpret(parent, keyword, *args, &block)
14
+ parent.send("#{keyword}_block=", block)
15
+ nil
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -35,6 +35,10 @@ module Glimmer
35
35
  parent.on_widget_selected do
36
36
  model_binding.call(widget_binding.evaluate_property)
37
37
  end
38
+
39
+ parent.on_modify_text do
40
+ model_binding.call(widget_binding.evaluate_property)
41
+ end
38
42
  end
39
43
  end
40
44
  end
@@ -0,0 +1,25 @@
1
+ require 'glimmer/dsl/static_expression'
2
+ require 'glimmer/swt/dnd_proxy'
3
+
4
+ # TODO consider turning static keywords like bind into methods
5
+
6
+ module Glimmer
7
+ module DSL
8
+ module SWT
9
+ # Responsible for returning DND constant values
10
+ #
11
+ # Named DndExpression (not DNDExpression) so that the DSL engine
12
+ # discovers quickly by convention
13
+ class DndExpression < StaticExpression
14
+ def can_interpret?(parent, keyword, *args, &block)
15
+ block.nil? &&
16
+ args.size > 0
17
+ end
18
+
19
+ def interpret(parent, keyword, *args, &block)
20
+ Glimmer::SWT::DNDProxy[*args]
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -25,6 +25,7 @@ module Glimmer
25
25
  table_items_data_binding
26
26
  data_binding
27
27
  property
28
+ block_property
28
29
  widget
29
30
  custom_widget
30
31
  ]
@@ -14,10 +14,6 @@ module Glimmer
14
14
 
15
15
  include_package 'org.eclipse.swt.widgets'
16
16
 
17
- def can_interpret?(parent, keyword, *args, &block)
18
- keyword == 'message_box'
19
- end
20
-
21
17
  def interpret(parent, keyword, *args, &block)
22
18
  potential_parent = args.first
23
19
  parent = args.shift if potential_parent.is_a?(Shell) || (potential_parent.respond_to?(:swt_widget) && potential_parent.swt_widget.is_a?(Shell))
@@ -31,5 +31,7 @@ module Glimmer
31
31
  end
32
32
 
33
33
  require 'glimmer/swt/widget_proxy'
34
+ require 'glimmer/swt/scrolled_composite_proxy'
34
35
  require 'glimmer/swt/tree_proxy'
35
36
  require 'glimmer/swt/table_proxy'
37
+ require 'glimmer/swt/table_column_proxy'
@@ -7,6 +7,12 @@ module Glimmer
7
7
  class << self
8
8
  attr_accessor :javapackager_extra_args
9
9
 
10
+ def clean
11
+ require 'fileutils'
12
+ FileUtils.rm_rf('dist')
13
+ FileUtils.rm_rf('packages')
14
+ end
15
+
10
16
  def config
11
17
  project_name = File.basename(File.expand_path('.'))
12
18
  if !File.exists?('config/warble.rb')
@@ -15,7 +21,7 @@ module Glimmer
15
21
  system('warble config')
16
22
  new_config = File.read('config/warble.rb').split("\n").inject('') do |output, line|
17
23
  if line.include?('config.dirs =')
18
- line = line.sub('# ', '').sub(/=[^=\n]+$/, '= %w(app config db lib script bin docs fonts icons images sounds videos)')
24
+ line = line.sub('# ', '').sub(/=[^=\n]+$/, '= %w(app config db lib script bin docs fonts icons images sounds videos vendor)')
19
25
  end
20
26
  if line.include?('config.includes =')
21
27
  line = line.sub('# ', '').sub(/=[^=\n]+$/, "= FileList['LICENSE.txt', 'VERSION']")
@@ -4,6 +4,11 @@ require_relative 'package'
4
4
 
5
5
  namespace :glimmer do
6
6
  namespace :package do
7
+ desc 'Clean by removing "dist" and "packages" directories'
8
+ task :clean do
9
+ Glimmer::Package.clean
10
+ end
11
+
7
12
  desc 'Generate JAR config file'
8
13
  task :config do
9
14
  Glimmer::Package.config
@@ -58,7 +58,7 @@ class Scaffold
58
58
 
59
59
  # for a library or gem, you might want to ignore these files since the code is
60
60
  # intended to run in multiple environments; otherwise, check them in:
61
- Gemfile.lock
61
+ # Gemfile.lock
62
62
  # .ruby-version
63
63
  # .ruby-gemset
64
64
 
@@ -179,6 +179,7 @@ class Scaffold
179
179
  end
180
180
 
181
181
  def custom_shell_gem(custom_shell_name, namespace)
182
+ return puts('Namespace is required! Usage: glimmer scaffold:custom_shell_gem[custom_shell_name,namespace]') unless `git config --get github.user`.to_s.strip == 'AndyObtiva'
182
183
  gem_name = "glimmer-cs-#{compact_name(custom_shell_name)}"
183
184
  gem_summary = "#{human_name(custom_shell_name)} - Glimmer Custom Shell"
184
185
  if namespace
@@ -218,6 +219,7 @@ class Scaffold
218
219
  end
219
220
 
220
221
  def custom_widget_gem(custom_widget_name, namespace)
222
+ return puts('Namespace is required! Usage: glimmer scaffold:custom_widget_gem[custom_widget_name,namespace]') unless `git config --get github.user`.to_s.strip == 'AndyObtiva'
221
223
  gem_name = "glimmer-cw-#{compact_name(custom_widget_name)}"
222
224
  gem_summary = "#{human_name(custom_widget_name)} - Glimmer Custom Widget"
223
225
  if namespace
@@ -1,14 +1,16 @@
1
+ require 'ext/glimmer/config'
2
+
1
3
  module Glimmer
2
4
  module SWT
3
5
  # This contains Java imports of SWT Java packages
4
6
  module Packages
5
- include_package 'org.eclipse.swt'
6
- include_package 'org.eclipse.swt.widgets'
7
- include_package 'org.eclipse.swt.layout'
8
- include_package 'org.eclipse.swt.graphics'
9
- include_package 'org.eclipse.swt.browser'
10
- include_package 'org.eclipse.swt.custom'
11
- include_package 'org.eclipse.swt.dnd'
7
+ class << self
8
+ def included(klass)
9
+ Glimmer::Config.import_swt_packages.to_a.each do |package|
10
+ include_package(package) if package.is_a?(String)
11
+ end
12
+ end
13
+ end
12
14
  end
13
15
  end
14
16
  end
@@ -0,0 +1,21 @@
1
+ require 'glimmer/swt/widget_proxy'
2
+
3
+ module Glimmer
4
+ module SWT
5
+ class ScrolledCompositeProxy < Glimmer::SWT::WidgetProxy
6
+ def initialize(underscored_widget_name, parent, args)
7
+ unless args.first.is_a?(Numeric)
8
+ args.unshift(:h_scroll)
9
+ args.unshift(:v_scroll)
10
+ end
11
+ super
12
+ swt_widget.expand_horizontal = true
13
+ swt_widget.expand_vertical = true
14
+ end
15
+
16
+ def post_initialize_child(child)
17
+ swt_widget.content = child.swt_widget
18
+ end
19
+ end
20
+ end
21
+ end
@@ -31,7 +31,8 @@ module Glimmer
31
31
  end
32
32
 
33
33
  EXTRA_STYLES = {
34
- NO_RESIZE: self[:shell_trim, :resize!, :max!]
34
+ NO_RESIZE: self[:shell_trim, :resize!, :max!],
35
+ NO_SORT: -7,
35
36
  }
36
37
  end
37
38
  end
@@ -0,0 +1,24 @@
1
+ require 'glimmer/swt/widget_proxy'
2
+
3
+ module Glimmer
4
+ module SWT
5
+ class TableColumnProxy < Glimmer::SWT::WidgetProxy
6
+ attr_reader :no_sort, :sort_property
7
+ alias no_sort? no_sort
8
+ attr_accessor :sort_block, :sort_by_block
9
+
10
+ def initialize(underscored_widget_name, parent, args)
11
+ @no_sort = args.delete(:no_sort)
12
+ super
13
+ on_widget_selected do |event|
14
+ parent.sort_by_column(self)
15
+ end unless no_sort?
16
+ end
17
+
18
+ def sort_property=(args)
19
+ @sort_property = args.to_a.first
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -33,7 +33,7 @@ module Glimmer
33
33
  end
34
34
  end
35
35
 
36
- attr_reader :table_editor, :table_editor_text_proxy
36
+ attr_reader :table_editor, :table_editor_text_proxy, :sort_property, :sort_direction, :sort_block, :sort_type, :sort_by_block
37
37
  attr_accessor :column_properties
38
38
 
39
39
  def initialize(underscored_widget_name, parent, args)
@@ -43,7 +43,70 @@ module Glimmer
43
43
  @table_editor.grabHorizontal = true
44
44
  @table_editor.minimumHeight = 20
45
45
  end
46
-
46
+
47
+ def model_binding
48
+ swt_widget.data
49
+ end
50
+
51
+ def sort_by_column(table_column_proxy)
52
+ index = swt_widget.columns.to_a.index(table_column_proxy.swt_widget)
53
+ new_sort_property = table_column_proxy.sort_property || column_properties[index]
54
+ @sort_direction = @sort_direction.nil? || @sort_property != new_sort_property || @sort_direction == :descending ? :ascending : :descending
55
+ @sort_property = new_sort_property
56
+ if table_column_proxy.sort_by_block
57
+ @sort_by_block = table_column_proxy.sort_by_block
58
+ elsif table_column_proxy.sort_block
59
+ @sort_block = table_column_proxy.sort_block
60
+ else
61
+ detect_sort_type
62
+ end
63
+ sort
64
+ end
65
+
66
+ def detect_sort_type
67
+ @sort_type = String
68
+ array = model_binding.evaluate_property
69
+ values = array.map { |object| object.send(sort_property) }
70
+ value_classes = values.map(&:class).uniq
71
+ if value_classes.size == 1
72
+ @sort_type = value_classes.first
73
+ elsif value_classes.include?(Integer)
74
+ @sort_type = Integer
75
+ elsif value_classes.include?(Float)
76
+ @sort_type = Float
77
+ end
78
+ end
79
+
80
+ def sort
81
+ return unless sort_property && (sort_type || sort_block || sort_by_block)
82
+ array = model_binding.evaluate_property
83
+ # Converting value to_s first to handle nil cases. Should work with numeric, boolean, and date fields
84
+ if sort_block
85
+ sorted_array = array.sort do |object1, object2|
86
+ value1 = object1.send(sort_property)
87
+ value2 = object2.send(sort_property)
88
+ sort_block.call(value1, value2)
89
+ end
90
+ else
91
+ sorted_array = array.sort_by do |object|
92
+ value = object.send(sort_property)
93
+ # handle nil and difficult to compare types gracefully
94
+ if sort_by_block
95
+ value = sort_by_block.call(value)
96
+ elsif sort_type == Integer
97
+ value = value.to_i
98
+ elsif sort_type == Float
99
+ value = value.to_f
100
+ elsif sort_type == String
101
+ value = value.to_s
102
+ end
103
+ value
104
+ end
105
+ end
106
+ sorted_array = sorted_array.reverse if sort_direction == :descending
107
+ model_binding.call(sorted_array)
108
+ end
109
+
47
110
  # Performs a search for table items matching block condition
48
111
  # If no condition block is passed, returns all table items
49
112
  # Returns a Java TableItem array to easily set as selection on org.eclipse.swt.Table if needed
@@ -31,8 +31,8 @@ module Glimmer
31
31
  "list" => [:border, :v_scroll],
32
32
  "button" => [:push],
33
33
  "menu_item" => [:push],
34
- "drag_source" => DND::DROP_COPY,
35
- "drop_target" => DND::DROP_COPY,
34
+ "drag_source" => [:drop_copy],
35
+ "drop_target" => [:drop_copy],
36
36
  }
37
37
 
38
38
  DEFAULT_INITIALIZERS = {
@@ -51,7 +51,7 @@ module Glimmer
51
51
  end,
52
52
  }
53
53
 
54
- attr_reader :swt_widget
54
+ attr_reader :swt_widget, :drag_source_proxy, :drop_target_proxy, :drag_source_style, :drag_source_transfer, :drop_target_transfer
55
55
 
56
56
  # Initializes a new SWT Widget
57
57
  #
@@ -61,6 +61,12 @@ module Glimmer
61
61
  swt_widget_class = self.class.swt_widget_class_for(underscored_widget_name)
62
62
  @swt_widget = swt_widget_class.new(parent.swt_widget, style(underscored_widget_name, styles), *extra_options)
63
63
  DEFAULT_INITIALIZERS[underscored_widget_name]&.call(@swt_widget)
64
+ parent.post_initialize_child(self)
65
+ end
66
+
67
+ # Subclasses may override to perform post initialization work on an added child
68
+ def post_initialize_child(child)
69
+ # No Op by default
64
70
  end
65
71
 
66
72
  def extract_args(underscored_widget_name, args)
@@ -75,7 +81,18 @@ module Glimmer
75
81
  if @arg_extractor_mapping[underscored_widget_name]
76
82
  @arg_extractor_mapping[underscored_widget_name].call(args)
77
83
  else
78
- [args, []]
84
+ extra_options = []
85
+ style_args = args.select {|arg| arg.is_a?(Symbol) || arg.is_a?(String)}
86
+ if style_args.any?
87
+ style_arg_start_index = args.index(style_args.first)
88
+ style_arg_last_index = args.index(style_args.last)
89
+ extra_options = args[style_arg_last_index+1..-1]
90
+ args = args[style_arg_start_index..style_arg_last_index]
91
+ elsif args.first.is_a?(Integer)
92
+ extra_options = args[1..-1]
93
+ args = args[0..0]
94
+ end
95
+ [args, extra_options]
79
96
  end
80
97
  end
81
98
 
@@ -84,7 +101,7 @@ module Glimmer
84
101
  if widget_custom_attribute
85
102
  @swt_widget.respond_to?(widget_custom_attribute[:setter][:name])
86
103
  else
87
- @swt_widget.respond_to?(attribute_setter(attribute_name), args)
104
+ @swt_widget.respond_to?(attribute_setter(attribute_name), args) || respond_to?(ruby_attribute_setter(attribute_name), args)
88
105
  end
89
106
  end
90
107
 
@@ -92,9 +109,11 @@ module Glimmer
92
109
  widget_custom_attribute = widget_custom_attribute_mapping[attribute_name.to_s]
93
110
  if widget_custom_attribute
94
111
  widget_custom_attribute[:setter][:invoker].call(@swt_widget, args)
95
- else
112
+ elsif @swt_widget.respond_to?(attribute_setter(attribute_name), args)
96
113
  apply_property_type_converters(attribute_name, args)
97
114
  @swt_widget.send(attribute_setter(attribute_name), *args) unless @swt_widget.send(attribute_getter(attribute_name)) == args.first
115
+ else
116
+ send(ruby_attribute_setter(attribute_name), args)
98
117
  end
99
118
  end
100
119
 
@@ -132,6 +151,23 @@ module Glimmer
132
151
  observer.call(false)
133
152
  }
134
153
  end,
154
+ :selection => lambda do |observer|
155
+ on_widget_selected { |selection_event|
156
+ observer.call(@swt_widget.getSelection)
157
+ } if can_handle_observation_request?(:on_widget_selected)
158
+ end,
159
+ :text => lambda do |observer|
160
+ on_modify_text { |modify_event|
161
+ observer.call(@swt_widget.getText)
162
+ } if can_handle_observation_request?(:on_modify_text)
163
+ end,
164
+ },
165
+ Java::OrgEclipseSwtWidgets::Combo => {
166
+ :text => lambda do |observer|
167
+ on_modify_text { |modify_event|
168
+ observer.call(@swt_widget.getText)
169
+ }
170
+ end,
135
171
  },
136
172
  Java::OrgEclipseSwtWidgets::Text => {
137
173
  :text => lambda do |observer|
@@ -236,11 +272,11 @@ module Glimmer
236
272
  end
237
273
  swt_widget_class
238
274
  rescue NameError => e
239
- Glimmer::Config.logger&.debug e.message
275
+ Glimmer::Config.logger&.debug e.full_message
240
276
  # Glimmer::Config.logger&.debug("#{e.message}\n#{e.backtrace.join("\n")}")
241
277
  nil
242
278
  rescue => e
243
- Glimmer::Config.logger&.debug e.message
279
+ Glimmer::Config.logger&.debug e.full_message
244
280
  # Glimmer::Config.logger&.debug("#{e.message}\n#{e.backtrace.join("\n")}")
245
281
  nil
246
282
  end
@@ -276,15 +312,28 @@ module Glimmer
276
312
  def add_observer(observer, property_name)
277
313
  property_listener_installers = @swt_widget.class.ancestors.map {|ancestor| widget_property_listener_installers[ancestor]}.compact
278
314
  widget_listener_installers = property_listener_installers.map{|installer| installer[property_name.to_s.to_sym]}.compact if !property_listener_installers.empty?
279
- widget_listener_installers.to_a.each do |widget_listener_installer|
280
- widget_listener_installer.call(observer)
281
- end
315
+ widget_listener_installers.to_a.first&.call(observer)
282
316
  end
283
317
 
284
318
  def remove_observer(observer, property_name)
285
319
  # TODO consider implementing if remove_observer is needed (consumers can remove listener via SWT API)
286
320
  end
287
321
 
322
+ def ensure_drag_source_proxy(style=[])
323
+ @drag_source_proxy ||= self.class.new('drag_source', self, style).tap do |proxy|
324
+ proxy.set_attribute(:transfer, :text)
325
+ end
326
+ end
327
+
328
+ def ensure_drop_target_proxy(style=[])
329
+ @drop_target_proxy ||= self.class.new('drop_target', self, style).tap do |proxy|
330
+ proxy.set_attribute(:transfer, :text)
331
+ proxy.on_drag_enter { |event|
332
+ event.detail = DNDProxy[:drop_copy]
333
+ }
334
+ end
335
+ end
336
+
288
337
  # TODO eliminate duplication in the following methods perhaps by relying on exceptions
289
338
 
290
339
  def can_handle_observation_request?(observation_request)
@@ -294,9 +343,31 @@ module Glimmer
294
343
  SWTProxy.has_constant?(constant_name)
295
344
  elsif observation_request.start_with?('on_')
296
345
  event = observation_request.sub(/^on_/, '')
297
- can_add_listener?(event)
298
- else
299
- false
346
+ can_add_listener?(event) || can_handle_drag_observation_request?(observation_request) || can_handle_drop_observation_request?(observation_request)
347
+ end
348
+ end
349
+
350
+ def can_handle_drag_observation_request?(observation_request)
351
+ return false unless swt_widget.is_a?(Control)
352
+ potential_drag_source = @drag_source_proxy.nil?
353
+ ensure_drag_source_proxy
354
+ @drag_source_proxy.can_handle_observation_request?(observation_request).tap do |result|
355
+ if potential_drag_source && !result
356
+ @drag_source_proxy.swt_widget.dispose
357
+ @drag_source_proxy = nil
358
+ end
359
+ end
360
+ end
361
+
362
+ def can_handle_drop_observation_request?(observation_request)
363
+ return false unless swt_widget.is_a?(Control)
364
+ potential_drop_target = @drop_target_proxy.nil?
365
+ ensure_drop_target_proxy
366
+ @drop_target_proxy.can_handle_observation_request?(observation_request).tap do |result|
367
+ if potential_drop_target && !result
368
+ @drop_target_proxy.swt_widget.dispose
369
+ @drop_target_proxy = nil
370
+ end
300
371
  end
301
372
  end
302
373
 
@@ -306,7 +377,14 @@ module Glimmer
306
377
  add_swt_event_listener(constant_name, &block)
307
378
  elsif observation_request.start_with?('on_')
308
379
  event = observation_request.sub(/^on_/, '')
309
- add_listener(event, &block)
380
+ if can_add_listener?(event)
381
+ event = observation_request.sub(/^on_/, '')
382
+ add_listener(event, &block)
383
+ elsif can_handle_drag_observation_request?(observation_request)
384
+ @drag_source_proxy&.handle_observation_request(observation_request, &block)
385
+ elsif can_handle_drop_observation_request?(observation_request)
386
+ @drop_target_proxy&.handle_observation_request(observation_request, &block)
387
+ end
310
388
  end
311
389
  end
312
390
 
@@ -331,7 +409,11 @@ module Glimmer
331
409
 
332
410
  def default_style(underscored_widget_name)
333
411
  styles = DEFAULT_STYLES[underscored_widget_name] || [:none]
334
- SWTProxy[styles]
412
+ SWTProxy[styles] rescue DNDProxy[styles]
413
+ end
414
+
415
+ def ruby_attribute_setter(attribute_name)
416
+ "#{attribute_name}="
335
417
  end
336
418
 
337
419
  def attribute_setter(attribute_name)
@@ -355,7 +437,7 @@ module Glimmer
355
437
  def add_listener(underscored_listener_name, &block)
356
438
  widget_add_listener_method, listener_class, listener_method = self.class.find_listener(@swt_widget.getClass, underscored_listener_name)
357
439
  widget_listener_proxy = nil
358
- safe_block = lambda { |event| block.call(event) unless @swt_widget.isDisposed }
440
+ safe_block = lambda { |event| block.call(event) unless @swt_widget.isDisposed }
359
441
  listener = listener_class.new(listener_method => safe_block)
360
442
  @swt_widget.send(widget_add_listener_method, listener)
361
443
  widget_listener_proxy = WidgetListenerProxy.new(swt_widget: @swt_widget, swt_listener: listener, widget_add_listener_method: widget_add_listener_method, swt_listener_class: listener_class, swt_listener_method: listener_method)
@@ -432,6 +514,38 @@ module Glimmer
432
514
  }
433
515
  end
434
516
 
517
+ def drag_source_style=(style)
518
+ ensure_drag_source_proxy(style)
519
+ end
520
+
521
+ def drop_target_style=(style)
522
+ ensure_drop_target_proxy(style)
523
+ end
524
+
525
+ def drag_source_transfer=(args)
526
+ args = args.first if !args.empty? && args.first.is_a?(ArrayJavaProxy)
527
+ ensure_drag_source_proxy
528
+ @drag_source_proxy.set_attribute(:transfer, args)
529
+ end
530
+
531
+ def drop_target_transfer=(args)
532
+ args = args.first if !args.empty? && args.first.is_a?(ArrayJavaProxy)
533
+ ensure_drop_target_proxy
534
+ @drop_target_proxy.set_attribute(:transfer, args)
535
+ end
536
+
537
+ def drag_source_effect=(args)
538
+ args = args.first if args.is_a?(Array)
539
+ ensure_drag_source_proxy
540
+ @drag_source_proxy.set_attribute(:drag_source_effect, args)
541
+ end
542
+
543
+ def drop_target_effect=(args)
544
+ args = args.first if args.is_a?(Array)
545
+ ensure_drop_target_proxy
546
+ @drop_target_proxy.set_attribute(:drop_target_effect, args)
547
+ end
548
+
435
549
  def apply_property_type_converters(attribute_name, args)
436
550
  if args.count == 1
437
551
  value = args.first
@@ -495,6 +609,7 @@ module Glimmer
495
609
  end
496
610
  end,
497
611
  :transfer => lambda do |value|
612
+ value = value.first if value.is_a?(Array) && value.size == 1 && value.first.is_a?(Array)
498
613
  transfer_object_extrapolator = lambda do |transfer_name|
499
614
  transfer_type = "#{transfer_name.to_s.camelcase(:upper)}Transfer".to_sym
500
615
  transfer_type_alternative = "#{transfer_name.to_s.upcase}Transfer".to_sym
@@ -137,6 +137,11 @@ module Glimmer
137
137
  execute_hooks('after_body')
138
138
  @swt_widget = @body_root.swt_widget
139
139
  end
140
+
141
+ # Subclasses may override to perform post initialization work on an added child
142
+ def post_initialize_child(child)
143
+ body_root.post_initialize_child(child)
144
+ end
140
145
 
141
146
  def can_handle_observation_request?(observation_request)
142
147
  result = false
metadata CHANGED
@@ -1,21 +1,21 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glimmer-dsl-swt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - AndyMaleh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-28 00:00:00.000000000 Z
11
+ date: 2020-07-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
16
  - - "~>"
17
17
  - !ruby/object:Gem::Version
18
- version: 0.9.3
18
+ version: 0.9.4
19
19
  name: glimmer
20
20
  type: :runtime
21
21
  prerelease: false
@@ -23,7 +23,7 @@ dependencies:
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.9.3
26
+ version: 0.9.4
27
27
  - !ruby/object:Gem::Dependency
28
28
  requirement: !ruby/object:Gem::Requirement
29
29
  requirements:
@@ -256,7 +256,7 @@ dependencies:
256
256
  - - "~>"
257
257
  - !ruby/object:Gem::Version
258
258
  version: 0.7.0
259
- description: Glimmer DSL for SWT (Desktop GUI)
259
+ description: Glimmer DSL for SWT (Desktop GUI) - JRuby on SWT
260
260
  email: andy.am@gmail.com
261
261
  executables:
262
262
  - glimmer
@@ -285,6 +285,7 @@ files:
285
285
  - lib/glimmer/data_binding/widget_binding.rb
286
286
  - lib/glimmer/dsl/swt/async_exec_expression.rb
287
287
  - lib/glimmer/dsl/swt/bind_expression.rb
288
+ - lib/glimmer/dsl/swt/block_property_expression.rb
288
289
  - lib/glimmer/dsl/swt/color_expression.rb
289
290
  - lib/glimmer/dsl/swt/column_properties_expression.rb
290
291
  - lib/glimmer/dsl/swt/combo_selection_data_binding_expression.rb
@@ -292,6 +293,7 @@ files:
292
293
  - lib/glimmer/dsl/swt/data_binding_expression.rb
293
294
  - lib/glimmer/dsl/swt/dialog_expression.rb
294
295
  - lib/glimmer/dsl/swt/display_expression.rb
296
+ - lib/glimmer/dsl/swt/dnd_expression.rb
295
297
  - lib/glimmer/dsl/swt/dsl.rb
296
298
  - lib/glimmer/dsl/swt/exec_expression.rb
297
299
  - lib/glimmer/dsl/swt/layout_data_expression.rb
@@ -327,10 +329,12 @@ files:
327
329
  - lib/glimmer/swt/menu_proxy.rb
328
330
  - lib/glimmer/swt/message_box_proxy.rb
329
331
  - lib/glimmer/swt/packages.rb
332
+ - lib/glimmer/swt/scrolled_composite_proxy.rb
330
333
  - lib/glimmer/swt/shell_proxy.rb
331
334
  - lib/glimmer/swt/style_constantizable.rb
332
335
  - lib/glimmer/swt/swt_proxy.rb
333
336
  - lib/glimmer/swt/tab_item_proxy.rb
337
+ - lib/glimmer/swt/table_column_proxy.rb
334
338
  - lib/glimmer/swt/table_proxy.rb
335
339
  - lib/glimmer/swt/tree_proxy.rb
336
340
  - lib/glimmer/swt/widget_listener_proxy.rb