glimmer-dsl-swt 0.5.6 → 0.6.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/RUBY_VERSION +1 -1
  4. data/VERSION +1 -1
  5. data/bin/girb +1 -1
  6. data/bin/glimmer +1 -1
  7. data/icons/scaffold_app.ico +0 -0
  8. data/icons/scaffold_app.png +0 -0
  9. data/lib/ext/glimmer/config.rb +5 -1
  10. data/lib/glimmer/Rakefile +5 -0
  11. data/lib/glimmer/dsl/swt/cursor_expression.rb +23 -0
  12. data/lib/glimmer/dsl/swt/dsl.rb +3 -0
  13. data/lib/glimmer/dsl/swt/font_expression.rb +26 -0
  14. data/lib/glimmer/dsl/swt/image_expression.rb +21 -0
  15. data/lib/glimmer/dsl/swt/message_box_expression.rb +9 -1
  16. data/lib/glimmer/dsl/swt/widget_expression.rb +7 -7
  17. data/lib/glimmer/launcher.rb +36 -8
  18. data/lib/glimmer/package.rb +31 -7
  19. data/lib/glimmer/rake_task.rb +111 -6
  20. data/lib/glimmer/scaffold.rb +98 -62
  21. data/lib/glimmer/swt/cursor_proxy.rb +45 -0
  22. data/lib/glimmer/swt/display_proxy.rb +13 -2
  23. data/lib/glimmer/swt/font_proxy.rb +7 -7
  24. data/lib/glimmer/swt/image_proxy.rb +16 -23
  25. data/lib/glimmer/swt/layout_proxy.rb +2 -0
  26. data/lib/glimmer/swt/message_box_proxy.rb +23 -5
  27. data/lib/glimmer/swt/scrolled_composite_proxy.rb +6 -11
  28. data/lib/glimmer/swt/style_constantizable.rb +11 -1
  29. data/lib/glimmer/swt/table_proxy.rb +50 -2
  30. data/lib/glimmer/swt/widget_proxy.rb +79 -18
  31. data/samples/elaborate/contact_manager.rb +121 -0
  32. data/samples/elaborate/contact_manager/contact.rb +11 -0
  33. data/samples/elaborate/contact_manager/contact_manager_presenter.rb +26 -0
  34. data/samples/elaborate/contact_manager/contact_repository.rb +244 -0
  35. data/samples/elaborate/login.rb +108 -0
  36. data/samples/elaborate/tic_tac_toe.rb +55 -0
  37. data/samples/elaborate/tic_tac_toe/board.rb +124 -0
  38. data/samples/elaborate/tic_tac_toe/cell.rb +27 -0
  39. data/samples/hello/hello_browser.rb +8 -0
  40. data/samples/hello/hello_combo.rb +38 -0
  41. data/samples/hello/hello_computed.rb +69 -0
  42. data/samples/hello/hello_computed/contact.rb +21 -0
  43. data/samples/hello/hello_drag_and_drop.rb +29 -0
  44. data/samples/hello/hello_list_multi_selection.rb +48 -0
  45. data/samples/hello/hello_list_single_selection.rb +37 -0
  46. data/samples/hello/hello_menu_bar.rb +64 -0
  47. data/samples/hello/hello_message_box.rb +15 -0
  48. data/samples/hello/hello_pop_up_context_menu.rb +36 -0
  49. data/samples/hello/hello_tab.rb +24 -0
  50. data/samples/hello/hello_world.rb +8 -0
  51. data/vendor/swt/linux/swt.jar +0 -0
  52. data/vendor/swt/mac/swt.jar +0 -0
  53. data/vendor/swt/windows/swt.jar +0 -0
  54. metadata +48 -7
@@ -45,6 +45,8 @@ module Glimmer
45
45
  @widget_proxy = widget_proxy
46
46
  args = SWTProxy.constantify_args(args)
47
47
  @swt_layout = self.class.swt_layout_class_for(underscored_layout_name).new(*args)
48
+ @swt_layout.marginWidth = 15 if @swt_layout.respond_to?(:marginWidth)
49
+ @swt_layout.marginHeight = 15 if @swt_layout.respond_to?(:marginHeight)
48
50
  @widget_proxy.swt_widget.setLayout(@swt_layout)
49
51
  end
50
52
 
@@ -14,16 +14,22 @@ module Glimmer
14
14
  attr_reader :swt_widget
15
15
 
16
16
  def initialize(parent, style)
