glimmer-dsl-swt 4.20.0.1 → 4.20.1.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/CHANGELOG.md +26 -0
- data/README.md +17 -13
- data/VERSION +1 -1
- data/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md +10 -7
- data/docs/reference/GLIMMER_SAMPLES.md +168 -49
- data/docs/reference/GLIMMER_STYLE_GUIDE.md +4 -3
- data/glimmer-dsl-swt.gemspec +0 -0
- data/lib/glimmer/data_binding/shine.rb +3 -1
- data/lib/glimmer/data_binding/table_items_binding.rb +2 -2
- data/lib/glimmer/dsl/swt/shine_data_binding_expression.rb +6 -3
- data/lib/glimmer/dsl/swt/table_items_data_binding_expression.rb +2 -2
- data/lib/glimmer/dsl/swt/widget_expression.rb +2 -0
- data/lib/glimmer/dsl/swt/widget_listener_expression.rb +3 -3
- data/lib/glimmer/rake_task/scaffold.rb +0 -2
- data/lib/glimmer/swt/combo_proxy.rb +48 -0
- data/lib/glimmer/swt/display_proxy.rb +11 -8
- data/lib/glimmer/swt/proxy_properties.rb +2 -1
- data/lib/glimmer/swt/table_proxy.rb +15 -8
- data/lib/glimmer/swt/tool_bar_proxy.rb +51 -0
- data/lib/glimmer/swt/widget_proxy.rb +8 -2
- data/lib/glimmer/ui/custom_shell.rb +3 -3
- data/lib/glimmer/ui/custom_widget.rb +5 -2
- data/samples/elaborate/calculator.rb +116 -0
- data/samples/elaborate/calculator/model/command.rb +105 -0
- data/samples/elaborate/calculator/model/command/all_clear.rb +17 -0
- data/samples/elaborate/calculator/model/command/command_history.rb +0 -0
- data/samples/elaborate/calculator/model/command/equals.rb +18 -0
- data/samples/elaborate/calculator/model/command/number.rb +20 -0
- data/samples/elaborate/calculator/model/command/operation.rb +27 -0
- data/samples/elaborate/calculator/model/command/operation/add.rb +15 -0
- data/samples/elaborate/calculator/model/command/operation/divide.rb +15 -0
- data/samples/elaborate/calculator/model/command/operation/multiply.rb +15 -0
- data/samples/elaborate/calculator/model/command/operation/subtract.rb +15 -0
- data/samples/elaborate/calculator/model/command/point.rb +20 -0
- data/samples/elaborate/calculator/model/presenter.rb +30 -0
- data/samples/elaborate/login.rb +15 -13
- data/samples/elaborate/tetris.rb +4 -4
- data/samples/elaborate/tetris/model/game.rb +0 -3
- data/samples/elaborate/timer.rb +233 -0
- data/samples/elaborate/timer/alarm1.wav +0 -0
- data/samples/elaborate/timer/sounds/alarm1.wav +0 -0
- data/samples/elaborate/user_profile.rb +4 -2
- data/samples/elaborate/weather.rb +164 -0
- data/samples/hello/hello_cool_bar.rb +147 -0
- data/samples/hello/hello_layout.rb +6 -2
- data/samples/hello/hello_shell.rb +205 -0
- data/samples/hello/hello_table.rb +5 -5
- data/samples/hello/hello_text.rb +120 -0
- data/samples/hello/hello_tool_bar.rb +143 -0
- metadata +25 -2
@@ -7,8 +7,9 @@
|
|
7
7
|
- Widget properties are declared with underscored lowercase versions of the SWT properties
|
8
8
|
- Widget property declarations always have arguments and never take a block
|
9
9
|
- Widget property arguments are never wrapped inside parentheses
|
10
|
-
- Widget listeners are always declared starting with `on_` prefix and affixing listener event method name afterwards in underscored lowercase form
|
10
|
+
- Widget listeners are always declared starting with `on_` prefix and affixing listener event method name afterwards in underscored lowercase form. Their multi-line blocks rely on the `do; end` style.
|
11
11
|
- Widget listeners are always followed by a block using curly braces (Only when declared in DSL. When invoked on widget object directly outside of GUI declarations, standard Ruby conventions apply)
|
12
12
|
- Data-binding is done via `bind` keyword, which always takes arguments wrapped in parentheses
|
13
|
-
- Custom widget body
|
14
|
-
- Custom widgets receive additional arguments
|
13
|
+
- Custom widget `body`, `before_body`, and `after_body` blocks open their blocks and close them with curly braces.
|
14
|
+
- Custom widgets receive additional keyword arguments called options, which come after the SWT styles.
|
15
|
+
- Pure logic multi-line blocks that do not constitute GUI DSL view elements (such as `Thread.new`, `loop`, `each` and `observe` blocks) rely on the `do; end` style to clearly separate logic code from view code.
|
data/glimmer-dsl-swt.gemspec
CHANGED
Binary file
|
@@ -33,8 +33,10 @@ module Glimmer
|
|
33
33
|
|
34
34
|
def <=>(other)
|
35
35
|
if other.is_a?(Array)
|
36
|
+
args_clone = other.clone
|
37
|
+
@parent.editable = true if @parent.is_a?(Glimmer::SWT::TableProxy) # TODO consider a polymorphic way to perform this
|
36
38
|
@parent.content {
|
37
|
-
send(@parent_attribute, bind(*
|
39
|
+
send(@parent_attribute, bind(*args_clone))
|
38
40
|
}
|
39
41
|
else # || other.is_a?(Hash) # TODO support hash e.g. {model: model_obj, attribute: :some_attribute, more-options...}
|
40
42
|
original_compare(other)
|
@@ -34,11 +34,11 @@ module Glimmer
|
|
34
34
|
include_package 'org.eclipse.swt'
|
35
35
|
include_package 'org.eclipse.swt.widgets'
|
36
36
|
|
37
|
-
def initialize(parent, model_binding, column_properties)
|
37
|
+
def initialize(parent, model_binding, column_properties = nil)
|
38
38
|
@table = parent
|
39
39
|
@model_binding = model_binding
|
40
40
|
@read_only_sort = @model_binding.binding_options[:read_only_sort]
|
41
|
-
@column_properties = column_properties
|
41
|
+
@column_properties = @model_binding.binding_options[:column_properties] || @model_binding.binding_options[:column_attributes] || column_properties
|
42
42
|
if @table.respond_to?(:column_properties=)
|
43
43
|
@table.column_properties = @column_properties
|
44
44
|
else # assume custom widget
|
@@ -29,12 +29,15 @@ module Glimmer
|
|
29
29
|
module DSL
|
30
30
|
module SWT
|
31
31
|
class ShineDataBindingExpression < Expression
|
32
|
+
include_package 'org.eclipse.swt.widgets'
|
33
|
+
|
32
34
|
def can_interpret?(parent, keyword, *args, &block)
|
33
35
|
args.size == 0 and
|
34
36
|
block.nil? and
|
35
|
-
|
36
|
-
|
37
|
-
|
37
|
+
(
|
38
|
+
(parent.respond_to?(:set_attribute) and parent.respond_to?(:has_attribute?) and parent.has_attribute?(keyword)) or
|
39
|
+
(parent.respond_to?(:swt_widget) and parent.swt_widget.is_a?(Table))
|
40
|
+
) and
|
38
41
|
!parent.is_a?(Glimmer::UI::CustomWidget) and
|
39
42
|
!parent.is_a?(Glimmer::UI::CustomShape) and
|
40
43
|
!(parent.respond_to?(:swt_widget) && parent.swt_widget.class == org.eclipse.swt.widgets.Canvas && keyword == 'image')
|
@@ -35,10 +35,10 @@ module Glimmer
|
|
35
35
|
block.nil? and
|
36
36
|
parent.respond_to?(:swt_widget) and
|
37
37
|
parent.swt_widget.is_a?(Table) and
|
38
|
-
args.size
|
38
|
+
args.size.between?(1, 2) and
|
39
39
|
args[0].is_a?(DataBinding::ModelBinding) and
|
40
40
|
args[0].evaluate_property.is_a?(Array) and
|
41
|
-
args[1].is_a?(Array)
|
41
|
+
(args[1].nil? or args[1].is_a?(Array))
|
42
42
|
end
|
43
43
|
|
44
44
|
def interpret(parent, keyword, *args, &block)
|
@@ -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
|
@@ -441,8 +441,6 @@ module Glimmer
|
|
441
441
|
require '#{file_name(app_name)}/view/app_view'
|
442
442
|
|
443
443
|
class #{class_name(app_name)}
|
444
|
-
include Glimmer
|
445
|
-
|
446
444
|
APP_ROOT = File.expand_path('../..', __FILE__)
|
447
445
|
VERSION = File.read(File.join(APP_ROOT, 'VERSION'))
|
448
446
|
LICENSE = File.read(File.join(APP_ROOT, 'LICENSE.txt'))
|
@@ -0,0 +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
|
+
|
22
|
+
require 'glimmer/swt/widget_proxy'
|
23
|
+
|
24
|
+
module Glimmer
|
25
|
+
module SWT
|
26
|
+
# Proxy for org.eclipse.swt.widgets.Combo
|
27
|
+
#
|
28
|
+
# Follows the Proxy Design Pattern
|
29
|
+
class ComboProxy < WidgetProxy
|
30
|
+
attr_accessor :tool_item_proxy, :swt_tool_item
|
31
|
+
|
32
|
+
def initialize(*init_args, &block)
|
33
|
+
super
|
34
|
+
self.tool_item_proxy = WidgetProxy.new("tool_item", parent_proxy, [:separator]) if parent_proxy.swt_widget.is_a?(ToolBar)
|
35
|
+
self.swt_tool_item = tool_item_proxy&.swt_widget
|
36
|
+
end
|
37
|
+
|
38
|
+
def post_add_content
|
39
|
+
if self.tool_item_proxy
|
40
|
+
self.swt_widget.pack
|
41
|
+
self.tool_item_proxy.text = 'filler' # text seems needed (any text works)
|
42
|
+
self.tool_item_proxy.width = swt_widget.size.x
|
43
|
+
self.tool_item_proxy.control = swt_widget
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -42,7 +42,7 @@ module Glimmer
|
|
42
42
|
|
43
43
|
OBSERVED_MENU_ITEMS = ['about', 'preferences', 'quit']
|
44
44
|
|
45
|
-
class
|
45
|
+
class ConcreteListener
|
46
46
|
include org.eclipse.swt.widgets.Listener
|
47
47
|
|
48
48
|
def initialize(&listener_block)
|
@@ -194,15 +194,17 @@ module Glimmer
|
|
194
194
|
observation_request = observation_request.to_s
|
195
195
|
if observation_request.start_with?('on_swt_')
|
196
196
|
constant_name = observation_request.sub(/^on_swt_/, '')
|
197
|
-
add_swt_event_filter(constant_name, &block)
|
197
|
+
swt_event_reg = add_swt_event_filter(constant_name, &block)
|
198
|
+
Glimmer::UI::CustomWidget.current_custom_widgets.last&.observer_registrations&.push(swt_event_reg)
|
199
|
+
swt_event_reg
|
198
200
|
elsif observation_request.start_with?('on_')
|
199
201
|
event_name = observation_request.sub(/^on_/, '')
|
200
202
|
if OBSERVED_MENU_ITEMS.include?(event_name) && OS.mac?
|
201
203
|
system_menu = swt_display.getSystemMenu
|
202
204
|
menu_item = system_menu.getItems.find {|menu_item| menu_item.getID == SWTProxy["ID_#{event_name.upcase}"]}
|
203
|
-
|
204
|
-
|
205
|
-
|
205
|
+
listener = ConcreteListener.new(&block)
|
206
|
+
display_mac_event_registration = menu_item.addListener(SWTProxy[:Selection], listener)
|
207
|
+
Glimmer::UI::CustomWidget.current_custom_widgets.last&.observer_registrations&.push(display_mac_event_registration)
|
206
208
|
display_mac_event_registration
|
207
209
|
end
|
208
210
|
end
|
@@ -210,15 +212,16 @@ module Glimmer
|
|
210
212
|
|
211
213
|
def add_swt_event_filter(swt_constant, &block)
|
212
214
|
event_type = SWTProxy[swt_constant]
|
213
|
-
|
215
|
+
swt_listener = ConcreteListener.new(&block)
|
216
|
+
@swt_display.addFilter(event_type, swt_listener)
|
214
217
|
#WidgetListenerProxy.new(@swt_display.getListeners(event_type).last)
|
215
218
|
WidgetListenerProxy.new(
|
216
219
|
swt_display: @swt_display,
|
217
220
|
event_type: event_type,
|
218
221
|
filter: true,
|
219
|
-
swt_listener:
|
222
|
+
swt_listener: swt_listener,
|
220
223
|
widget_add_listener_method: 'addFilter',
|
221
|
-
swt_listener_class:
|
224
|
+
swt_listener_class: ConcreteListener,
|
222
225
|
swt_listener_method: 'handleEvent'
|
223
226
|
)
|
224
227
|
end
|
@@ -33,6 +33,7 @@ module Glimmer
|
|
33
33
|
# default implementation of attribute setters/getters
|
34
34
|
# It tries swt_widget, swt_display, swt_image, and swt_dialog by default.
|
35
35
|
def proxy_source_object
|
36
|
+
# TODO the logic here should not be needed if derived with polymorphism. Consider removing.
|
36
37
|
if respond_to?(:swt_widget)
|
37
38
|
swt_widget
|
38
39
|
elsif respond_to?(:swt_display)
|
@@ -62,7 +63,7 @@ module Glimmer
|
|
62
63
|
|
63
64
|
def has_attribute?(attribute_name, *args)
|
64
65
|
Glimmer::SWT::DisplayProxy.instance.auto_exec do
|
65
|
-
proxy_source_object&.respond_to?(attribute_setter(attribute_name), args)
|
66
|
+
proxy_source_object&.respond_to?(attribute_setter(attribute_name), args) or
|
66
67
|
respond_to?(ruby_attribute_setter(attribute_name), args)
|
67
68
|
end
|
68
69
|
end
|
@@ -250,19 +250,13 @@ module Glimmer
|
|
250
250
|
alias editable? editable
|
251
251
|
|
252
252
|
def initialize(underscored_widget_name, parent, args)
|
253
|
-
|
253
|
+
editable_style = args.delete(:editable)
|
254
254
|
super
|
255
255
|
@table_editor = TableEditor.new(swt_widget)
|
256
256
|
@table_editor.horizontalAlignment = SWTProxy[:left]
|
257
257
|
@table_editor.grabHorizontal = true
|
258
258
|
@table_editor.minimumHeight = 20
|
259
|
-
|
260
|
-
content {
|
261
|
-
on_mouse_up { |event|
|
262
|
-
edit_table_item(event.table_item, event.column_index)
|
263
|
-
}
|
264
|
-
}
|
265
|
-
end
|
259
|
+
self.editable = editable_style
|
266
260
|
end
|
267
261
|
|
268
262
|
def items
|
@@ -283,6 +277,19 @@ module Glimmer
|
|
283
277
|
end
|
284
278
|
end
|
285
279
|
|
280
|
+
def editable=(value)
|
281
|
+
@editable = value
|
282
|
+
if @editable
|
283
|
+
content {
|
284
|
+
@editable_on_mouse_up = on_mouse_up { |event|
|
285
|
+
edit_table_item(event.table_item, event.column_index)
|
286
|
+
}
|
287
|
+
}
|
288
|
+
else
|
289
|
+
@editable_on_mouse_up.deregister if @editable_on_mouse_up
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
286
293
|
def sort_block=(comparator)
|
287
294
|
@sort_block = comparator
|
288
295
|
end
|
@@ -0,0 +1,51 @@
|
|
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
|
+
|
22
|
+
require 'glimmer/swt/widget_proxy'
|
23
|
+
|
24
|
+
module Glimmer
|
25
|
+
module SWT
|
26
|
+
# Proxy for org.eclipse.swt.widgets.ToolBarProxy
|
27
|
+
#
|
28
|
+
# Follows the Proxy Design Pattern
|
29
|
+
class ToolBarProxy < WidgetProxy
|
30
|
+
attr_accessor :cool_item_proxy, :swt_cool_item
|
31
|
+
|
32
|
+
def initialize(*init_args, &block)
|
33
|
+
super
|
34
|
+
self.cool_item_proxy = WidgetProxy.new("cool_item", parent_proxy, []) if parent_proxy.swt_widget.is_a?(CoolBar)
|
35
|
+
self.swt_cool_item = cool_item_proxy&.swt_widget
|
36
|
+
end
|
37
|
+
|
38
|
+
def post_add_content
|
39
|
+
apply_preferred_size if cool_item_proxy
|
40
|
+
end
|
41
|
+
|
42
|
+
def apply_preferred_size
|
43
|
+
swt_widget.pack
|
44
|
+
size = swt_widget.size
|
45
|
+
cool_item_proxy.control = swt_widget
|
46
|
+
preferred = swt_cool_item.computeSize(size.x, size.y)
|
47
|
+
swt_cool_item.setPreferredSize(preferred)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -765,7 +765,7 @@ module Glimmer
|
|
765
765
|
|
766
766
|
def can_add_listener?(underscored_listener_name)
|
767
767
|
auto_exec do
|
768
|
-
!self.class.find_listener(@swt_widget.getClass, underscored_listener_name).empty?
|
768
|
+
@swt_widget && !self.class.find_listener(@swt_widget.getClass, underscored_listener_name).empty?
|
769
769
|
end
|
770
770
|
end
|
771
771
|
|
@@ -838,7 +838,7 @@ module Glimmer
|
|
838
838
|
widget_listener_proxy = nil
|
839
839
|
safe_block = lambda { |*args| block.call(*args) unless @swt_widget.isDisposed }
|
840
840
|
@swt_widget.addListener(event_type, &safe_block)
|
841
|
-
|
841
|
+
WidgetListenerProxy.new(swt_widget: @swt_widget, swt_listener: @swt_widget.getListeners(event_type).last, event_type: event_type, swt_constant: swt_constant)
|
842
842
|
end
|
843
843
|
end
|
844
844
|
|
@@ -1006,6 +1006,12 @@ module Glimmer
|
|
1006
1006
|
image: lambda do |*value|
|
1007
1007
|
ImageProxy.create(*value).swt_image
|
1008
1008
|
end,
|
1009
|
+
disabled_image: lambda do |*value|
|
1010
|
+
ImageProxy.create(*value).swt_image
|
1011
|
+
end,
|
1012
|
+
hot_image: lambda do |*value|
|
1013
|
+
ImageProxy.create(*value).swt_image
|
1014
|
+
end,
|
1009
1015
|
images: lambda do |array|
|
1010
1016
|
array.to_a.map do |value|
|
1011
1017
|
ImageProxy.create(value).swt_image
|
@@ -31,9 +31,9 @@ module Glimmer
|
|
31
31
|
class << self
|
32
32
|
def launch(*args, &content)
|
33
33
|
auto_exec do
|
34
|
-
|
35
|
-
|
36
|
-
|
34
|
+
launched_custom_shell = send(keyword, *args, &content)
|
35
|
+
launched_custom_shell.swt_widget.set_data('launched', true)
|
36
|
+
launched_custom_shell.open
|
37
37
|
end
|
38
38
|
end
|
39
39
|
end
|
@@ -186,8 +186,11 @@ module Glimmer
|
|
186
186
|
@swt_widget.set_data('custom_widget', self)
|
187
187
|
end
|
188
188
|
execute_hook('after_body')
|
189
|
-
|
190
|
-
|
189
|
+
auto_exec do
|
190
|
+
@dispose_listener_registration = @body_root.on_widget_disposed do
|
191
|
+
observer_registrations.compact.each(&:deregister)
|
192
|
+
observer_registrations.clear
|
193
|
+
end
|
191
194
|
end
|
192
195
|
end
|
193
196
|
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'glimmer-dsl-swt'
|
2
|
+
require 'bigdecimal'
|
3
|
+
|
4
|
+
require_relative 'calculator/model/presenter'
|
5
|
+
|
6
|
+
# This sample demonstrates use of MVP (Model-View-Presenter) Architectural Pattern
|
7
|
+
# to data-bind View widgets to object-oriented Models taking advantage of design patterns
|
8
|
+
# like Command Design Pattern.
|
9
|
+
class Calculator
|
10
|
+
include Glimmer::UI::CustomShell
|
11
|
+
|
12
|
+
BUTTON_FONT = {height: 14}
|
13
|
+
BUTTON_FONT_OPERATION = {height: 18}
|
14
|
+
BUTTON_FONT_BIG = {height: 28}
|
15
|
+
|
16
|
+
attr_reader :presenter
|
17
|
+
|
18
|
+
before_body {
|
19
|
+
@presenter = Model::Presenter.new
|
20
|
+
|
21
|
+
Display.setAppName('Glimmer Calculator')
|
22
|
+
|
23
|
+
display {
|
24
|
+
on_swt_keydown { |key_event|
|
25
|
+
char = key_event.character.chr rescue nil
|
26
|
+
@presenter.press(char)
|
27
|
+
}
|
28
|
+
|
29
|
+
on_about {
|
30
|
+
display_about_dialog
|
31
|
+
}
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
body {
|
36
|
+
shell {
|
37
|
+
grid_layout 4, true
|
38
|
+
|
39
|
+
minimum_size (OS.mac? ? 320 : (OS.windows? ? 390 : 520)), 240
|
40
|
+
text "Glimmer Calculator"
|
41
|
+
|
42
|
+
on_shell_closed do
|
43
|
+
@presenter.purge_command_history
|
44
|
+
end
|
45
|
+
|
46
|
+
# Setting styled_text to multi in order for alignment options to activate
|
47
|
+
styled_text(:multi, :wrap, :border) {
|
48
|
+
text bind(@presenter, :result)
|
49
|
+
alignment swt(:right)
|
50
|
+
right_margin 5
|
51
|
+
font height: 40
|
52
|
+
layout_data(:fill, :fill, true, true) {
|
53
|
+
horizontal_span 4
|
54
|
+
}
|
55
|
+
editable false
|
56
|
+
caret nil
|
57
|
+
}
|
58
|
+
command_button('AC')
|
59
|
+
operation_button('÷')
|
60
|
+
operation_button('×')
|
61
|
+
operation_button('−')
|
62
|
+
(7..9).each { |number|
|
63
|
+
number_button(number)
|
64
|
+
}
|
65
|
+
operation_button('+', font: BUTTON_FONT_BIG, vertical_span: 2)
|
66
|
+
(4..6).each { |number|
|
67
|
+
number_button(number)
|
68
|
+
}
|
69
|
+
(1..3).each { |number|
|
70
|
+
number_button(number)
|
71
|
+
}
|
72
|
+
command_button('=', font: BUTTON_FONT_BIG, vertical_span: 2)
|
73
|
+
number_button(0, horizontal_span: 2)
|
74
|
+
operation_button('.')
|
75
|
+
}
|
76
|
+
}
|
77
|
+
|
78
|
+
def number_button(number, options = {})
|
79
|
+
command_button(number, options)
|
80
|
+
end
|
81
|
+
|
82
|
+
def operation_button(operation, options = {})
|
83
|
+
command_button(operation, options.merge(font: BUTTON_FONT_OPERATION))
|
84
|
+
end
|
85
|
+
|
86
|
+
def command_button(command, options = {})
|
87
|
+
command = command.to_s
|
88
|
+
options[:font] ||= BUTTON_FONT
|
89
|
+
options[:horizontal_span] ||= 1
|
90
|
+
options[:vertical_span] ||= 1
|
91
|
+
|
92
|
+
button { |proxy|
|
93
|
+
text command
|
94
|
+
font options[:font]
|
95
|
+
|
96
|
+
layout_data(:fill, :fill, true, true) {
|
97
|
+
horizontal_span options[:horizontal_span]
|
98
|
+
vertical_span options[:vertical_span]
|
99
|
+
}
|
100
|
+
|
101
|
+
on_widget_selected {
|
102
|
+
@presenter.press(command)
|
103
|
+
}
|
104
|
+
}
|
105
|
+
end
|
106
|
+
|
107
|
+
def display_about_dialog
|
108
|
+
message_box(body_root) {
|
109
|
+
text 'About'
|
110
|
+
message "Glimmer - Calculator\n\nCopyright (c) 2007-2021 Andy Maleh"
|
111
|
+
}.open
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
Calculator.launch
|