glimmer-dsl-swt 4.20.0.0 → 4.20.0.5
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 +18 -14
- data/VERSION +1 -1
- data/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md +11 -7
- data/docs/reference/GLIMMER_SAMPLES.md +170 -17
- data/docs/reference/GLIMMER_STYLE_GUIDE.md +4 -3
- data/glimmer-dsl-swt.gemspec +0 -0
- 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/tool_bar_proxy.rb +51 -0
- data/lib/glimmer/swt/widget_proxy.rb +7 -1
- 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_composite.rb +71 -0
- data/samples/hello/hello_cool_bar.rb +147 -0
- data/samples/hello/hello_layout.rb +243 -0
- data/samples/hello/hello_shell.rb +205 -0
- data/samples/hello/hello_text.rb +120 -0
- data/samples/hello/hello_tool_bar.rb +143 -0
- metadata +28 -3
@@ -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
|
@@ -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
|
@@ -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
|
@@ -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
|
@@ -0,0 +1,105 @@
|
|
1
|
+
class Calculator
|
2
|
+
module Model
|
3
|
+
class Command
|
4
|
+
class << self
|
5
|
+
attr_accessor :number1, :number2, :operation
|
6
|
+
|
7
|
+
# Keyword string representing calculator command (e.g. '+' for Add command)
|
8
|
+
# Subclasses must call to define a single keyword
|
9
|
+
def keyword(keyword_text)
|
10
|
+
Command.keyword_to_command_class_mapping[keyword_text] = self
|
11
|
+
end
|
12
|
+
|
13
|
+
# Keyword string array representing calculator command (e.g. ('0'..'9').to_a)
|
14
|
+
# Subclasses must call to define multiple keywords
|
15
|
+
def keywords(*keyword_text_array)
|
16
|
+
keyword_text_array.flatten.each do |keyword_text|
|
17
|
+
keyword(keyword_text)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def keyword_to_command_class_mapping
|
22
|
+
@keyword_to_command_class_mapping ||= {}
|
23
|
+
end
|
24
|
+
|
25
|
+
def command_history
|
26
|
+
@command_history ||= []
|
27
|
+
end
|
28
|
+
|
29
|
+
def purge_command_history
|
30
|
+
Command.command_history.clear
|
31
|
+
self.number1 = nil
|
32
|
+
self.number2 = nil
|
33
|
+
self.operation = nil
|
34
|
+
end
|
35
|
+
|
36
|
+
def for(button)
|
37
|
+
command_class = keyword_to_command_class_mapping[button]
|
38
|
+
command_class&.new(button)&.tap do |command|
|
39
|
+
command.execute
|
40
|
+
command_history << command
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
attr_reader :button
|
46
|
+
attr_accessor :result
|
47
|
+
|
48
|
+
def initialize(button)
|
49
|
+
@button = button
|
50
|
+
end
|
51
|
+
|
52
|
+
def number1
|
53
|
+
Command.number1
|
54
|
+
end
|
55
|
+
|
56
|
+
def number1=(value)
|
57
|
+
Command.number1 = value.to_f
|
58
|
+
end
|
59
|
+
|
60
|
+
def number2
|
61
|
+
Command.number2
|
62
|
+
end
|
63
|
+
|
64
|
+
def number2=(value)
|
65
|
+
Command.number2 = value.to_f
|
66
|
+
end
|
67
|
+
|
68
|
+
def operation
|
69
|
+
Command.operation
|
70
|
+
end
|
71
|
+
|
72
|
+
def operation=(op)
|
73
|
+
Command.operation = op
|
74
|
+
end
|
75
|
+
|
76
|
+
def last_result
|
77
|
+
last_command&.result
|
78
|
+
end
|
79
|
+
|
80
|
+
def last_command
|
81
|
+
command_history.last
|
82
|
+
end
|
83
|
+
|
84
|
+
def command_history
|
85
|
+
Command.command_history
|
86
|
+
end
|
87
|
+
|
88
|
+
def execute
|
89
|
+
raise 'Not implemented! Please override in a subclass.'
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Dir[File.join(File.dirname(__FILE__), 'command', '**', '*.rb')].each {|f| require(f)} # disabled for Opal compatibility
|
96
|
+
|
97
|
+
require_relative 'command/all_clear'
|
98
|
+
require_relative 'command/equals'
|
99
|
+
require_relative 'command/number'
|
100
|
+
require_relative 'command/operation'
|
101
|
+
require_relative 'command/point'
|
102
|
+
require_relative 'command/operation/add'
|
103
|
+
require_relative 'command/operation/divide'
|
104
|
+
require_relative 'command/operation/multiply'
|
105
|
+
require_relative 'command/operation/subtract'
|