17
- parent = parent.swt_widget if parent.respond_to?(:swt_widget) && parent.swt_widget.is_a?(Shell)
18
- @temporary_parent = parent = Glimmer::SWT::ShellProxy.new.swt_widget if parent.nil?
19
- @swt_widget = MessageBox.new(parent, style)
17
+ if parent.nil?
18
+ @temporary_parent = parent = Glimmer::SWT::ShellProxy.new.swt_widget
19
+ end
20
+ @swt_widget = MessageBox.new(parent, style)
20
21
  end
21
22
 
22
23
  def open
23
- @swt_widget.open
24
- @temporary_parent&.dispose
24
+ @swt_widget.open.tap do |result|
25
+ @temporary_parent&.dispose
26
+ end
25
27
  end
26
28
 
29
+ def content(&block)
30
+ Glimmer::DSL::Engine.add_content(self, Glimmer::DSL::SWT::MessageBoxExpression.new, &block)
31
+ end
32
+
27
33
  # TODO refactor the following methods to put in a JavaBean mixin or somethin (perhaps contribute to OSS project too)
28
34
 
29
35
  def attribute_setter(attribute_name)
@@ -44,6 +50,18 @@ module Glimmer
44
50
 
45
51
  def get_attribute(attribute_name)
46
52
  @swt_widget.send(attribute_getter(attribute_name))
53
+ end
54
+
55
+ def method_missing(method, *args, &block)
56
+ swt_widget.send(method, *args, &block)
57
+ rescue => e
58
+ Glimmer::Config.logger.debug {"Neither MessageBoxProxy nor #{swt_widget.class.name} can handle the method ##{method}"}
59
+ super
60
+ end
61
+
62
+ def respond_to?(method, *args, &block)
63
+ super ||
64
+ swt_widget.respond_to?(method, *args, &block)
47
65
  end
48
66
  end
49
67
  end
@@ -1,21 +1,16 @@
1
1
  require 'glimmer/swt/widget_proxy'
2
+ require 'glimmer/swt/swt_proxy'
2
3
 
3
4
  module Glimmer
4
5
  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
-
6
+ class ScrolledCompositeProxy < Glimmer::SWT::WidgetProxy
16
7
  def post_initialize_child(child)
17
8
  swt_widget.content = child.swt_widget
18
9
  end
10
+
11
+ def post_add_content
12
+ swt_widget.set_min_size(swt_widget.computeSize(SWTProxy[:default], SWTProxy[:default]))
13
+ end
19
14
  end
20
15
  end
21
16
  end
@@ -106,7 +106,17 @@ module Glimmer
106
106
  def deconstruct(integer)
107
107
  constant_source_class.constants.reduce([]) do |found, c|
108
108
  constant_value = constant_source_class.const_get(c) rescue -1
109
- is_found = constant_value.is_a?(Integer) && (constant_value & integer) == constant_value
109
+ is_found = constant_value.is_a?(Integer) && (integer & constant_value) == integer
110
+ is_found ? found += [c] : found
111
+ end
112
+ end
113
+
114
+ # Reverse engineer a style integer into a symbol
115
+ # Useful for debugging
116
+ def reverse_lookup(integer)
117
+ constant_source_class.constants.reduce([]) do |found, c|
118
+ constant_value = constant_source_class.const_get(c) rescue -1
119
+ is_found = constant_value.is_a?(Integer) && integer == constant_value
110
120
  is_found ? found += [c] : found
111
121
  end
112
122
  end
@@ -85,7 +85,55 @@ module Glimmer
85
85
  }
86
86
  table_editor_widget_proxy
87
87
  end,
