glimmer-dsl-swt 4.18.2.2 → 4.18.3.1
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/CHANGELOG.md +53 -0
- data/README.md +213 -32
- data/VERSION +1 -1
- data/glimmer-dsl-swt.gemspec +19 -6
- data/lib/ext/glimmer/config.rb +24 -7
- data/lib/glimmer/data_binding/widget_binding.rb +14 -4
- data/lib/glimmer/dsl/swt/color_expression.rb +4 -4
- data/lib/glimmer/dsl/swt/data_binding_expression.rb +3 -3
- data/lib/glimmer/dsl/swt/display_expression.rb +3 -3
- data/lib/glimmer/dsl/swt/dsl.rb +1 -0
- data/lib/glimmer/dsl/swt/multiply_expression.rb +53 -0
- data/lib/glimmer/dsl/swt/property_expression.rb +4 -2
- data/lib/glimmer/dsl/swt/shape_expression.rb +2 -4
- data/lib/glimmer/dsl/swt/transform_expression.rb +55 -0
- data/lib/glimmer/dsl/swt/widget_expression.rb +2 -1
- data/lib/glimmer/rake_task/scaffold.rb +4 -3
- data/lib/glimmer/swt/color_proxy.rb +28 -6
- data/lib/glimmer/swt/custom/drawable.rb +8 -0
- data/lib/glimmer/swt/custom/shape.rb +66 -26
- data/lib/glimmer/swt/directory_dialog_proxy.rb +3 -3
- data/lib/glimmer/swt/display_proxy.rb +26 -5
- data/lib/glimmer/swt/file_dialog_proxy.rb +3 -3
- data/lib/glimmer/swt/layout_data_proxy.rb +3 -3
- data/lib/glimmer/swt/shell_proxy.rb +17 -5
- data/lib/glimmer/swt/transform_proxy.rb +109 -0
- data/lib/glimmer/swt/widget_listener_proxy.rb +14 -5
- data/lib/glimmer/swt/widget_proxy.rb +35 -26
- data/lib/glimmer/ui/custom_shell.rb +17 -3
- data/lib/glimmer/ui/custom_widget.rb +66 -45
- data/samples/elaborate/meta_sample.rb +102 -24
- data/samples/elaborate/tetris.rb +137 -0
- data/samples/elaborate/tetris/model/block.rb +48 -0
- data/samples/elaborate/tetris/model/game.rb +226 -0
- data/samples/elaborate/tetris/model/tetromino.rb +316 -0
- data/samples/elaborate/tetris/view/block.rb +70 -0
- data/samples/elaborate/tetris/view/game_over_dialog.rb +68 -0
- data/samples/elaborate/tetris/view/playfield.rb +56 -0
- data/samples/elaborate/tetris/view/score_lane.rb +87 -0
- data/samples/elaborate/tetris/view/tetris_menu_bar.rb +72 -0
- data/samples/elaborate/tic_tac_toe.rb +4 -4
- data/samples/hello/hello_canvas_transform.rb +40 -0
- data/samples/hello/hello_link.rb +1 -1
- metadata +17 -4
@@ -26,10 +26,12 @@ module Glimmer
|
|
26
26
|
# Follows the Proxy Design Pattern
|
27
27
|
class WidgetListenerProxy
|
28
28
|
|
29
|
-
attr_reader :swt_widget, :swt_listener, :widget_add_listener_method, :swt_listener_class, :swt_listener_method, :event_type, :swt_constant
|
29
|
+
attr_reader :swt_widget, :swt_display, :swt_listener, :widget_add_listener_method, :swt_listener_class, :swt_listener_method, :event_type, :swt_constant
|
30
30
|
|
31
|
-
def initialize(swt_widget
|
31
|
+
def initialize(swt_widget:nil, swt_display:nil, swt_listener:, widget_add_listener_method: nil, swt_listener_class: nil, swt_listener_method: nil, event_type: nil, swt_constant: nil, filter: false)
|
32
32
|
@swt_widget = swt_widget
|
33
|
+
@swt_display = swt_display
|
34
|
+
@filter = filter
|
33
35
|
@swt_listener = swt_listener
|
34
36
|
@widget_add_listener_method = widget_add_listener_method
|
35
37
|
@swt_listener_class = swt_listener_class
|
@@ -42,14 +44,21 @@ module Glimmer
|
|
42
44
|
@widget_add_listener_method.sub('add', 'remove')
|
43
45
|
end
|
44
46
|
|
45
|
-
def
|
46
|
-
|
47
|
-
if @
|
47
|
+
def deregister
|
48
|
+
return if @swt_widget&.is_disposed || @swt_display&.is_disposed
|
49
|
+
if @swt_display
|
50
|
+
if @filter
|
51
|
+
@swt_display.removeFilter(@event_type, @swt_listener)
|
52
|
+
else
|
53
|
+
@swt_display.removeListener(@event_type, @swt_listener)
|
54
|
+
end
|
55
|
+
elsif @event_type
|
48
56
|
@swt_widget.removeListener(@event_type, @swt_listener)
|
49
57
|
else
|
50
58
|
@swt_widget.send(widget_remove_listener_method, @swt_listener)
|
51
59
|
end
|
52
60
|
end
|
61
|
+
alias unregister deregister # TODO consider dropping unregister (and in Observer too)
|
53
62
|
end
|
54
63
|
end
|
55
64
|
end
|
@@ -74,12 +74,10 @@ module Glimmer
|
|
74
74
|
|
75
75
|
DEFAULT_INITIALIZERS = {
|
76
76
|
composite: lambda do |composite|
|
77
|
-
if composite.get_layout.nil?
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
composite.layout = layout
|
82
|
-
end
|
77
|
+
composite.layout = GridLayout.new if composite.get_layout.nil?
|
78
|
+
end,
|
79
|
+
canvas: lambda do |canvas|
|
80
|
+
canvas.layout = nil unless canvas.get_layout.nil?
|
83
81
|
end,
|
84
82
|
scrolled_composite: lambda do |scrolled_composite|
|
85
83
|
scrolled_composite.expand_horizontal = true
|
@@ -160,7 +158,7 @@ module Glimmer
|
|
160
158
|
underscored_widget_name = self.class.underscored_widget_name(@swt_widget)
|
161
159
|
parent_proxy_class = self.class.widget_proxy_class(self.class.underscored_widget_name(@swt_widget.parent))
|
162
160
|
parent = swt_widget.parent
|
163
|
-
@parent_proxy = parent
|
161
|
+
@parent_proxy = parent&.get_data('proxy') || parent_proxy_class.new(swt_widget: parent)
|
164
162
|
end
|
165
163
|
if @swt_widget&.get_data('proxy').nil?
|
166
164
|
@swt_widget.set_data('proxy', self)
|
@@ -499,26 +497,37 @@ module Glimmer
|
|
499
497
|
|
500
498
|
# This supports widgets in and out of basic SWT
|
501
499
|
def self.swt_widget_class_for(underscored_widget_name)
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
500
|
+
# TODO clear memoization for a keyword if a custom widget was defined with that keyword
|
501
|
+
unless flyweight_swt_widget_classes.keys.include?(underscored_widget_name)
|
502
|
+
begin
|
503
|
+
underscored_widget_name = KEYWORD_ALIASES[underscored_widget_name] if KEYWORD_ALIASES[underscored_widget_name]
|
504
|
+
swt_widget_name = underscored_widget_name.camelcase(:upper)
|
505
|
+
swt_widget_class = eval(swt_widget_name)
|
506
|
+
# TODO fix issue with not detecting DateTime because it's conflicting with the Ruby DateTime
|
507
|
+
unless swt_widget_class.ancestors.include?(org.eclipse.swt.widgets.Widget)
|
508
|
+
swt_widget_class = swt_widget_class_manual_entries[underscored_widget_name]
|
509
|
+
if swt_widget_class.nil?
|
510
|
+
Glimmer::Config.logger.debug {"Class #{swt_widget_class} matching #{underscored_widget_name} is not a subclass of org.eclipse.swt.widgets.Widget"}
|
511
|
+
return nil
|
512
|
+
end
|
513
|
+
end
|
514
|
+
flyweight_swt_widget_classes[underscored_widget_name] = swt_widget_class
|
515
|
+
rescue SyntaxError, NameError => e
|
516
|
+
Glimmer::Config.logger.debug {e.full_message}
|
517
|
+
# Glimmer::Config.logger.debug {"#{e.message}\n#{e.backtrace.join("\n")}"}
|
518
|
+
nil
|
519
|
+
rescue => e
|
520
|
+
Glimmer::Config.logger.debug {e.full_message}
|
521
|
+
# Glimmer::Config.logger.debug {"#{e.message}\n#{e.backtrace.join("\n")}"}
|
522
|
+
nil
|
511
523
|
end
|
512
524
|
end
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
Glimmer::Config.logger.debug {e.full_message}
|
520
|
-
# Glimmer::Config.logger.debug {"#{e.message}\n#{e.backtrace.join("\n")}"}
|
521
|
-
nil
|
525
|
+
flyweight_swt_widget_classes[underscored_widget_name]
|
526
|
+
end
|
527
|
+
|
528
|
+
# Flyweight Design Pattern memoization cache. Can be cleared if memory is needed.
|
529
|
+
def self.flyweight_swt_widget_classes
|
530
|
+
@flyweight_swt_widget_classes ||= {}
|
522
531
|
end
|
523
532
|
|
524
533
|
def async_exec(&block)
|
@@ -687,7 +696,7 @@ module Glimmer
|
|
687
696
|
safe_block = lambda { |*args| block.call(*args) unless @swt_widget.isDisposed }
|
688
697
|
listener = listener_class.new(listener_method => safe_block)
|
689
698
|
@swt_widget.send(widget_add_listener_method, listener)
|
690
|
-
|
699
|
+
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)
|
691
700
|
end
|
692
701
|
|
693
702
|
# Looks through SWT class add***Listener methods till it finds one for which
|
@@ -27,12 +27,21 @@ module Glimmer
|
|
27
27
|
include SuperModule
|
28
28
|
include Glimmer::UI::CustomWidget
|
29
29
|
|
30
|
+
class << self
|
31
|
+
attr_reader :launched_custom_shell
|
32
|
+
|
33
|
+
def launch(*args, &content)
|
34
|
+
@launched_custom_shell = send(keyword, *args, &content) if @launched_custom_shell.nil? || @launched_custom_shell.disposed?
|
35
|
+
@launched_custom_shell.open
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
30
39
|
def initialize(parent, *swt_constants, options, &content)
|
31
40
|
super
|
32
41
|
@swt_widget.set_data('custom_shell', self)
|
33
42
|
raise Error, 'Invalid custom shell body root! Must be a shell or another custom shell.' unless body_root.swt_widget.is_a?(org.eclipse.swt.widgets.Shell)
|
34
43
|
end
|
35
|
-
|
44
|
+
|
36
45
|
# Classes may override
|
37
46
|
def open
|
38
47
|
body_root.open
|
@@ -43,6 +52,7 @@ module Glimmer
|
|
43
52
|
open
|
44
53
|
end
|
45
54
|
|
55
|
+
# TODO consider using Forwardable instead
|
46
56
|
def close
|
47
57
|
body_root.close
|
48
58
|
end
|
@@ -55,8 +65,12 @@ module Glimmer
|
|
55
65
|
body_root.visible?
|
56
66
|
end
|
57
67
|
|
58
|
-
def
|
59
|
-
|
68
|
+
def disposed?
|
69
|
+
swt_widget.is_disposed
|
70
|
+
end
|
71
|
+
|
72
|
+
def center_within_display
|
73
|
+
body_root.center_within_display
|
60
74
|
end
|
61
75
|
|
62
76
|
def start_event_loop
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# Copyright (c) 2007-2021 Andy Maleh
|
2
|
-
#
|
2
|
+
#
|
3
3
|
# Permission is hereby granted, free of charge, to any person obtaining
|
4
4
|
# a copy of this software and associated documentation files (the
|
5
5
|
# "Software"), to deal in the Software without restriction, including
|
@@ -7,10 +7,10 @@
|
|
7
7
|
# distribute, sublicense, and/or sell copies of the Software, and to
|
8
8
|
# permit persons to whom the Software is furnished to do so, subject to
|
9
9
|
# the following conditions:
|
10
|
-
#
|
10
|
+
#
|
11
11
|
# The above copyright notice and this permission notice shall be
|
12
12
|
# included in all copies or substantial portions of the Software.
|
13
|
-
#
|
13
|
+
#
|
14
14
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
15
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
16
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
@@ -34,39 +34,60 @@ module Glimmer
|
|
34
34
|
include DataBinding::ObservableModel
|
35
35
|
|
36
36
|
super_module_included do |klass|
|
37
|
+
# TODO clear memoization of WidgetProxy.swt_widget_class_for for a keyword if a custom widget was defined with that keyword
|
37
38
|
klass.include(Glimmer) unless klass.name.include?('Glimmer::UI::CustomShell')
|
38
39
|
Glimmer::UI::CustomWidget.add_custom_widget_namespaces_for(klass) unless klass.name.include?('Glimmer::UI::CustomShell')
|
39
40
|
end
|
40
41
|
|
41
42
|
class << self
|
42
43
|
def for(underscored_custom_widget_name)
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
44
|
+
unless flyweight_custom_widget_classes.keys.include?(underscored_custom_widget_name)
|
45
|
+
begin
|
46
|
+
extracted_namespaces = underscored_custom_widget_name.
|
47
|
+
to_s.
|
48
|
+
split(/__/).map do |namespace|
|
49
|
+
namespace.camelcase(:upper)
|
50
|
+
end
|
51
|
+
custom_widget_namespaces.each do |base|
|
52
|
+
extracted_namespaces.reduce(base) do |result, namespace|
|
53
|
+
if !result.constants.include?(namespace)
|
54
|
+
namespace = result.constants.detect {|c| c.to_s.upcase == namespace.to_s.upcase } || namespace
|
55
|
+
end
|
56
|
+
begin
|
57
|
+
flyweight_custom_widget_classes[underscored_custom_widget_name] = constant = result.const_get(namespace)
|
58
|
+
return constant if constant.ancestors.include?(Glimmer::UI::CustomWidget)
|
59
|
+
flyweight_custom_widget_classes[underscored_custom_widget_name] = constant
|
60
|
+
rescue => e
|
61
|
+
# Glimmer::Config.logger.debug {"#{e.message}\n#{e.backtrace.join("\n")}"}
|
62
|
+
flyweight_custom_widget_classes[underscored_custom_widget_name] = result
|
63
|
+
end
|
64
|
+
end
|
60
65
|
end
|
66
|
+
raise "#{underscored_custom_widget_name} has no custom widget class!"
|
67
|
+
rescue => e
|
68
|
+
Glimmer::Config.logger.debug {e.message}
|
69
|
+
Glimmer::Config.logger.debug {"#{e.message}\n#{e.backtrace.join("\n")}"}
|
70
|
+
flyweight_custom_widget_classes[underscored_custom_widget_name] = nil
|
61
71
|
end
|
62
72
|
end
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
73
|
+
flyweight_custom_widget_classes[underscored_custom_widget_name]
|
74
|
+
end
|
75
|
+
|
76
|
+
# Flyweight Design Pattern memoization cache. Can be cleared if memory is needed.
|
77
|
+
def flyweight_custom_widget_classes
|
78
|
+
@flyweight_custom_widget_classes ||= {}
|
79
|
+
end
|
80
|
+
|
81
|
+
# Returns keyword to use for this custom widget
|
82
|
+
def keyword
|
83
|
+
self.name.underscore.gsub('::', '__')
|
84
|
+
end
|
85
|
+
|
86
|
+
# Returns shortcut keyword to use for this custom widget (keyword minus namespace)
|
87
|
+
def shortcut_keyword
|
88
|
+
self.name.underscore.gsub('::', '__').split('__').last
|
68
89
|
end
|
69
|
-
|
90
|
+
|
70
91
|
def add_custom_widget_namespaces_for(klass)
|
71
92
|
Glimmer::UI::CustomWidget.namespaces_for_class(klass).drop(1).each do |namespace|
|
72
93
|
Glimmer::UI::CustomWidget.custom_widget_namespaces << namespace
|
@@ -127,8 +148,7 @@ module Glimmer
|
|
127
148
|
end
|
128
149
|
|
129
150
|
def before_body(&block)
|
130
|
-
@
|
131
|
-
@before_body_blocks << block
|
151
|
+
@before_body_block = block
|
132
152
|
end
|
133
153
|
|
134
154
|
def body(&block)
|
@@ -136,27 +156,28 @@ module Glimmer
|
|
136
156
|
end
|
137
157
|
|
138
158
|
def after_body(&block)
|
139
|
-
@
|
140
|
-
@after_body_blocks << block
|
159
|
+
@after_body_block = block
|
141
160
|
end
|
142
161
|
end
|
143
162
|
|
144
|
-
attr_reader :body_root, :swt_widget, :parent, :swt_style, :options
|
163
|
+
attr_reader :body_root, :swt_widget, :parent, :parent_proxy, :swt_style, :options
|
145
164
|
|
146
165
|
def initialize(parent, *swt_constants, options, &content)
|
147
|
-
@parent = parent
|
148
166
|
@swt_style = SWT::SWTProxy[*swt_constants]
|
149
167
|
options ||= {}
|
150
168
|
@options = self.class.options.merge(options)
|
151
169
|
@content = Util::ProcTracker.new(content) if content
|
152
|
-
|
170
|
+
execute_hook('before_body')
|
153
171
|
body_block = self.class.instance_variable_get("@body_block")
|
154
172
|
raise Glimmer::Error, 'Invalid custom widget for having no body! Please define body block!' if body_block.nil?
|
155
173
|
@body_root = instance_exec(&body_block)
|
156
174
|
raise Glimmer::Error, 'Invalid custom widget for having an empty body! Please fill body block!' if @body_root.nil?
|
157
175
|
@swt_widget = @body_root.swt_widget
|
158
176
|
@swt_widget.set_data('custom_widget', self)
|
159
|
-
|
177
|
+
@parent = parent
|
178
|
+
@parent ||= @swt_widget.parent
|
179
|
+
@parent_proxy ||= @parent&.get_data('proxy')
|
180
|
+
execute_hook('after_body')
|
160
181
|
end
|
161
182
|
|
162
183
|
# Subclasses may override to perform post initialization work on an added child
|
@@ -211,10 +232,10 @@ module Glimmer
|
|
211
232
|
|
212
233
|
# This method ensures it has an instance method not coming from Glimmer DSL
|
213
234
|
def has_instance_method?(method_name)
|
214
|
-
respond_to?(method_name) and
|
235
|
+
respond_to?(method_name) and
|
215
236
|
!swt_widget&.respond_to?(method_name) and
|
216
237
|
(method(method_name) rescue nil) and
|
217
|
-
!method(method_name)&.source_location&.first&.include?('glimmer/dsl/engine.rb') and
|
238
|
+
!method(method_name)&.source_location&.first&.include?('glimmer/dsl/engine.rb') and
|
218
239
|
!method(method_name)&.source_location&.first&.include?('glimmer/swt/widget_proxy.rb')
|
219
240
|
end
|
220
241
|
|
@@ -265,22 +286,22 @@ module Glimmer
|
|
265
286
|
end
|
266
287
|
end
|
267
288
|
|
268
|
-
alias local_respond_to? respond_to?
|
289
|
+
alias local_respond_to? respond_to?
|
269
290
|
def respond_to?(method, *args, &block)
|
270
291
|
super or
|
271
292
|
can_handle_observation_request?(method) or
|
272
293
|
body_root.respond_to?(method, *args, &block)
|
273
294
|
end
|
274
|
-
|
295
|
+
|
275
296
|
private
|
276
297
|
|
277
|
-
def
|
278
|
-
self.class.instance_variable_get("@#{hook_name}
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
298
|
+
def execute_hook(hook_name)
|
299
|
+
hook_block = self.class.instance_variable_get("@#{hook_name}_block")
|
300
|
+
return if hook_block.nil?
|
301
|
+
temp_method_name = "#{hook_name}_block_#{hook_block.hash.abs}_#{(Time.now.to_f * 1_000_000).to_i}"
|
302
|
+
singleton_class.define_method(temp_method_name, &hook_block)
|
303
|
+
send(temp_method_name)
|
304
|
+
singleton_class.send(:remove_method, temp_method_name)
|
284
305
|
end
|
285
306
|
end
|
286
307
|
end
|
@@ -1,9 +1,48 @@
|
|
1
|
+
# Copyright (c) 2007-2021 Andy Maleh
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
# a copy of this software and associated documentation files (the
|
5
|
+
# "Software"), to deal in the Software without restriction, including
|
6
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
# the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be
|
12
|
+
# included in all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
1
22
|
require 'fileutils'
|
2
23
|
require 'etc'
|
3
24
|
|
4
25
|
class Sample
|
5
26
|
include Glimmer::DataBinding::ObservableModel
|
6
27
|
|
28
|
+
class << self
|
29
|
+
def glimmer_directory
|
30
|
+
File.expand_path('../../..', __FILE__)
|
31
|
+
end
|
32
|
+
|
33
|
+
def user_glimmer_directory
|
34
|
+
File.join(Etc.getpwuid.dir, '.glimmer-dsl-swt')
|
35
|
+
end
|
36
|
+
|
37
|
+
def ensure_user_glimmer_directory
|
38
|
+
unless @ensured_glimmer_directory
|
39
|
+
FileUtils.rm_rf(user_glimmer_directory)
|
40
|
+
FileUtils.cp_r(glimmer_directory, user_glimmer_directory)
|
41
|
+
@ensured_glimmer_directory = true
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
7
46
|
attr_accessor :sample_directory, :file, :selected
|
8
47
|
|
9
48
|
def initialize(file, sample_directory: )
|
@@ -38,25 +77,35 @@ class Sample
|
|
38
77
|
File.basename(file) != 'meta_sample.rb'
|
39
78
|
end
|
40
79
|
alias launchable editable
|
80
|
+
|
81
|
+
def file_relative_path
|
82
|
+
file.sub(self.class.glimmer_directory, '')
|
83
|
+
end
|
84
|
+
|
85
|
+
def user_file
|
86
|
+
File.join(self.class.user_glimmer_directory, file_relative_path)
|
87
|
+
end
|
88
|
+
|
89
|
+
def user_file_parent_directory
|
90
|
+
File.dirname(user_file)
|
91
|
+
end
|
41
92
|
|
93
|
+
def directory
|
94
|
+
file.sub(/\.rb/, '')
|
95
|
+
end
|
96
|
+
|
42
97
|
def launch(modified_code)
|
43
|
-
|
44
|
-
modified_file_parent_directory = File.join(Etc.getpwuid.dir, '.glimmer', 'samples', parent_directory)
|
45
|
-
launch_file = modified_file = File.join(modified_file_parent_directory, File.basename(file))
|
98
|
+
launch_file = user_file
|
46
99
|
begin
|
47
|
-
FileUtils.
|
48
|
-
FileUtils.cp_r(
|
49
|
-
|
50
|
-
File.write(modified_file, modified_code)
|
100
|
+
FileUtils.cp_r(file, user_file_parent_directory)
|
101
|
+
FileUtils.cp_r(directory, user_file_parent_directory) if File.exist?(directory)
|
102
|
+
File.write(user_file, modified_code)
|
51
103
|
rescue => e
|
52
104
|
puts 'Error writing sample modifications. Launching original sample.'
|
53
105
|
puts e.full_message
|
54
106
|
launch_file = file # load original file if failed to write changes
|
55
107
|
end
|
56
108
|
load(launch_file)
|
57
|
-
ensure
|
58
|
-
FileUtils.rm_rf(modified_file)
|
59
|
-
FileUtils.rm_rf(modified_file.sub(/\.rb/, ''))
|
60
109
|
end
|
61
110
|
end
|
62
111
|
|
@@ -141,17 +190,18 @@ class SampleDirectory
|
|
141
190
|
end
|
142
191
|
|
143
192
|
class MetaSampleApplication
|
144
|
-
include Glimmer
|
193
|
+
include Glimmer::UI::CustomShell
|
145
194
|
|
146
|
-
|
195
|
+
before_body {
|
196
|
+
Sample.ensure_user_glimmer_directory
|
147
197
|
selected_sample_directory = SampleDirectory.sample_directories.first
|
148
198
|
selected_sample = selected_sample_directory.samples.first
|
149
199
|
selected_sample_directory.selected_sample_name = selected_sample.name
|
150
|
-
end
|
151
|
-
|
152
|
-
def launch
|
153
200
|
Display.app_name = 'Glimmer Meta-Sample'
|
154
|
-
|
201
|
+
}
|
202
|
+
|
203
|
+
body {
|
204
|
+
shell(:fill_screen) {
|
155
205
|
minimum_size 1280, 768
|
156
206
|
text 'Glimmer Meta-Sample (The Sample of Samples)'
|
157
207
|
image File.expand_path('../../icons/scaffold_app.png', __dir__)
|
@@ -197,11 +247,8 @@ class MetaSampleApplication
|
|
197
247
|
on_widget_selected {
|
198
248
|
begin
|
199
249
|
SampleDirectory.selected_sample.launch(@code_text.text)
|
200
|
-
rescue StandardError, SyntaxError => launch_error
|
201
|
-
|
202
|
-
text 'Error Launching'
|
203
|
-
message launch_error.full_message
|
204
|
-
}.open
|
250
|
+
rescue LoadError, StandardError, SyntaxError => launch_error
|
251
|
+
error_dialog(message: launch_error.full_message).open
|
205
252
|
end
|
206
253
|
}
|
207
254
|
}
|
@@ -222,10 +269,41 @@ class MetaSampleApplication
|
|
222
269
|
editable bind(SampleDirectory, 'selected_sample.editable')
|
223
270
|
}
|
224
271
|
|
225
|
-
weights 4,
|
272
|
+
weights 4, 11
|
273
|
+
}
|
274
|
+
}
|
275
|
+
}
|
276
|
+
|
277
|
+
# Method-based error_dialog custom widget
|
278
|
+
def error_dialog(message:)
|
279
|
+
return if message.nil?
|
280
|
+
dialog(body_root) { |dialog_proxy|
|
281
|
+
row_layout(:vertical) {
|
282
|
+
center true
|
283
|
+
}
|
284
|
+
|
285
|
+
text 'Error Launching'
|
286
|
+
|
287
|
+
styled_text(:border, :h_scroll, :v_scroll) {
|
288
|
+
layout_data {
|
289
|
+
width body_root.bounds.width*0.75
|
290
|
+
height body_root.bounds.height*0.75
|
291
|
+
}
|
292
|
+
|
293
|
+
text message
|
294
|
+
editable false
|
295
|
+
caret nil
|
296
|
+
}
|
297
|
+
|
298
|
+
button {
|
299
|
+
text 'Close'
|
300
|
+
|
301
|
+
on_widget_selected {
|
302
|
+
dialog_proxy.close
|
303
|
+
}
|
226
304
|
}
|
227
|
-
}
|
305
|
+
}
|
228
306
|
end
|
229
307
|
end
|
230
308
|
|
231
|
-
MetaSampleApplication.
|
309
|
+
MetaSampleApplication.launch
|