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
@@ -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'
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class Calculator
|
2
|
+
module Model
|
3
|
+
class Command
|
4
|
+
class AllClear < Command
|
5
|
+
keywords 'AC', 'c', 'C', 8.chr, 27.chr, 127.chr
|
6
|
+
|
7
|
+
def execute
|
8
|
+
self.result = '0'
|
9
|
+
self.number1 = nil
|
10
|
+
self.number2 = nil
|
11
|
+
self.operation = nil
|
12
|
+
command_history.clear
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
File without changes
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class Calculator
|
2
|
+
module Model
|
3
|
+
class Command
|
4
|
+
class Equals < Command
|
5
|
+
keywords '=', "\r"
|
6
|
+
|
7
|
+
def execute
|
8
|
+
if number1 && number2 && operation
|
9
|
+
self.result = operation.calculate.to_s
|
10
|
+
self.number1 = self.result
|
11
|
+
else
|
12
|
+
self.result = last_result || '0'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class Calculator
|
2
|
+
module Model
|
3
|
+
class Command
|
4
|
+
class Number < Command
|
5
|
+
keywords ('0'..'9').to_a
|
6
|
+
|
7
|
+
def execute
|
8
|
+
self.result = last_result.nil? || (!last_command.is_a?(Number) && !last_command.is_a?(Point)) ? button : last_result + button
|
9
|
+
if operation.nil? || last_command.is_a?(Equals)
|
10
|
+
self.number1 = self.result
|
11
|
+
self.number2 = nil
|
12
|
+
self.operation = nil
|
13
|
+
else
|
14
|
+
self.number2 = self.result
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class Calculator
|
2
|
+
module Model
|
3
|
+
class Command
|
4
|
+
class Operation < Command
|
5
|
+
def execute
|
6
|
+
if number1 && number2 && operation && !last_command.is_a?(Equals)
|
7
|
+
self.result = operation.calculate.to_s
|
8
|
+
self.number1 = self.result
|
9
|
+
else
|
10
|
+
self.result = last_result || '0'
|
11
|
+
self.operation = self
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def calculate
|
16
|
+
calculation_result = BigDecimal.new(number1.to_s).send(operation_method, BigDecimal.new(number2.to_s)).to_f
|
17
|
+
calculation_result.to_s.match(/\.0+$/) ? calculation_result.to_i : calculation_result
|
18
|
+
end
|
19
|
+
|
20
|
+
# Subclasses must implement to indicate operation method on number (e.g. :+ for addition)
|
21
|
+
def operation_method
|
22
|
+
raise 'Not implemented!'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class Calculator
|
2
|
+
module Model
|
3
|
+
class Command
|
4
|
+
class Point < Command
|
5
|
+
keyword '.'
|
6
|
+
|
7
|
+
def execute
|
8
|
+
self.result = last_result.nil? || !last_command.is_a?(Number) ? '0.' : "#{last_result}."
|
9
|
+
if operation.nil? || last_command.is_a?(Equals)
|
10
|
+
self.number1 = self.result
|
11
|
+
self.number2 = nil
|
12
|
+
self.operation = nil
|
13
|
+
else
|
14
|
+
self.number2 = self.result
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require_relative 'command'
|
2
|
+
|
3
|
+
class Calculator
|
4
|
+
module Model
|
5
|
+
class Presenter
|
6
|
+
FORMATTER = {
|
7
|
+
nil => '0',
|
8
|
+
'NaN' => 'Not a number'
|
9
|
+
}
|
10
|
+
|
11
|
+
attr_accessor :result
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
self.result = '0'
|
15
|
+
end
|
16
|
+
|
17
|
+
def press(button)
|
18
|
+
command = Command.for(button)
|
19
|
+
if command
|
20
|
+
new_result = command.result
|
21
|
+
self.result = FORMATTER[new_result] || new_result
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def purge_command_history
|
26
|
+
Command.purge_command_history
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/samples/elaborate/login.rb
CHANGED
@@ -35,24 +35,19 @@ class LoginPresenter
|
|
35
35
|
|
36
36
|
def status=(status)
|
37
37
|
@status = status
|
38
|
-
|
39
|
-
notify_observers("logged_in")
|
40
|
-
notify_observers("logged_out")
|
41
38
|
end
|
42
39
|
|
43
40
|
def valid?
|
44
41
|
!@user_name.to_s.strip.empty? && !@password.to_s.strip.empty?
|
45
42
|
end
|
46
43
|
|
47
|
-
def logged_in
|
44
|
+
def logged_in?
|
48
45
|
self.status == "Logged In"
|
49
46
|
end
|
50
|
-
alias logged_in? logged_in
|
51
47
|
|
52
|
-
def logged_out
|
53
|
-
!self.logged_in
|
48
|
+
def logged_out?
|
49
|
+
!self.logged_in?
|
54
50
|
end
|
55
|
-
alias logged_out? logged_out
|
56
51
|
|
57
52
|
def login!
|
58
53
|
return unless valid?
|
@@ -77,13 +72,15 @@ class Login
|
|
77
72
|
body {
|
78
73
|
shell {
|
79
74
|
text "Login"
|
75
|
+
|
80
76
|
composite {
|
81
77
|
grid_layout 2, false #two columns with differing widths
|
82
78
|
|
83
79
|
label { text "Username:" } # goes in column 1
|
84
80
|
@user_name_text = text { # goes in column 2
|
85
81
|
text <=> [@presenter, :user_name]
|
86
|
-
enabled <= [@presenter, :logged_out]
|
82
|
+
enabled <= [@presenter, :logged_out?, computed_by: :status]
|
83
|
+
|
87
84
|
on_key_pressed { |event|
|
88
85
|
@password_text.set_focus if event.keyCode == swt(:cr)
|
89
86
|
}
|
@@ -92,7 +89,8 @@ class Login
|
|
92
89
|
label { text "Password:" }
|
93
90
|
@password_text = text(:password, :border) {
|
94
91
|
text <=> [@presenter, :password]
|
95
|
-
enabled <= [@presenter, :logged_out]
|
92
|
+
enabled <= [@presenter, :logged_out?, computed_by: :status]
|
93
|
+
|
96
94
|
on_key_pressed { |event|
|
97
95
|
@presenter.login! if event.keyCode == swt(:cr)
|
98
96
|
}
|
@@ -103,16 +101,20 @@ class Login
|
|
103
101
|
|
104
102
|
button {
|
105
103
|
text "Login"
|
106
|
-
enabled <= [@presenter, :logged_out]
|
104
|
+
enabled <= [@presenter, :logged_out?, computed_by: :status]
|
105
|
+
|
107
106
|
on_widget_selected { @presenter.login! }
|
108
107
|
on_key_pressed { |event|
|
109
|
-
|
108
|
+
if event.keyCode == swt(:cr)
|
109
|
+
@presenter.login!
|
110
|
+
end
|
110
111
|
}
|
111
112
|
}
|
112
113
|
|
113
114
|
button {
|
114
115
|
text "Logout"
|
115
|
-
enabled <= [@presenter, :logged_in]
|
116
|
+
enabled <= [@presenter, :logged_in?, computed_by: :status]
|
117
|
+
|
116
118
|
on_widget_selected { @presenter.logout! }
|
117
119
|
on_key_pressed { |event|
|
118
120
|
if event.keyCode == swt(:cr)
|
data/samples/elaborate/tetris.rb
CHANGED
@@ -54,7 +54,7 @@ class Tetris
|
|
54
54
|
Display.app_name = 'Glimmer Tetris'
|
55
55
|
|
56
56
|
display {
|
57
|
-
|
57
|
+
on_swt_keydown { |key_event|
|
58
58
|
case key_event.keyCode
|
59
59
|
when swt(:arrow_down), 's'.bytes.first
|
60
60
|
game.down! if OS.mac?
|
@@ -82,7 +82,7 @@ class Tetris
|
|
82
82
|
|
83
83
|
# invoke game.down! on keyup with Windows/Linux since they seem to group-render similar events, preventing intermediate renders (causing invisiblity while holding keys)
|
84
84
|
if !OS.mac?
|
85
|
-
|
85
|
+
on_swt_keyup { |key_event|
|
86
86
|
case key_event.keyCode
|
87
87
|
when swt(:arrow_down), 's'.bytes.first
|
88
88
|
game.down!
|
@@ -91,11 +91,11 @@ class Tetris
|
|
91
91
|
end
|
92
92
|
|
93
93
|
# if running in app mode, set the Mac app about dialog (ignored in platforms)
|
94
|
-
|
94
|
+
on_about {
|
95
95
|
show_about_dialog
|
96
96
|
}
|
97
97
|
|
98
|
-
|
98
|
+
on_quit {
|
99
99
|
exit(0)
|
100
100
|
}
|
101
101
|
}
|
@@ -33,8 +33,6 @@ class Tetris
|
|
33
33
|
class Game
|
34
34
|
PLAYFIELD_WIDTH = 10
|
35
35
|
PLAYFIELD_HEIGHT = 20
|
36
|
-
# PLAYFIELD_WIDTH = 5
|
37
|
-
# PLAYFIELD_HEIGHT = 5
|
38
36
|
PREVIEW_PLAYFIELD_WIDTH = 4
|
39
37
|
PREVIEW_PLAYFIELD_HEIGHT = 2
|
40
38
|
SCORE_MULTIPLIER = {1 => 40, 2 => 100, 3 => 300, 4 => 1200}
|
@@ -201,7 +199,6 @@ class Tetris
|
|
201
199
|
|
202
200
|
def delay
|
203
201
|
[1.1 - (level.to_i * 0.1), 0.001].max
|
204
|
-
# 99999
|
205
202
|
end
|
206
203
|
|
207
204
|
def beep
|