88
- }
88
+ },
89
+ checkbox: {
90
+ widget_value_property: :selection,
91
+ editor_gui: lambda do |args, model, property, table_proxy|
92
+ first_time = true
93
+ table_proxy.table_editor.minimumHeight = 25
94
+ checkbox(*args) {
95
+ selection model.send(property)
96
+ focus true
97
+ on_widget_selected {
98
+ table_proxy.finish_edit!
99
+ }
100
+ on_focus_lost {
101
+ table_proxy.finish_edit!
102
+ }
103
+ on_key_pressed { |key_event|
104
+ if key_event.keyCode == swt(:cr)
105
+ table_proxy.finish_edit!
106
+ elsif key_event.keyCode == swt(:esc)
107
+ table_proxy.cancel_edit!
108
+ end
109
+ }
110
+ }
111
+ end,
112
+ },
113
+ radio: {
114
+ widget_value_property: :selection,
115
+ editor_gui: lambda do |args, model, property, table_proxy|
116
+ first_time = true
117
+ table_proxy.table_editor.minimumHeight = 25
118
+ radio(*args) {
119
+ selection model.send(property)
120
+ focus true
121
+ on_widget_selected {
122
+ table_proxy.finish_edit!
123
+ }
124
+ on_focus_lost {
125
+ table_proxy.finish_edit!
126
+ }
127
+ on_key_pressed { |key_event|
128
+ if key_event.keyCode == swt(:cr)
129
+ table_proxy.finish_edit!
130
+ elsif key_event.keyCode == swt(:esc)
131
+ table_proxy.cancel_edit!
132
+ end
133
+ }
134
+ }
135
+ end,
136
+ }
89
137
  }
90
138
  end
91
139
  end
@@ -276,7 +324,7 @@ module Glimmer
276
324
  new_value = @table_editor_widget_proxy&.swt_widget&.send(widget_value_property)
277
325
  if table_item.isDisposed
278
326
  @cancel_edit.call
279
- elsif new_value && !action_taken && !@edit_in_progress && !@cancel_in_progress
327
+ elsif !new_value.nil? && !action_taken && !@edit_in_progress && !@cancel_in_progress
280
328
  action_taken = true
281
329
  @edit_in_progress = true
282
330
  if new_value == model.send(model_editing_property)
@@ -22,21 +22,39 @@ module Glimmer
22
22
  include Packages
23
23
 
24
24
  DEFAULT_STYLES = {
25
- "text" => [:border],
26
- "table" => [:virtual, :border, :full_selection],
27
- "tree" => [:virtual, :border, :h_scroll, :v_scroll],
28
- "spinner" => [:border],
29
- "styled_text" => [:border],
30
- "list" => [:border, :v_scroll],
31
- "button" => [:push],
32
- "menu_item" => [:push],
33
- "drag_source" => [:drop_copy],
34
- "drop_target" => [:drop_copy],
25
+ "arrow" => [:arrow],
26
+ "button" => [:push],
27
+ "checkbox" => [:check],
28
+ "drag_source" => [:drop_copy],
29
+ "drop_target" => [:drop_copy],
30
+ "list" => [:border, :v_scroll],
31
+ "menu_item" => [:push],
32
+ "radio" => [:radio],
33
+ "scrolled_composite" => [:border, :h_scroll, :v_scroll],
34
+ "spinner" => [:border],
35
+ "styled_text" => [:border],
36
+ "table" => [:virtual, :border, :full_selection],
37
+ "text" => [:border],
38
+ "toggle" => [:toggle],
39
+ "tree" => [:virtual, :border, :h_scroll, :v_scroll],
35
40
  }
36
41
 
37
42
  DEFAULT_INITIALIZERS = {
38
43
  "composite" => lambda do |composite|
39
- composite.setLayout(GridLayout.new)
44
+ layout = GridLayout.new
45
+ layout.marginWidth = 15
46
+ layout.marginHeight = 15
47
+ composite.layout = layout
48
+ end,
49
+ "scrolled_composite" => lambda do |scrolled_composite|
50
+ scrolled_composite.expand_horizontal = true
51
+ scrolled_composite.expand_vertical = true
52
+ end,
53
+ "shell" => lambda do |shell|
54
+ layout = FillLayout.new
55
+ layout.marginWidth = 15
56
+ layout.marginHeight = 15
57
+ shell.layout = layout
40
58
  end,
41
59
  "table" => lambda do |table|
42
60
  table.setHeaderVisible(true)
@@ -49,19 +67,47 @@ module Glimmer
49
67
  group.setLayout(GridLayout.new)
50
68
  end,
51
69
  }
70
+
71
+ class << self
72
+ def create(keyword, parent, args)
73
+ widget_proxy_class(keyword).new(keyword, parent, args)
74
+ end
75
+
76
+ def widget_proxy_class(keyword)
77
+ begin
78
+ class_name = "#{keyword.camelcase(:upper)}Proxy".to_sym
79
+ Glimmer::SWT.const_get(class_name)
80
+ rescue
81
+ Glimmer::SWT::WidgetProxy
82
+ end
83
+ end
84
+
85
+ def underscored_widget_name(swt_widget)
86
+ swt_widget.class.name.split(/::|\./).last.underscore
87
+ end
88
+ end
52
89
 
