glimmer-dsl-swt 0.2.4 → 0.5.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.md +11 -4
- data/VERSION +1 -1
- data/lib/ext/glimmer/config.rb +88 -0
- data/lib/glimmer-dsl-swt.rb +2 -1
- data/lib/glimmer/data_binding/table_items_binding.rb +7 -3
- data/lib/glimmer/data_binding/tree_items_binding.rb +4 -6
- data/lib/glimmer/dsl/swt/custom_widget_expression.rb +1 -0
- data/lib/glimmer/dsl/swt/exec_expression.rb +1 -1
- data/lib/glimmer/dsl/swt/tab_item_expression.rb +1 -1
- data/lib/glimmer/dsl/swt/widget_listener_expression.rb +5 -5
- data/lib/glimmer/package.rb +5 -3
- data/lib/glimmer/rake_task.rb +68 -28
- data/lib/glimmer/scaffold.rb +4 -6
- data/lib/glimmer/swt/color_proxy.rb +11 -0
- data/lib/glimmer/swt/display_proxy.rb +13 -15
- data/lib/glimmer/swt/layout_data_proxy.rb +1 -1
- data/lib/glimmer/swt/layout_proxy.rb +2 -2
- data/lib/glimmer/swt/message_box_proxy.rb +2 -0
- data/lib/glimmer/swt/shell_proxy.rb +10 -9
- data/lib/glimmer/swt/style_constantizable.rb +2 -2
- data/lib/glimmer/swt/table_column_proxy.rb +6 -2
- data/lib/glimmer/swt/table_proxy.rb +169 -78
- data/lib/glimmer/swt/widget_proxy.rb +52 -32
- data/lib/glimmer/ui/custom_shell.rb +2 -1
- data/lib/glimmer/ui/custom_widget.rb +28 -18
- metadata +51 -31
@@ -33,26 +33,24 @@ module Glimmer
|
|
33
33
|
|
34
34
|
def initialize(*args)
|
35
35
|
@swt_display = Display.new(*args)
|
36
|
+
@swt_display.set_data('proxy', self)
|
36
37
|
end
|
37
38
|
|
38
|
-
def
|
39
|
-
|
39
|
+
def method_missing(method, *args, &block)
|
40
|
+
swt_display.send(method, *args, &block)
|
41
|
+
rescue => e
|
42
|
+
Glimmer::Config.logger.debug {"Neither DisplayProxy nor #{swt_display.class.name} can handle the method ##{method}"}
|
43
|
+
super
|
40
44
|
end
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
@swt_display.asyncExec(&block)
|
45
|
-
end
|
46
|
-
|
47
|
-
# Executes code block synchronously with respect to SWT UI thread
|
48
|
-
def sync_exec(&block)
|
49
|
-
@swt_display.syncExec(&block)
|
45
|
+
|
46
|
+
def respond_to?(method, *args, &block)
|
47
|
+
super || swt_display.respond_to?(method, *args, &block)
|
50
48
|
end
|
51
49
|
|
52
50
|
def can_handle_observation_request?(observation_request)
|
53
51
|
observation_request = observation_request.to_s
|
54
|
-
if observation_request.start_with?('
|
55
|
-
constant_name = observation_request.sub(/^
|
52
|
+
if observation_request.start_with?('on_swt_')
|
53
|
+
constant_name = observation_request.sub(/^on_swt_/, '')
|
56
54
|
SWTProxy.has_constant?(constant_name)
|
57
55
|
elsif observation_request.start_with?('on_')
|
58
56
|
event_name = observation_request.sub(/^on_/, '')
|
@@ -63,8 +61,8 @@ module Glimmer
|
|
63
61
|
end
|
64
62
|
|
65
63
|
def handle_observation_request(observation_request, &block)
|
66
|
-
if observation_request.start_with?('
|
67
|
-
constant_name = observation_request.sub(/^
|
64
|
+
if observation_request.start_with?('on_swt_')
|
65
|
+
constant_name = observation_request.sub(/^on_swt_/, '')
|
68
66
|
add_swt_event_listener(constant_name, &block)
|
69
67
|
elsif observation_request.start_with?('on_')
|
70
68
|
event_name = observation_request.sub(/^on_/, '')
|
@@ -31,7 +31,7 @@ module Glimmer
|
|
31
31
|
begin
|
32
32
|
@swt_layout_data = swt_layout_data_class.new(*args)
|
33
33
|
rescue => e
|
34
|
-
Glimmer::Config.logger
|
34
|
+
Glimmer::Config.logger.debug {"#{e.message}\n#{e.backtrace.join("\n")}"}
|
35
35
|
@swt_layout_data = args.first if args.count == 1
|
36
36
|
end
|
37
37
|
@widget_proxy.swt_widget.setLayoutData(@swt_layout_data)
|
@@ -34,8 +34,8 @@ module Glimmer
|
|
34
34
|
end
|
35
35
|
swt_layout_class
|
36
36
|
rescue => e
|
37
|
-
Glimmer::Config.logger
|
38
|
-
# Glimmer::Config.logger
|
37
|
+
Glimmer::Config.logger.debug {e.message}
|
38
|
+
# Glimmer::Config.logger.debug {"#{e.message}\n#{e.backtrace.join("\n")}"}
|
39
39
|
raise e
|
40
40
|
end
|
41
41
|
end
|
@@ -15,11 +15,13 @@ module Glimmer
|
|
15
15
|
|
16
16
|
def initialize(parent, style)
|
17
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?
|
18
19
|
@swt_widget = MessageBox.new(parent, style)
|
19
20
|
end
|
20
21
|
|
21
22
|
def open
|
22
23
|
@swt_widget.open
|
24
|
+
@temporary_parent&.dispose
|
23
25
|
end
|
24
26
|
|
25
27
|
# TODO refactor the following methods to put in a JavaBean mixin or somethin (perhaps contribute to OSS project too)
|
@@ -40,9 +40,10 @@ module Glimmer
|
|
40
40
|
end
|
41
41
|
args = args.compact
|
42
42
|
@swt_widget = Shell.new(*args)
|
43
|
+
@swt_widget.set_data('proxy', self)
|
43
44
|
@swt_widget.setLayout(FillLayout.new)
|
44
45
|
@swt_widget.setMinimumSize(WIDTH_MIN, HEIGHT_MIN)
|
45
|
-
|
46
|
+
on_swt_show do
|
46
47
|
Thread.new do
|
47
48
|
sleep(0.25)
|
48
49
|
async_exec do
|
@@ -83,10 +84,6 @@ module Glimmer
|
|
83
84
|
@swt_widget.setVisible(false)
|
84
85
|
end
|
85
86
|
|
86
|
-
def close
|
87
|
-
@swt_widget.close
|
88
|
-
end
|
89
|
-
|
90
87
|
def visible?
|
91
88
|
@swt_widget.isDisposed ? false : @swt_widget.isVisible
|
92
89
|
end
|
@@ -130,7 +127,11 @@ module Glimmer
|
|
130
127
|
# This method is not needed except in rare circumstances where there is a need to start the SWT Event Loop before opening the shell.
|
131
128
|
def start_event_loop
|
132
129
|
until @swt_widget.isDisposed
|
133
|
-
|
130
|
+
begin
|
131
|
+
@display.sleep unless @display.readAndDispatch
|
132
|
+
rescue => e
|
133
|
+
Glimmer::Config.logger.debug {e.full_message}
|
134
|
+
end
|
134
135
|
end
|
135
136
|
end
|
136
137
|
|
@@ -140,9 +141,9 @@ module Glimmer
|
|
140
141
|
visibility_notifier = proc do
|
141
142
|
observer.call(visible?)
|
142
143
|
end
|
143
|
-
|
144
|
-
|
145
|
-
|
144
|
+
on_swt_show(&visibility_notifier)
|
145
|
+
on_swt_hide(&visibility_notifier)
|
146
|
+
on_swt_close(&visibility_notifier)
|
146
147
|
else
|
147
148
|
super
|
148
149
|
end
|
@@ -61,12 +61,12 @@ module Glimmer
|
|
61
61
|
negative ? ~bit_value : bit_value
|
62
62
|
rescue => e
|
63
63
|
begin
|
64
|
-
# Glimmer::Config.logger
|
64
|
+
# Glimmer::Config.logger.debug {e.full_message}
|
65
65
|
alternative_swt_constant_symbol = constant_source_class.constants.find {|c| c.to_s.upcase == swt_constant_symbol.to_s.upcase}
|
66
66
|
bit_value = constant_source_class.const_get(alternative_swt_constant_symbol)
|
67
67
|
negative ? ~bit_value : bit_value
|
68
68
|
rescue => e
|
69
|
-
# Glimmer::Config.logger
|
69
|
+
# Glimmer::Config.logger.debug {e.full_message}
|
70
70
|
bit_value = extra_styles[swt_constant_symbol]
|
71
71
|
if bit_value
|
72
72
|
negative ? ~bit_value : bit_value
|
@@ -3,7 +3,7 @@ require 'glimmer/swt/widget_proxy'
|
|
3
3
|
module Glimmer
|
4
4
|
module SWT
|
5
5
|
class TableColumnProxy < Glimmer::SWT::WidgetProxy
|
6
|
-
attr_reader :no_sort, :sort_property
|
6
|
+
attr_reader :no_sort, :sort_property, :editor
|
7
7
|
alias no_sort? no_sort
|
8
8
|
attr_accessor :sort_block, :sort_by_block
|
9
9
|
|
@@ -16,7 +16,11 @@ module Glimmer
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def sort_property=(args)
|
19
|
-
@sort_property = args.
|
19
|
+
@sort_property = args unless args.empty?
|
20
|
+
end
|
21
|
+
|
22
|
+
def editor=(args)
|
23
|
+
@editor = args
|
20
24
|
end
|
21
25
|
|
22
26
|
end
|
@@ -23,8 +23,8 @@ module Glimmer
|
|
23
23
|
def find_table_item_and_column_index
|
24
24
|
{}.tap do |result|
|
25
25
|
if respond_to?(:x) && respond_to?(:y)
|
26
|
-
result[:table_item] = widget.
|
27
|
-
result[:column_index] = widget.
|
26
|
+
result[:table_item] = widget.items.detect do |ti|
|
27
|
+
result[:column_index] = widget.column_count.times.to_a.detect do |ci|
|
28
28
|
ti.getBounds(ci).contains(x, y)
|
29
29
|
end
|
30
30
|
end
|
@@ -33,7 +33,61 @@ module Glimmer
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
-
|
36
|
+
class << self
|
37
|
+
def editors
|
38
|
+
@editors ||= {
|
39
|
+
text: {
|
40
|
+
widget_value_property: :text,
|
41
|
+
editor_gui: lambda do |args, model, property, table_proxy|
|
42
|
+
table_proxy.table_editor.minimumHeight = 20
|
43
|
+
table_editor_widget_proxy = text(*args) {
|
44
|
+
text model.send(property)
|
45
|
+
focus true
|
46
|
+
on_focus_lost {
|
47
|
+
table_proxy.finish_edit!
|
48
|
+
}
|
49
|
+
on_key_pressed { |key_event|
|
50
|
+
if key_event.keyCode == swt(:cr)
|
51
|
+
table_proxy.finish_edit!
|
52
|
+
elsif key_event.keyCode == swt(:esc)
|
53
|
+
table_proxy.cancel_edit!
|
54
|
+
end
|
55
|
+
}
|
56
|
+
}
|
57
|
+
table_editor_widget_proxy.swt_widget.selectAll
|
58
|
+
table_editor_widget_proxy
|
59
|
+
end,
|
60
|
+
},
|
61
|
+
combo: {
|
62
|
+
widget_value_property: :text,
|
63
|
+
editor_gui: lambda do |args, model, property, table_proxy|
|
64
|
+
table_proxy.table_editor.minimumHeight = 25
|
65
|
+
table_editor_widget_proxy = combo(*args) {
|
66
|
+
items model.send("#{property}_options")
|
67
|
+
text model.send(property)
|
68
|
+
focus true
|
69
|
+
on_focus_lost {
|
70
|
+
table_proxy.finish_edit!
|
71
|
+
}
|
72
|
+
on_key_pressed { |key_event|
|
73
|
+
if key_event.keyCode == swt(:cr)
|
74
|
+
table_proxy.finish_edit!
|
75
|
+
elsif key_event.keyCode == swt(:esc)
|
76
|
+
table_proxy.cancel_edit!
|
77
|
+
end
|
78
|
+
}
|
79
|
+
on_widget_selected {
|
80
|
+
table_proxy.finish_edit!
|
81
|
+
}
|
82
|
+
}
|
83
|
+
table_editor_widget_proxy
|
84
|
+
end,
|
85
|
+
}
|
86
|
+
}
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
attr_reader :table_editor, :table_editor_widget_proxy, :sort_property, :sort_direction, :sort_block, :sort_type, :sort_by_block, :additional_sort_properties, :editor
|
37
91
|
attr_accessor :column_properties
|
38
92
|
|
39
93
|
def initialize(underscored_widget_name, parent, args)
|
@@ -46,13 +100,30 @@ module Glimmer
|
|
46
100
|
|
47
101
|
def model_binding
|
48
102
|
swt_widget.data
|
49
|
-
end
|
103
|
+
end
|
50
104
|
|
51
105
|
def sort_by_column(table_column_proxy)
|
52
106
|
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
|
-
|
107
|
+
new_sort_property = table_column_proxy.sort_property || [column_properties[index]]
|
108
|
+
if new_sort_property.size == 1 && !additional_sort_properties.to_a.empty?
|
109
|
+
selected_additional_sort_properties = additional_sort_properties.clone
|
110
|
+
if selected_additional_sort_properties.include?(new_sort_property.first)
|
111
|
+
selected_additional_sort_properties.delete(new_sort_property.first)
|
112
|
+
new_sort_property += selected_additional_sort_properties
|
113
|
+
else
|
114
|
+
new_sort_property += additional_sort_properties
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
@sort_direction = @sort_direction.nil? || @sort_property != new_sort_property || @sort_direction == :descending ? :ascending : :descending
|
119
|
+
swt_widget.sort_direction = @sort_direction == :ascending ? SWTProxy[:up] : SWTProxy[:down]
|
120
|
+
|
55
121
|
@sort_property = new_sort_property
|
122
|
+
swt_widget.sort_column = table_column_proxy.swt_widget
|
123
|
+
|
124
|
+
@sort_by_block = nil
|
125
|
+
@sort_block = nil
|
126
|
+
@sort_type = nil
|
56
127
|
if table_column_proxy.sort_by_block
|
57
128
|
@sort_by_block = table_column_proxy.sort_by_block
|
58
129
|
elsif table_column_proxy.sort_block
|
@@ -64,43 +135,51 @@ module Glimmer
|
|
64
135
|
end
|
65
136
|
|
66
137
|
def detect_sort_type
|
67
|
-
@sort_type = String
|
138
|
+
@sort_type = sort_property.size.times.map { String }
|
68
139
|
array = model_binding.evaluate_property
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
140
|
+
sort_property.each_with_index do |a_sort_property, i|
|
141
|
+
values = array.map { |object| object.send(a_sort_property) }
|
142
|
+
value_classes = values.map(&:class).uniq
|
143
|
+
if value_classes.size == 1
|
144
|
+
@sort_type[i] = value_classes.first
|
145
|
+
elsif value_classes.include?(Integer)
|
146
|
+
@sort_type[i] = Integer
|
147
|
+
elsif value_classes.include?(Float)
|
148
|
+
@sort_type[i] = Float
|
149
|
+
end
|
77
150
|
end
|
78
151
|
end
|
79
152
|
|
153
|
+
def additional_sort_properties=(args)
|
154
|
+
@additional_sort_properties = args unless args.empty?
|
155
|
+
end
|
156
|
+
|
157
|
+
def editor=(args)
|
158
|
+
@editor = args
|
159
|
+
end
|
160
|
+
|
80
161
|
def sort
|
81
162
|
return unless sort_property && (sort_type || sort_block || sort_by_block)
|
82
163
|
array = model_binding.evaluate_property
|
83
164
|
# Converting value to_s first to handle nil cases. Should work with numeric, boolean, and date fields
|
84
165
|
if sort_block
|
85
|
-
sorted_array = array.sort
|
86
|
-
|
87
|
-
|
88
|
-
sort_block.call(value1, value2)
|
89
|
-
end
|
166
|
+
sorted_array = array.sort(&sort_block)
|
167
|
+
elsif sort_by_block
|
168
|
+
sorted_array = array.sort_by(&sort_by_block)
|
90
169
|
else
|
91
170
|
sorted_array = array.sort_by do |object|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
171
|
+
sort_property.each_with_index.map do |a_sort_property, i|
|
172
|
+
value = object.send(a_sort_property)
|
173
|
+
# handle nil and difficult to compare types gracefully
|
174
|
+
if sort_type[i] == Integer
|
175
|
+
value = value.to_i
|
176
|
+
elsif sort_type[i] == Float
|
177
|
+
value = value.to_f
|
178
|
+
elsif sort_type[i] == String
|
179
|
+
value = value.to_s
|
180
|
+
end
|
181
|
+
value
|
102
182
|
end
|
103
|
-
value
|
104
183
|
end
|
105
184
|
end
|
106
185
|
sorted_array = sorted_array.reverse if sort_direction == :descending
|
@@ -131,6 +210,14 @@ module Glimmer
|
|
131
210
|
})
|
132
211
|
end
|
133
212
|
|
213
|
+
def post_initialize_child(table_column_proxy)
|
214
|
+
table_column_proxies << table_column_proxy
|
215
|
+
end
|
216
|
+
|
217
|
+
def table_column_proxies
|
218
|
+
@table_column_proxies ||= []
|
219
|
+
end
|
220
|
+
|
134
221
|
# Indicates if table is in edit mode, thus displaying a text widget for a table item cell
|
135
222
|
def edit_mode?
|
136
223
|
!!@edit_mode
|
@@ -156,58 +243,62 @@ module Glimmer
|
|
156
243
|
|
157
244
|
def edit_table_item(table_item, column_index, before_write: nil, after_write: nil, after_cancel: nil)
|
158
245
|
return if table_item.nil?
|
246
|
+
model = table_item.data
|
247
|
+
property = column_properties[column_index]
|
159
248
|
@cancel_edit&.call if @edit_mode
|
249
|
+
action_taken = false
|
160
250
|
@edit_mode = true
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
251
|
+
|
252
|
+
editor_config = table_column_proxies[column_index].editor || editor
|
253
|
+
editor_config = editor_config.to_a
|
254
|
+
editor_widget_options = editor_config.last.is_a?(Hash) ? editor_config.last : {}
|
255
|
+
editor_widget_arg_last_index = editor_config.last.is_a?(Hash) ? -2 : -1
|
256
|
+
editor_widget = editor_config[0] || :text
|
257
|
+
editor_widget_args = editor_config[1..editor_widget_arg_last_index]
|
258
|
+
model_editing_property = editor_widget_options[:property] || property
|
259
|
+
widget_value_property = TableProxy::editors[editor_widget][:widget_value_property]
|
260
|
+
|
261
|
+
@cancel_edit = lambda do |event=nil|
|
262
|
+
@cancel_in_progress = true
|
263
|
+
@table_editor_widget_proxy&.swt_widget&.dispose
|
264
|
+
@table_editor_widget_proxy = nil
|
265
|
+
after_cancel&.call
|
266
|
+
@edit_in_progress = false
|
267
|
+
@cancel_in_progress = false
|
268
|
+
@cancel_edit = nil
|
269
|
+
@edit_mode = false
|
270
|
+
end
|
271
|
+
|
272
|
+
@finish_edit = lambda do |event=nil|
|
273
|
+
new_value = @table_editor_widget_proxy&.swt_widget&.send(widget_value_property)
|
274
|
+
if table_item.isDisposed
|
275
|
+
@cancel_edit.call
|
276
|
+
elsif new_value && !action_taken && !@edit_in_progress && !@cancel_in_progress
|
277
|
+
action_taken = true
|
278
|
+
@edit_in_progress = true
|
279
|
+
if new_value == model.send(model_editing_property)
|
280
|
+
@cancel_edit.call
|
281
|
+
else
|
282
|
+
before_write&.call
|
283
|
+
model.send("#{model_editing_property}=", new_value) # makes table update itself, so must search for selected table item again
|
284
|
+
# Table refresh happens here because of model update triggering observers, so must retrieve table item again
|
285
|
+
edited_table_item = search { |ti| ti.getData == model }.first
|
286
|
+
swt_widget.showItem(edited_table_item)
|
287
|
+
@table_editor_widget_proxy&.swt_widget&.dispose
|
288
|
+
@table_editor_widget_proxy = nil
|
289
|
+
after_write&.call(edited_table_item)
|
171
290
|
@edit_in_progress = false
|
172
|
-
@cancel_in_progress = false
|
173
|
-
@cancel_edit = nil
|
174
|
-
@edit_mode = false
|
175
291
|
end
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
@edit_in_progress = true
|
182
|
-
new_text = @table_editor_text_proxy.swt_widget.getText
|
183
|
-
if new_text == table_item.getText(column_index)
|
184
|
-
@cancel_edit.call
|
185
|
-
else
|
186
|
-
before_write&.call
|
187
|
-
table_item.setText(column_index, new_text)
|
188
|
-
model = table_item.getData
|
189
|
-
model.send("#{column_properties[column_index]}=", new_text) # makes table update itself, so must search for selected table item again
|
190
|
-
edited_table_item = search { |ti| ti.getData == model }.first
|
191
|
-
swt_widget.showItem(edited_table_item)
|
192
|
-
@table_editor_text_proxy&.swt_widget&.dispose
|
193
|
-
@table_editor_text_proxy = nil
|
194
|
-
after_write&.call(edited_table_item)
|
195
|
-
@edit_in_progress = false
|
196
|
-
end
|
197
|
-
end
|
198
|
-
end
|
199
|
-
on_focus_lost(&@finish_edit)
|
200
|
-
on_key_pressed { |key_event|
|
201
|
-
if key_event.keyCode == swt(:cr)
|
202
|
-
@finish_edit.call(key_event)
|
203
|
-
elsif key_event.keyCode == swt(:esc)
|
204
|
-
@cancel_edit.call
|
205
|
-
end
|
206
|
-
}
|
207
|
-
}
|
208
|
-
@table_editor_text_proxy.swt_widget.selectAll
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
content {
|
296
|
+
@table_editor_widget_proxy = TableProxy::editors[editor_widget][:editor_gui].call(editor_widget_args, model, model_editing_property, self)
|
209
297
|
}
|
210
|
-
@table_editor.setEditor(@
|
298
|
+
@table_editor.setEditor(@table_editor_widget_proxy.swt_widget, table_item, column_index)
|
299
|
+
rescue => e
|
300
|
+
Glimmer::Config.logger.error {e.full_message}
|
301
|
+
raise e
|
211
302
|
end
|
212
303
|
|
213
304
|
def add_listener(underscored_listener_name, &block)
|