glimmer 0.7.4 → 0.8.0
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.
- checksums.yaml +4 -4
- data/{README.markdown → README.md} +210 -104
- data/VERSION +1 -1
- data/lib/glimmer/data_binding/table_items_binding.rb +1 -0
- data/lib/glimmer/data_binding/tree_items_binding.rb +30 -12
- data/lib/glimmer/dsl/swt/dialog_expression.rb +26 -0
- data/lib/glimmer/launcher.rb +18 -10
- data/lib/glimmer/rake_task.rb +3 -3
- data/lib/glimmer/scaffold.rb +208 -68
- data/lib/glimmer/swt/display_proxy.rb +14 -0
- data/lib/glimmer/swt/menu_proxy.rb +17 -0
- data/lib/glimmer/swt/shell_proxy.rb +1 -26
- data/lib/glimmer/swt/tab_item_proxy.rb +6 -0
- data/lib/glimmer/swt/tree_proxy.rb +97 -1
- data/lib/glimmer/swt/widget_listener_proxy.rb +21 -4
- data/lib/glimmer/swt/widget_proxy.rb +46 -25
- data/lib/glimmer/ui/custom_widget.rb +13 -6
- metadata +7 -36
@@ -16,6 +16,8 @@ module Glimmer
|
|
16
16
|
class DisplayProxy
|
17
17
|
include_package 'org.eclipse.swt.widgets'
|
18
18
|
|
19
|
+
OBSERVED_MENU_ITEMS = ['about', 'preferences']
|
20
|
+
|
19
21
|
class << self
|
20
22
|
# Returns singleton instance
|
21
23
|
def instance(*args)
|
@@ -52,6 +54,9 @@ module Glimmer
|
|
52
54
|
if observation_request.start_with?('on_event_')
|
53
55
|
constant_name = observation_request.sub(/^on_event_/, '')
|
54
56
|
SWTProxy.has_constant?(constant_name)
|
57
|
+
elsif observation_request.start_with?('on_')
|
58
|
+
event_name = observation_request.sub(/^on_/, '')
|
59
|
+
OBSERVED_MENU_ITEMS.include?(event_name)
|
55
60
|
else
|
56
61
|
false
|
57
62
|
end
|
@@ -61,6 +66,15 @@ module Glimmer
|
|
61
66
|
if observation_request.start_with?('on_event_')
|
62
67
|
constant_name = observation_request.sub(/^on_event_/, '')
|
63
68
|
add_swt_event_listener(constant_name, &block)
|
69
|
+
elsif observation_request.start_with?('on_')
|
70
|
+
event_name = observation_request.sub(/^on_/, '')
|
71
|
+
if OBSERVED_MENU_ITEMS.include?(event_name)
|
72
|
+
if OS.mac?
|
73
|
+
system_menu = swt_display.getSystemMenu
|
74
|
+
menu_item = system_menu.getItems.find {|menu_item| menu_item.getID == SWTProxy["ID_#{event_name.upcase}"]}
|
75
|
+
menu_item.addListener(SWTProxy[:Selection], &block)
|
76
|
+
end
|
77
|
+
end
|
64
78
|
end
|
65
79
|
end
|
66
80
|
|
@@ -79,6 +79,23 @@ module Glimmer
|
|
79
79
|
super(attribute_name)
|
80
80
|
end
|
81
81
|
end
|
82
|
+
|
83
|
+
def can_handle_observation_request?(observation_request, super_only: false)
|
84
|
+
super_result = super(observation_request)
|
85
|
+
if observation_request.start_with?('on_') && !super_result && !super_only
|
86
|
+
return menu_item_proxy.can_handle_observation_request?(observation_request)
|
87
|
+
else
|
88
|
+
super_result
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def handle_observation_request(observation_request, &block)
|
93
|
+
if can_handle_observation_request?(observation_request, super_only: true)
|
94
|
+
super
|
95
|
+
else
|
96
|
+
menu_item_proxy.handle_observation_request(observation_request, &block)
|
97
|
+
end
|
98
|
+
end
|
82
99
|
end
|
83
100
|
end
|
84
101
|
end
|
@@ -14,7 +14,6 @@ module Glimmer
|
|
14
14
|
|
15
15
|
WIDTH_MIN = 130
|
16
16
|
HEIGHT_MIN = 0
|
17
|
-
OBSERVED_MENU_ITEMS = ['about', 'preferences']
|
18
17
|
|
19
18
|
attr_reader :opened_before
|
20
19
|
alias opened_before? opened_before
|
@@ -47,7 +46,7 @@ module Glimmer
|
|
47
46
|
Thread.new do
|
48
47
|
sleep(0.25)
|
49
48
|
async_exec do
|
50
|
-
@swt_widget.setActive
|
49
|
+
@swt_widget.setActive unless @swt_widget.isDisposed
|
51
50
|
end
|
52
51
|
end
|
53
52
|
end
|
@@ -128,30 +127,6 @@ module Glimmer
|
|
128
127
|
end
|
129
128
|
end
|
130
129
|
|
131
|
-
def can_handle_observation_request?(observation_request)
|
132
|
-
result = false
|
133
|
-
if observation_request.start_with?('on_')
|
134
|
-
event_name = observation_request.sub(/^on_/, '')
|
135
|
-
result = OBSERVED_MENU_ITEMS.include?(event_name)
|
136
|
-
end
|
137
|
-
result || super
|
138
|
-
end
|
139
|
-
|
140
|
-
def handle_observation_request(observation_request, &block)
|
141
|
-
if observation_request.start_with?('on_')
|
142
|
-
event_name = observation_request.sub(/^on_/, '')
|
143
|
-
if OBSERVED_MENU_ITEMS.include?(event_name)
|
144
|
-
if OS.mac?
|
145
|
-
system_menu = DisplayProxy.instance.swt_display.getSystemMenu
|
146
|
-
menu_item = system_menu.getItems.find {|menu_item| menu_item.getID == SWTProxy["ID_#{event_name.upcase}"]}
|
147
|
-
menu_item.addListener(SWTProxy[:Selection], &block)
|
148
|
-
end
|
149
|
-
else
|
150
|
-
super
|
151
|
-
end
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
130
|
def add_observer(observer, property_name)
|
156
131
|
case property_name.to_s
|
157
132
|
when 'visible?' #TODO see if you must handle non-? version and/or move elsewhere
|
@@ -3,22 +3,118 @@ require 'glimmer/swt/widget_proxy'
|
|
3
3
|
module Glimmer
|
4
4
|
module SWT
|
5
5
|
class TreeProxy < Glimmer::SWT::WidgetProxy
|
6
|
+
include Glimmer
|
7
|
+
|
8
|
+
attr_reader :tree_editor, :tree_editor_text_proxy
|
9
|
+
attr_accessor :tree_properties
|
10
|
+
|
11
|
+
def initialize(underscored_widget_name, parent, args)
|
12
|
+
super
|
13
|
+
@tree_editor = TreeEditor.new(swt_widget)
|
14
|
+
@tree_editor.horizontalAlignment = SWTProxy[:left]
|
15
|
+
@tree_editor.grabHorizontal = true
|
16
|
+
@tree_editor.minimumHeight = 20
|
17
|
+
end
|
18
|
+
|
6
19
|
# Performs depth first search for tree items matching block condition
|
7
|
-
#
|
20
|
+
# If no condition block is passed, returns all tree items
|
21
|
+
# Returns a Java TreeItem array to easily set as selection on org.eclipse.swt.Tree if needed
|
8
22
|
def depth_first_search(&condition)
|
9
23
|
found = []
|
10
24
|
recursive_depth_first_search(swt_widget.getItems.first, found, &condition)
|
11
25
|
found.to_java(TreeItem)
|
12
26
|
end
|
27
|
+
|
28
|
+
# Returns all tree items including descendants
|
29
|
+
def all_tree_items
|
30
|
+
depth_first_search
|
31
|
+
end
|
13
32
|
|
33
|
+
def widget_property_listener_installers
|
34
|
+
super.merge({
|
35
|
+
Java::OrgEclipseSwtWidgets::Tree => {
|
36
|
+
selection: lambda do |observer|
|
37
|
+
on_widget_selected { |selection_event|
|
38
|
+
observer.call(@swt_widget.getSelection)
|
39
|
+
}
|
40
|
+
end
|
41
|
+
},
|
42
|
+
})
|
43
|
+
end
|
44
|
+
|
45
|
+
def edit_in_progress?
|
46
|
+
!!@edit_in_progress
|
47
|
+
end
|
48
|
+
|
49
|
+
def edit_selected_tree_item(before_write: nil, after_write: nil, after_cancel: nil)
|
50
|
+
edit_tree_item(swt_widget.getSelection.first, before_write: before_write, after_write: after_write, after_cancel: after_cancel)
|
51
|
+
end
|
52
|
+
|
53
|
+
def edit_tree_item(tree_item, before_write: nil, after_write: nil, after_cancel: nil)
|
54
|
+
return if tree_item.nil?
|
55
|
+
content {
|
56
|
+
@tree_editor_text_proxy = text {
|
57
|
+
focus true
|
58
|
+
text tree_item.getText
|
59
|
+
action_taken = false
|
60
|
+
cancel = lambda {
|
61
|
+
@tree_editor_text_proxy.swt_widget.dispose
|
62
|
+
@tree_editor_text_proxy = nil
|
63
|
+
after_cancel&.call
|
64
|
+
@edit_in_progress = false
|
65
|
+
}
|
66
|
+
action = lambda { |event|
|
67
|
+
if !action_taken && !@edit_in_progress
|
68
|
+
action_taken = true
|
69
|
+
@edit_in_progress = true
|
70
|
+
new_text = @tree_editor_text_proxy.swt_widget.getText
|
71
|
+
if new_text == tree_item.getText
|
72
|
+
cancel.call
|
73
|
+
else
|
74
|
+
before_write&.call
|
75
|
+
tree_item.setText(new_text)
|
76
|
+
model = tree_item.getData
|
77
|
+
model.send("#{tree_properties[:text]}=", new_text) # makes tree update itself, so must search for selected tree item again
|
78
|
+
edited_tree_item = depth_first_search { |ti| ti.getData == model }.first
|
79
|
+
swt_widget.showItem(edited_tree_item)
|
80
|
+
@tree_editor_text_proxy.swt_widget.dispose
|
81
|
+
@tree_editor_text_proxy = nil
|
82
|
+
after_write&.call(edited_tree_item)
|
83
|
+
@edit_in_progress = false
|
84
|
+
end
|
85
|
+
end
|
86
|
+
}
|
87
|
+
on_focus_lost(&action)
|
88
|
+
on_key_pressed { |key_event|
|
89
|
+
if key_event.keyCode == swt(:cr)
|
90
|
+
action.call(key_event)
|
91
|
+
elsif key_event.keyCode == swt(:esc)
|
92
|
+
cancel.call
|
93
|
+
end
|
94
|
+
}
|
95
|
+
}
|
96
|
+
@tree_editor_text_proxy.swt_widget.selectAll
|
97
|
+
}
|
98
|
+
@tree_editor.setEditor(@tree_editor_text_proxy.swt_widget, tree_item);
|
99
|
+
end
|
100
|
+
|
14
101
|
private
|
15
102
|
|
16
103
|
def recursive_depth_first_search(tree_item, found, &condition)
|
104
|
+
return if tree_item.nil?
|
17
105
|
found << tree_item if condition.nil? || condition.call(tree_item)
|
18
106
|
tree_item.getItems.each do |child_tree_item|
|
19
107
|
recursive_depth_first_search(child_tree_item, found, &condition)
|
20
108
|
end
|
21
109
|
end
|
110
|
+
|
111
|
+
def property_type_converters
|
112
|
+
super.merge({
|
113
|
+
selection: lambda do |value|
|
114
|
+
depth_first_search {|ti| ti.getData == value}
|
115
|
+
end,
|
116
|
+
})
|
117
|
+
end
|
22
118
|
end
|
23
119
|
end
|
24
120
|
end
|
@@ -5,12 +5,29 @@ module Glimmer
|
|
5
5
|
# Follows the Proxy Design Pattern
|
6
6
|
class WidgetListenerProxy
|
7
7
|
|
8
|
-
attr_reader :swt_listener
|
8
|
+
attr_reader :swt_widget, :swt_listener, :widget_add_listener_method, :swt_listener_class, :swt_listener_method, :event_type, :swt_constant
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
def initialize(swt_listener)
|
10
|
+
def initialize(swt_widget:, swt_listener:, widget_add_listener_method: nil, swt_listener_class: nil, swt_listener_method: nil, event_type: nil, swt_constant: nil)
|
11
|
+
@swt_widget = swt_widget
|
13
12
|
@swt_listener = swt_listener
|
13
|
+
@widget_add_listener_method = widget_add_listener_method
|
14
|
+
@swt_listener_class = swt_listener_class
|
15
|
+
@swt_listener_method = swt_listener_method
|
16
|
+
@event_type = event_type
|
17
|
+
@swt_constant = swt_constant
|
18
|
+
end
|
19
|
+
|
20
|
+
def widget_remove_listener_method
|
21
|
+
@widget_add_listener_method.sub('add', 'remove')
|
22
|
+
end
|
23
|
+
|
24
|
+
def unregister
|
25
|
+
# TODO consider renaming to deregister (and in Observer too)
|
26
|
+
if @event_type
|
27
|
+
@swt_widget.removeListener(@event_type, @swt_listener)
|
28
|
+
else
|
29
|
+
@swt_widget.send(widget_remove_listener_method, @swt_listener)
|
30
|
+
end
|
14
31
|
end
|
15
32
|
end
|
16
33
|
end
|
@@ -5,6 +5,8 @@ require 'glimmer/swt/font_proxy'
|
|
5
5
|
require 'glimmer/swt/swt_proxy'
|
6
6
|
require 'glimmer/data_binding/observable_widget'
|
7
7
|
|
8
|
+
# TODO refactor to make file smaller and extract sub-widget-proxies out of this
|
9
|
+
|
8
10
|
module Glimmer
|
9
11
|
module SWT
|
10
12
|
# Proxy for SWT Widget objects
|
@@ -23,6 +25,7 @@ module Glimmer
|
|
23
25
|
DEFAULT_STYLES = {
|
24
26
|
"text" => [:border],
|
25
27
|
"table" => [:border],
|
28
|
+
"tree" => [:virtual, :border, :h_scroll, :v_scroll],
|
26
29
|
"spinner" => [:border],
|
27
30
|
"styled_text" => [:border],
|
28
31
|
"list" => [:border, :v_scroll],
|
@@ -31,17 +34,17 @@ module Glimmer
|
|
31
34
|
}
|
32
35
|
|
33
36
|
DEFAULT_INITIALIZERS = {
|
34
|
-
"composite" =>
|
37
|
+
"composite" => lambda do |composite|
|
35
38
|
composite.setLayout(GridLayout.new)
|
36
39
|
end,
|
37
|
-
"table" =>
|
40
|
+
"table" => lambda do |table|
|
38
41
|
table.setHeaderVisible(true)
|
39
42
|
table.setLinesVisible(true)
|
40
43
|
end,
|
41
|
-
"table_column" =>
|
44
|
+
"table_column" => lambda do |table_column|
|
42
45
|
table_column.setWidth(80)
|
43
46
|
end,
|
44
|
-
"group" =>
|
47
|
+
"group" => lambda do |group|
|
45
48
|
group.setLayout(GridLayout.new)
|
46
49
|
end,
|
47
50
|
}
|
@@ -119,7 +122,7 @@ module Glimmer
|
|
119
122
|
def widget_property_listener_installers
|
120
123
|
@swt_widget_property_listener_installers ||= {
|
121
124
|
Java::OrgEclipseSwtWidgets::Control => {
|
122
|
-
:focus =>
|
125
|
+
:focus => lambda do |observer|
|
123
126
|
on_focus_gained { |focus_event|
|
124
127
|
observer.call(true)
|
125
128
|
}
|
@@ -129,12 +132,12 @@ module Glimmer
|
|
129
132
|
end,
|
130
133
|
},
|
131
134
|
Java::OrgEclipseSwtWidgets::Text => {
|
132
|
-
:text =>
|
135
|
+
:text => lambda do |observer|
|
133
136
|
on_modify_text { |modify_event|
|
134
137
|
observer.call(@swt_widget.getText)
|
135
138
|
}
|
136
139
|
end,
|
137
|
-
:caret_position =>
|
140
|
+
:caret_position => lambda do |observer|
|
138
141
|
on_event_keydown { |event|
|
139
142
|
observer.call(@swt_widget.getCaretPosition)
|
140
143
|
}
|
@@ -148,7 +151,21 @@ module Glimmer
|
|
148
151
|
observer.call(@swt_widget.getCaretPosition)
|
149
152
|
}
|
150
153
|
end,
|
151
|
-
:
|
154
|
+
:selection => lambda do |observer|
|
155
|
+
on_event_keydown { |event|
|
156
|
+
observer.call(@swt_widget.getSelection)
|
157
|
+
}
|
158
|
+
on_event_keyup { |event|
|
159
|
+
observer.call(@swt_widget.getSelection)
|
160
|
+
}
|
161
|
+
on_event_mousedown { |event|
|
162
|
+
observer.call(@swt_widget.getSelection)
|
163
|
+
}
|
164
|
+
on_event_mouseup { |event|
|
165
|
+
observer.call(@swt_widget.getSelection)
|
166
|
+
}
|
167
|
+
end,
|
168
|
+
:selection_count => lambda do |observer|
|
152
169
|
on_event_keydown { |event|
|
153
170
|
observer.call(@swt_widget.getSelectionCount)
|
154
171
|
}
|
@@ -162,7 +179,7 @@ module Glimmer
|
|
162
179
|
observer.call(@swt_widget.getSelectionCount)
|
163
180
|
}
|
164
181
|
end,
|
165
|
-
:top_index =>
|
182
|
+
:top_index => lambda do |observer|
|
166
183
|
@last_top_index = @swt_widget.getTopIndex
|
167
184
|
on_paint_control { |event|
|
168
185
|
if @swt_widget.getTopIndex != @last_top_index
|
@@ -173,33 +190,33 @@ module Glimmer
|
|
173
190
|
end,
|
174
191
|
},
|
175
192
|
Java::OrgEclipseSwtCustom::StyledText => {
|
176
|
-
:text =>
|
193
|
+
:text => lambda do |observer|
|
177
194
|
on_modify_text { |modify_event|
|
178
195
|
observer.call(@swt_widget.getText)
|
179
196
|
}
|
180
197
|
end,
|
181
198
|
},
|
182
199
|
Java::OrgEclipseSwtWidgets::Button => {
|
183
|
-
:selection =>
|
200
|
+
:selection => lambda do |observer|
|
184
201
|
on_widget_selected { |selection_event|
|
185
202
|
observer.call(@swt_widget.getSelection)
|
186
203
|
}
|
187
204
|
end
|
188
205
|
},
|
189
206
|
Java::OrgEclipseSwtWidgets::MenuItem => {
|
190
|
-
:selection =>
|
207
|
+
:selection => lambda do |observer|
|
191
208
|
on_widget_selected { |selection_event|
|
192
209
|
observer.call(@swt_widget.getSelection)
|
193
210
|
}
|
194
211
|
end
|
195
212
|
},
|
196
213
|
Java::OrgEclipseSwtWidgets::Spinner => {
|
197
|
-
:selection =>
|
214
|
+
:selection => lambda do |observer|
|
198
215
|
on_widget_selected { |selection_event|
|
199
216
|
observer.call(@swt_widget.getSelection)
|
200
217
|
}
|
201
218
|
end
|
202
|
-
}
|
219
|
+
},
|
203
220
|
}
|
204
221
|
end
|
205
222
|
|
@@ -321,10 +338,12 @@ module Glimmer
|
|
321
338
|
end
|
322
339
|
|
323
340
|
def add_listener(underscored_listener_name, &block)
|
324
|
-
widget_add_listener_method, listener_class, listener_method = self.class.find_listener(@swt_widget.getClass, underscored_listener_name)
|
325
|
-
|
341
|
+
widget_add_listener_method, listener_class, listener_method = self.class.find_listener(@swt_widget.getClass, underscored_listener_name)
|
342
|
+
widget_listener_proxy = nil
|
343
|
+
safe_block = lambda { |event| block.call(event) unless @swt_widget.isDisposed }
|
344
|
+
listener = listener_class.new(listener_method => safe_block)
|
326
345
|
@swt_widget.send(widget_add_listener_method, listener)
|
327
|
-
WidgetListenerProxy.new(listener)
|
346
|
+
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)
|
328
347
|
end
|
329
348
|
|
330
349
|
# Looks through SWT class add***Listener methods till it finds one for which
|
@@ -375,8 +394,10 @@ module Glimmer
|
|
375
394
|
|
376
395
|
def add_swt_event_listener(swt_constant, &block)
|
377
396
|
event_type = SWTProxy[swt_constant]
|
378
|
-
|
379
|
-
|
397
|
+
widget_listener_proxy = nil
|
398
|
+
safe_block = lambda { |event| block.call(event) unless @swt_widget.isDisposed }
|
399
|
+
@swt_widget.addListener(event_type, &safe_block)
|
400
|
+
widget_listener_proxy = WidgetListenerProxy.new(swt_widget: @swt_widget, swt_listener: @swt_widget.getListeners(event_type).last, event_type: event_type, swt_constant: swt_constant)
|
380
401
|
end
|
381
402
|
|
382
403
|
def widget_custom_attribute_mapping
|
@@ -409,7 +430,7 @@ module Glimmer
|
|
409
430
|
end
|
410
431
|
|
411
432
|
def property_type_converters
|
412
|
-
color_converter =
|
433
|
+
color_converter = lambda do |value|
|
413
434
|
if value.is_a?(Symbol) || value.is_a?(String)
|
414
435
|
ColorProxy.new(value).swt_color
|
415
436
|
else
|
@@ -419,7 +440,7 @@ module Glimmer
|
|
419
440
|
# TODO consider detecting type on widget method and automatically invoking right converter (e.g. :to_s for String, :to_i for Integer)
|
420
441
|
@property_type_converters ||= {
|
421
442
|
:background => color_converter,
|
422
|
-
:background_image =>
|
443
|
+
:background_image => lambda do |value|
|
423
444
|
if value.is_a?(String)
|
424
445
|
if value.start_with?('uri:classloader')
|
425
446
|
value = value.sub(/^uri\:classloader\:\//, '')
|
@@ -440,7 +461,7 @@ module Glimmer
|
|
440
461
|
end
|
441
462
|
end,
|
442
463
|
:foreground => color_converter,
|
443
|
-
:font =>
|
464
|
+
:font => lambda do |value|
|
444
465
|
if value.is_a?(Hash)
|
445
466
|
font_properties = value
|
446
467
|
FontProxy.new(self, font_properties).swt_font
|
@@ -448,17 +469,17 @@ module Glimmer
|
|
448
469
|
value
|
449
470
|
end
|
450
471
|
end,
|
451
|
-
:items =>
|
472
|
+
:items => lambda do |value|
|
452
473
|
value.to_java :string
|
453
474
|
end,
|
454
|
-
:text =>
|
475
|
+
:text => lambda do |value|
|
455
476
|
if swt_widget.is_a?(Browser)
|
456
477
|
value.to_s
|
457
478
|
else
|
458
479
|
value.to_s
|
459
480
|
end
|
460
481
|
end,
|
461
|
-
:visible =>
|
482
|
+
:visible => lambda do |value|
|
462
483
|
!!value
|
463
484
|
end,
|
464
485
|
}
|