53
- attr_reader :swt_widget, :drag_source_proxy, :drop_target_proxy, :drag_source_style, :drag_source_transfer, :drop_target_transfer
90
+ attr_reader :parent_proxy, :swt_widget, :drag_source_proxy, :drop_target_proxy, :drag_source_style, :drag_source_transfer, :drop_target_transfer
54
91
 
55
92
  # Initializes a new SWT Widget
56
93
  #
57
94
  # Styles is a comma separate list of symbols representing SWT styles in lower case
58
- def initialize(underscored_widget_name, parent, args)
59
- styles, extra_options = extract_args(underscored_widget_name, args)
60
- swt_widget_class = self.class.swt_widget_class_for(underscored_widget_name)
61
- @swt_widget = swt_widget_class.new(parent.swt_widget, style(underscored_widget_name, styles), *extra_options)
62
- @swt_widget.set_data('proxy', self)
95
+ def initialize(*init_args, swt_widget: nil)
96
+ if swt_widget.nil?
97
+ underscored_widget_name, parent, args = init_args
98
+ @parent_proxy = parent
99
+ styles, extra_options = extract_args(underscored_widget_name, args)
100
+ swt_widget_class = self.class.swt_widget_class_for(underscored_widget_name)
101
+ @swt_widget = swt_widget_class.new(@parent_proxy.swt_widget, style(underscored_widget_name, styles), *extra_options)
102
+ else
103
+ @swt_widget = swt_widget
104
+ underscored_widget_name = self.class.underscored_widget_name(@swt_widget)
105
+ parent_proxy_class = self.class.widget_proxy_class(self.class.underscored_widget_name(@swt_widget.parent))
106
+ @parent_proxy = parent_proxy_class.new(swt_widget: swt_widget.parent)
107
+ end
108
+ @swt_widget.set_data('proxy', self)
63
109
  DEFAULT_INITIALIZERS[underscored_widget_name]&.call(@swt_widget)
64
- parent.post_initialize_child(self)
110
+ @parent_proxy.post_initialize_child(self)
65
111
  end
66
112
 
67
113
  # Subclasses may override to perform post initialization work on an added child
@@ -69,6 +115,11 @@ module Glimmer
69
115
  # No Op by default
70
116
  end
71
117
 
118
+ # Subclasses may override to perform post add_content work
119
+ def post_add_content
120
+ # No Op by default
121
+ end
122
+
72
123
  def extract_args(underscored_widget_name, args)
73
124
  @arg_extractor_mapping ||= {
74
125
  'menu_item' => lambda do |args|
@@ -264,6 +315,7 @@ module Glimmer
264
315
 
265
316
  # This supports widgets in and out of basic SWT
266
317
  def self.swt_widget_class_for(underscored_widget_name)
318
+ underscored_widget_name = 'button' if %w[radio checkbox toggle arrow].include?(underscored_widget_name)
267
319
  swt_widget_name = underscored_widget_name.camelcase(:upper)
268
320
  swt_widget_class = eval(swt_widget_name)
269
321
  unless swt_widget_class.ancestors.include?(org.eclipse.swt.widgets.Widget)
@@ -607,6 +659,15 @@ module Glimmer
607
659
  value
608
660
  end
609
661
  end,
662
+ :cursor => lambda do |value|
663
+ cursor_proxy = nil
664
+ if value.is_a?(CursorProxy)
665
+ cursor_proxy = value
666
+ elsif value.is_a?(Symbol) || value.is_a?(String) || value.is_a?(Integer)
667
+ cursor_proxy = CursorProxy.new(value)
668
+ end
669
+ cursor_proxy ? cursor_proxy.swt_cursor : value
670
+ end,
610
671
  :foreground => color_converter,
611
672
  :font => lambda do |value|
612
673
  if value.is_a?(Hash)
@@ -0,0 +1,121 @@
1
+ require_relative "contact_manager/contact_manager_presenter"
2
+
3
+ class ContactManager
4
+ include Glimmer
5
+
6
+ def initialize
7
+ @contact_manager_presenter = ContactManagerPresenter.new
8
+ @contact_manager_presenter.list
9
+ end
10
+
11
+ def launch
12
+ shell {
13
+ text "Contact Manager"
14
+ composite {
15
+ group {
16
+ grid_layout(2, false) {
17
+ margin_width 0
18
+ margin_height 0
19
+ }
20
+ layout_data :fill, :center, true, false
21
+ text 'Lookup Contacts'
22
+ font height: 24
23
+
24
+ label {
25
+ layout_data :right, :center, false, false
26
+ text "First &Name: "
27
+ font height: 16
28
+ }
29
+ text {
30
+ layout_data :fill, :center, true, false
31
+ text bind(@contact_manager_presenter, :first_name)
32
+ on_key_pressed {|key_event|
33
+ @contact_manager_presenter.find if key_event.keyCode == swt(:cr)
34
+ }
35
+ }
36
+
37
+ label {
38
+ layout_data :right, :center, false, false
39
+ text "&Last Name: "
40
+ font height: 16
41
+ }
42
+ text {
43
+ layout_data :fill, :center, true, false
44
+ text bind(@contact_manager_presenter, :last_name)
45
+ on_key_pressed {|key_event|
46
+ @contact_manager_presenter.find if key_event.keyCode == swt(:cr)
47
+ }
48
+ }
49
+
50
+ label {
51
+ layout_data :right, :center, false, false
52
+ text "&Email: "
53
+ font height: 16
54
+ }
55
+ text {
56
+ layout_data :fill, :center, true, false
57
+ text bind(@contact_manager_presenter, :email)
58
+ on_key_pressed {|key_event|
59
+ @contact_manager_presenter.find if key_event.keyCode == swt(:cr)
60
+ }
61
+ }
62
+
63
+ composite {
64
+ row_layout {
65
+ margin_width 0
66
+ margin_height 0
67
+ }
68
+ layout_data(:right, :center, false, false) {
69
+ horizontal_span 2
70
+ }
71
+
72
+ button {
73
+ text "&Find"
74
+ on_widget_selected { @contact_manager_presenter.find }
75
+ on_key_pressed {|key_event|
76
+ @contact_manager_presenter.find if key_event.keyCode == swt(:cr)
77
+ }
78
+ }
79
+
80
+ button {
81
+ text "&List All"
82
+ on_widget_selected { @contact_manager_presenter.list }
83
+ on_key_pressed {|key_event|
84
+ @contact_manager_presenter.list if key_event.keyCode == swt(:cr)
85
+ }
86
+ }
87
+ }
88
+ }
89
+
90
+ table(:multi) { |table_proxy|
91
+ layout_data {
92
+ horizontal_alignment :fill
93
+ vertical_alignment :fill
94
+ grab_excess_horizontal_space true
95
+ grab_excess_vertical_space true
96
+ height_hint 200
97
+ }
98
+ table_column {
99
+ text "First Name"
100
+ width 80
101
+ }
102
+ table_column {
103
+ text "Last Name"
104
+ width 80
105
+ }
106
+ table_column {
107
+ text "Email"
108
+ width 200
109
+ }
110
+ items bind(@contact_manager_presenter, :results),
111
+ column_properties(:first_name, :last_name, :email)
112
+ on_mouse_up { |event|
113
+ table_proxy.edit_table_item(event.table_item, event.column_index)
114
+ }
115
+ }
116
+ }
117
+ }.open
118
+ end
119
+ end
120
+
121
+ ContactManager.new.launch
@@ -0,0 +1,11 @@
1
+ class ContactManager
2
+ class Contact
3
+ attr_accessor :first_name, :last_name, :email
4
+
5
+ def initialize(attribute_map)
6
+ @first_name = attribute_map[:first_name]
7
+ @last_name = attribute_map[:last_name]
8
+ @email = attribute_map[:email]
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,26 @@
1
+ require_relative "contact_repository"
2
+
3
+ class ContactManager
4
+ class ContactManagerPresenter
5
+ attr_accessor :results
6
+ @@contact_attributes = [:first_name, :last_name, :email]
7
+ @@contact_attributes.each {|attribute_name| attr_accessor attribute_name}
8
+
9
+ def initialize(contact_repository = nil)
10
+ @contact_repository = contact_repository || ContactRepository.new
11
+ @results = []
12
+ end
13
+
14
+ def list
15
+ self.results = @contact_repository.find({})
16
+ end
17
+
18
+ def find
19
+ filter_map = {}
20
+ @@contact_attributes.each do |attribute_name|
21
+ filter_map[attribute_name] = self.send(attribute_name) if self.send(attribute_name)
22
+ end
23
+ self.results = @contact_repository.find(filter_map)
24
+ end
25
+ end
26
+ end