glimmer-dsl-swt 4.18.4.8 → 4.18.5.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 +70 -0
- data/README.md +24 -11
- data/VERSION +1 -1
- data/bin/glimmer +3 -3
- data/docs/reference/GLIMMER_CONFIGURATION.md +7 -3
- data/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md +353 -145
- data/docs/reference/GLIMMER_SAMPLES.md +207 -41
- data/glimmer-dsl-swt.gemspec +33 -15
- data/lib/ext/glimmer/config.rb +3 -7
- data/lib/glimmer/data_binding/list_selection_binding.rb +13 -7
- data/lib/glimmer/data_binding/table_items_binding.rb +22 -17
- data/lib/glimmer/data_binding/tree_items_binding.rb +19 -15
- data/lib/glimmer/data_binding/widget_binding.rb +13 -15
- data/lib/glimmer/dsl/swt/{file_dialog_expression.rb → auto_exec_expression.rb} +6 -18
- data/lib/glimmer/dsl/swt/checkbox_group_selection_data_binding_expression.rb +9 -6
- data/lib/glimmer/dsl/swt/color_expression.rb +1 -1
- data/lib/glimmer/dsl/swt/combo_selection_data_binding_expression.rb +16 -14
- data/lib/glimmer/dsl/swt/custom_widget_expression.rb +4 -1
- data/lib/glimmer/dsl/swt/data_binding_expression.rb +2 -2
- data/lib/glimmer/dsl/swt/dialog_expression.rb +18 -9
- data/lib/glimmer/dsl/swt/dsl.rb +1 -0
- data/lib/glimmer/dsl/swt/exec_expression.rb +1 -1
- data/lib/glimmer/dsl/swt/font_expression.rb +1 -1
- data/lib/glimmer/dsl/swt/image_expression.rb +18 -3
- data/lib/glimmer/dsl/swt/list_selection_data_binding_expression.rb +11 -8
- data/lib/glimmer/dsl/swt/pixel_expression.rb +1 -1
- data/lib/glimmer/dsl/swt/radio_group_selection_data_binding_expression.rb +9 -5
- data/lib/glimmer/dsl/swt/shape_expression.rb +1 -1
- data/lib/glimmer/dsl/swt/shell_expression.rb +5 -2
- data/lib/glimmer/dsl/swt/widget_expression.rb +8 -4
- data/lib/glimmer/launcher.rb +3 -0
- data/lib/glimmer/rake_task/scaffold.rb +3 -0
- data/lib/glimmer/swt/color_proxy.rb +1 -1
- data/lib/glimmer/swt/custom/code_text.rb +33 -11
- data/lib/glimmer/swt/custom/drawable.rb +50 -2
- data/lib/glimmer/swt/custom/radio_group.rb +2 -1
- data/lib/glimmer/swt/custom/shape.rb +166 -34
- data/lib/glimmer/{dsl/swt/directory_dialog_expression.rb → swt/custom/shape/arc.rb} +15 -20
- data/lib/glimmer/swt/custom/shape/focus.rb +43 -0
- data/lib/glimmer/swt/custom/shape/image.rb +86 -0
- data/lib/glimmer/swt/custom/shape/line.rb +58 -0
- data/lib/glimmer/swt/custom/shape/oval.rb +43 -0
- data/lib/glimmer/swt/custom/shape/point.rb +52 -0
- data/lib/glimmer/swt/custom/shape/polygon.rb +73 -0
- data/lib/glimmer/swt/custom/shape/polyline.rb +73 -0
- data/lib/glimmer/swt/custom/shape/rectangle.rb +87 -0
- data/lib/glimmer/swt/custom/shape/text.rb +73 -0
- data/lib/glimmer/swt/date_time_proxy.rb +9 -3
- data/lib/glimmer/swt/dialog_proxy.rb +92 -0
- data/lib/glimmer/swt/display_proxy.rb +62 -2
- data/lib/glimmer/swt/expand_item_proxy.rb +18 -12
- data/lib/glimmer/swt/font_proxy.rb +13 -7
- data/lib/glimmer/swt/image_proxy.rb +16 -5
- data/lib/glimmer/swt/layout_data_proxy.rb +21 -15
- data/lib/glimmer/swt/layout_proxy.rb +19 -15
- data/lib/glimmer/swt/menu_proxy.rb +2 -2
- data/lib/glimmer/swt/message_box_proxy.rb +21 -7
- data/lib/glimmer/swt/properties.rb +3 -0
- data/lib/glimmer/swt/proxy_properties.rb +145 -0
- data/lib/glimmer/swt/scrolled_composite_proxy.rb +20 -7
- data/lib/glimmer/swt/shell_proxy.rb +96 -80
- data/lib/glimmer/swt/swt_proxy.rb +17 -0
- data/lib/glimmer/swt/tab_item_proxy.rb +6 -3
- data/lib/glimmer/swt/table_proxy.rb +32 -11
- data/lib/glimmer/swt/transform_proxy.rb +26 -38
- data/lib/glimmer/swt/tree_proxy.rb +11 -16
- data/lib/glimmer/swt/widget_listener_proxy.rb +6 -2
- data/lib/glimmer/swt/widget_proxy.rb +194 -137
- data/lib/glimmer/ui.rb +5 -0
- data/lib/glimmer/ui/custom_shell.rb +13 -7
- data/lib/glimmer/ui/custom_widget.rb +4 -5
- data/samples/elaborate/contact_manager.rb +7 -7
- data/samples/elaborate/login.rb +25 -21
- data/samples/elaborate/mandelbrot_fractal.rb +346 -39
- data/samples/elaborate/meta_sample.rb +1 -1
- data/samples/elaborate/tetris.rb +1 -0
- data/samples/elaborate/tic_tac_toe.rb +16 -14
- data/samples/elaborate/tic_tac_toe/board.rb +5 -5
- data/samples/elaborate/tic_tac_toe/cell.rb +5 -5
- data/samples/hello/hello_button.rb +7 -7
- data/samples/hello/hello_canvas.rb +145 -41
- data/samples/hello/hello_checkbox.rb +16 -14
- data/samples/hello/hello_checkbox_group.rb +11 -9
- data/samples/hello/hello_color_dialog.rb +66 -0
- data/samples/hello/hello_combo.rb +14 -12
- data/samples/hello/hello_computed.rb +7 -7
- data/samples/hello/hello_cursor.rb +58 -0
- data/samples/hello/hello_custom_shell.rb +17 -21
- data/samples/hello/hello_custom_widget.rb +4 -6
- data/samples/hello/hello_date_time.rb +14 -12
- data/samples/hello/hello_directory_dialog.rb +7 -7
- data/samples/hello/hello_expand_bar.rb +8 -8
- data/samples/hello/hello_file_dialog.rb +7 -7
- data/samples/hello/hello_font_dialog.rb +82 -0
- data/samples/hello/hello_group.rb +18 -16
- data/samples/hello/hello_list_multi_selection.rb +13 -11
- data/samples/hello/hello_list_single_selection.rb +13 -11
- data/samples/hello/hello_progress_bar.rb +125 -0
- data/samples/hello/hello_radio.rb +18 -16
- data/samples/hello/hello_radio_group.rb +14 -12
- data/samples/hello/hello_spinner.rb +7 -7
- data/samples/hello/hello_tab.rb +5 -5
- data/samples/hello/hello_table.rb +10 -5
- data/samples/hello/hello_tree.rb +485 -0
- metadata +30 -23
- data/lib/glimmer/swt/directory_dialog_proxy.rb +0 -65
- data/lib/glimmer/swt/file_dialog_proxy.rb +0 -66
@@ -27,7 +27,7 @@ class HelloRadioGroup
|
|
27
27
|
attr_accessor :gender, :age_group
|
28
28
|
|
29
29
|
def initialize
|
30
|
-
reset
|
30
|
+
reset!
|
31
31
|
end
|
32
32
|
|
33
33
|
def gender_options
|
@@ -38,17 +38,19 @@ class HelloRadioGroup
|
|
38
38
|
['Child', 'Teen', 'Adult', 'Senior']
|
39
39
|
end
|
40
40
|
|
41
|
-
def reset
|
41
|
+
def reset!
|
42
42
|
self.gender = nil
|
43
43
|
self.age_group = 'Adult'
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
-
include Glimmer
|
47
|
+
include Glimmer::UI::CustomShell
|
48
48
|
|
49
|
-
|
50
|
-
person = Person.new
|
51
|
-
|
49
|
+
before_body {
|
50
|
+
@person = Person.new
|
51
|
+
}
|
52
|
+
|
53
|
+
body {
|
52
54
|
shell {
|
53
55
|
text 'Hello, Radio Group!'
|
54
56
|
row_layout :vertical
|
@@ -60,7 +62,7 @@ class HelloRadioGroup
|
|
60
62
|
|
61
63
|
radio_group {
|
62
64
|
row_layout :horizontal
|
63
|
-
selection bind(person, :gender)
|
65
|
+
selection bind(@person, :gender)
|
64
66
|
}
|
65
67
|
|
66
68
|
label {
|
@@ -70,18 +72,18 @@ class HelloRadioGroup
|
|
70
72
|
|
71
73
|
radio_group {
|
72
74
|
row_layout :horizontal
|
73
|
-
selection bind(person, :age_group)
|
75
|
+
selection bind(@person, :age_group)
|
74
76
|
}
|
75
77
|
|
76
78
|
button {
|
77
79
|
text 'Reset'
|
78
80
|
|
79
81
|
on_widget_selected do
|
80
|
-
person.reset
|
82
|
+
@person.reset!
|
81
83
|
end
|
82
84
|
}
|
83
|
-
}
|
84
|
-
|
85
|
+
}
|
86
|
+
}
|
85
87
|
end
|
86
88
|
|
87
|
-
HelloRadioGroup.
|
89
|
+
HelloRadioGroup.launch
|
@@ -24,14 +24,14 @@ class HelloSpinner
|
|
24
24
|
attr_accessor :donation
|
25
25
|
end
|
26
26
|
|
27
|
-
include Glimmer
|
27
|
+
include Glimmer::UI::CustomShell
|
28
28
|
|
29
|
-
|
29
|
+
before_body {
|
30
30
|
@person = Person.new
|
31
31
|
@person.donation = 500
|
32
|
-
|
32
|
+
}
|
33
33
|
|
34
|
-
|
34
|
+
body {
|
35
35
|
shell {
|
36
36
|
grid_layout
|
37
37
|
|
@@ -62,8 +62,8 @@ class HelloSpinner
|
|
62
62
|
selection bind(@person, :donation) # selection must be set last if other properties are configured to ensure value is within bounds
|
63
63
|
}
|
64
64
|
}
|
65
|
-
}
|
66
|
-
|
65
|
+
}
|
66
|
+
}
|
67
67
|
end
|
68
68
|
|
69
|
-
HelloSpinner.
|
69
|
+
HelloSpinner.launch
|
data/samples/hello/hello_tab.rb
CHANGED
@@ -20,9 +20,9 @@
|
|
20
20
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
21
|
|
22
22
|
class HelloTab
|
23
|
-
include Glimmer
|
23
|
+
include Glimmer::UI::CustomShell
|
24
24
|
|
25
|
-
|
25
|
+
body {
|
26
26
|
shell {
|
27
27
|
text 'Hello, Tab!'
|
28
28
|
|
@@ -43,8 +43,8 @@ class HelloTab
|
|
43
43
|
}
|
44
44
|
}
|
45
45
|
}
|
46
|
-
}
|
47
|
-
|
46
|
+
}
|
47
|
+
}
|
48
48
|
end
|
49
49
|
|
50
|
-
HelloTab.
|
50
|
+
HelloTab.launch
|
@@ -179,14 +179,19 @@ class HelloTable
|
|
179
179
|
end
|
180
180
|
end
|
181
181
|
|
182
|
-
include Glimmer
|
182
|
+
include Glimmer::UI::CustomShell
|
183
183
|
|
184
|
-
|
184
|
+
before_body {
|
185
|
+
Display.app_name = 'Hello, Table!'
|
186
|
+
}
|
187
|
+
|
188
|
+
body {
|
185
189
|
shell {
|
186
190
|
grid_layout
|
187
191
|
|
188
192
|
text 'Hello, Table!'
|
189
193
|
background_image File.expand_path('hello_table/baseball_park.png', __dir__)
|
194
|
+
image File.expand_path('hello_table/baseball_park.png', __dir__)
|
190
195
|
|
191
196
|
label {
|
192
197
|
layout_data :center, :center, true, false
|
@@ -272,8 +277,8 @@ class HelloTable
|
|
272
277
|
book_selected_game
|
273
278
|
}
|
274
279
|
}
|
275
|
-
}
|
276
|
-
|
280
|
+
}
|
281
|
+
}
|
277
282
|
|
278
283
|
def book_selected_game
|
279
284
|
message_box {
|
@@ -283,4 +288,4 @@ class HelloTable
|
|
283
288
|
end
|
284
289
|
end
|
285
290
|
|
286
|
-
HelloTable.
|
291
|
+
HelloTable.launch
|
@@ -0,0 +1,485 @@
|
|
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-dsl-swt'
|
23
|
+
|
24
|
+
class HelloTree
|
25
|
+
EMPLOYEE_ATTRIBUTES = [
|
26
|
+
:first_name, :last_name, :position, :salary,
|
27
|
+
:health_insurance, :desk_location,
|
28
|
+
:sales_bonus_percentage, :merit_bonus,
|
29
|
+
:work_expense, :technology_expense, :travel_expense, :client_expense, :sponsorship_expense, :food_expense, :office_expense,
|
30
|
+
]
|
31
|
+
|
32
|
+
EmployeeStruct ||= Struct.new(*EMPLOYEE_ATTRIBUTES, keyword_init: true)
|
33
|
+
|
34
|
+
class Employee < EmployeeStruct
|
35
|
+
|
36
|
+
NAMES_FIRST = %w[
|
37
|
+
John
|
38
|
+
Noah
|
39
|
+
Bill
|
40
|
+
James
|
41
|
+
Oliver
|
42
|
+
Bob
|
43
|
+
Laura
|
44
|
+
Stephanie
|
45
|
+
Marie
|
46
|
+
Emma
|
47
|
+
Olivia
|
48
|
+
Anna
|
49
|
+
]
|
50
|
+
|
51
|
+
NAMES_LAST = %w[
|
52
|
+
Smith
|
53
|
+
Johnson
|
54
|
+
Williams
|
55
|
+
Brown
|
56
|
+
Jones
|
57
|
+
Harvard
|
58
|
+
Miller
|
59
|
+
Davis
|
60
|
+
Wilson
|
61
|
+
Anderson
|
62
|
+
Taylor
|
63
|
+
Magnus
|
64
|
+
]
|
65
|
+
|
66
|
+
EMPLOYMENT_TYPE_POSITIONS = {
|
67
|
+
'Sales' => 'Sales Person',
|
68
|
+
'HR' => 'HR Staff',
|
69
|
+
'Engineering' => 'Engineer',
|
70
|
+
'Finance' => 'Accountant',
|
71
|
+
}
|
72
|
+
|
73
|
+
SENIORITY_SALARIES = {
|
74
|
+
'Senior' => 111_111,
|
75
|
+
'Standard' => 88_888,
|
76
|
+
'Junior' => 55_555,
|
77
|
+
}
|
78
|
+
|
79
|
+
ALL_HEALTH_INSURANCES = [
|
80
|
+
'Family Plan',
|
81
|
+
'Standard Plan',
|
82
|
+
'Minimal Plan',
|
83
|
+
]
|
84
|
+
|
85
|
+
class << self
|
86
|
+
attr_accessor :selected_employee
|
87
|
+
|
88
|
+
def available_names
|
89
|
+
@available_names ||= NAMES_FIRST.size.times.map { |n| NAMES_FIRST.rotate(n).zip(NAMES_LAST) }.flatten(1)
|
90
|
+
end
|
91
|
+
|
92
|
+
def select_name!
|
93
|
+
available_names.shift
|
94
|
+
end
|
95
|
+
|
96
|
+
def all_desk_locations
|
97
|
+
@all_desk_locations ||= 30.times.map do |n|
|
98
|
+
floor = n + 1
|
99
|
+
[
|
100
|
+
"Floor #{floor} Sales",
|
101
|
+
"Floor #{floor} Engineering",
|
102
|
+
"Floor #{floor} HR",
|
103
|
+
"Floor #{floor} Finance",
|
104
|
+
]
|
105
|
+
end.reduce(:+)
|
106
|
+
end
|
107
|
+
|
108
|
+
def available_desk_locations
|
109
|
+
@available_desk_locations ||= all_desk_locations.clone.reverse
|
110
|
+
end
|
111
|
+
|
112
|
+
def select_desk_location!(type)
|
113
|
+
available_desk_locations.delete(available_desk_locations.detect {|desk_location| desk_location.to_s.end_with?(type)})
|
114
|
+
end
|
115
|
+
|
116
|
+
def ceo
|
117
|
+
@ceo ||= Employee.new(
|
118
|
+
position: 'CEO',
|
119
|
+
salary: 999_999,
|
120
|
+
health_insurance: ALL_HEALTH_INSURANCES[0],
|
121
|
+
desk_location: Employee.select_desk_location!('Sales'),
|
122
|
+
).tap do |employee|
|
123
|
+
employee.subordinates << cto
|
124
|
+
employee.subordinates << cfo
|
125
|
+
employee.subordinates << cio
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def cto
|
130
|
+
@cto ||= Employee.new(
|
131
|
+
position: 'CTO',
|
132
|
+
salary: 777_777,
|
133
|
+
health_insurance: ALL_HEALTH_INSURANCES[0],
|
134
|
+
desk_location: Employee.select_desk_location!('Engineering'),
|
135
|
+
).tap do |employee|
|
136
|
+
employee.subordinates << vp('Engineering')
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def cfo
|
141
|
+
@cfo ||= Employee.new(
|
142
|
+
position: 'CFO',
|
143
|
+
salary: 777_777,
|
144
|
+
health_insurance: ALL_HEALTH_INSURANCES[0],
|
145
|
+
desk_location: Employee.select_desk_location!('Finance'),
|
146
|
+
).tap do |employee|
|
147
|
+
employee.subordinates << vp('Finance')
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def cio
|
152
|
+
@cio ||= Employee.new(
|
153
|
+
position: 'CIO',
|
154
|
+
salary: 777_777,
|
155
|
+
health_insurance: ALL_HEALTH_INSURANCES[0],
|
156
|
+
desk_location: Employee.select_desk_location!('HR'),
|
157
|
+
).tap do |employee|
|
158
|
+
employee.subordinates << vp('Sales')
|
159
|
+
employee.subordinates << vp('HR')
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def vp(type)
|
164
|
+
Employee.new(
|
165
|
+
position: "VP #{type}",
|
166
|
+
salary: 555_555,
|
167
|
+
health_insurance: ALL_HEALTH_INSURANCES[0],
|
168
|
+
desk_location: Employee.select_desk_location!(type),
|
169
|
+
).tap do |employee|
|
170
|
+
2.times { employee.subordinates << director(type) }
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def director(type)
|
175
|
+
Employee.new(
|
176
|
+
position: "Director #{type}",
|
177
|
+
salary: 333_333,
|
178
|
+
health_insurance: ALL_HEALTH_INSURANCES.sample,
|
179
|
+
desk_location: Employee.select_desk_location!(type),
|
180
|
+
).tap do |employee|
|
181
|
+
3.times { employee.subordinates << manager(type) }
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def manager(type)
|
186
|
+
Employee.new(
|
187
|
+
position: "Manager #{type}",
|
188
|
+
salary: 222_222,
|
189
|
+
health_insurance: ALL_HEALTH_INSURANCES.sample,
|
190
|
+
desk_location: Employee.select_desk_location!(type),
|
191
|
+
).tap do |employee|
|
192
|
+
employee.subordinates << employee(type, 'Senior')
|
193
|
+
employee.subordinates << employee(type, 'Standard')
|
194
|
+
employee.subordinates << employee(type, 'Junior')
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def employee(type, seniority)
|
199
|
+
seniority_title = seniority == 'Standard' ? '' : seniority
|
200
|
+
Employee.new(
|
201
|
+
position: "#{seniority_title} #{EMPLOYMENT_TYPE_POSITIONS[type]}",
|
202
|
+
salary: SENIORITY_SALARIES[seniority],
|
203
|
+
health_insurance: ALL_HEALTH_INSURANCES.sample,
|
204
|
+
desk_location: Employee.select_desk_location!(type),
|
205
|
+
)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def initialize(*args)
|
210
|
+
super(*args)
|
211
|
+
determine_type_from_position
|
212
|
+
if first_name.nil? || last_name.nil?
|
213
|
+
name = Employee.select_name!
|
214
|
+
self.first_name = name.first
|
215
|
+
self.last_name = name.last
|
216
|
+
end
|
217
|
+
self.sales_bonus_percentage = (rand*100).to_i if @type == 'Sales'
|
218
|
+
self.merit_bonus = (rand*99_999).to_i
|
219
|
+
[:work_expense, :technology_expense, :travel_expense, :client_expense, :sponsorship_expense, :food_expense, :office_expense].each do |attribute|
|
220
|
+
self.send("#{attribute}=", rand*9_999)
|
221
|
+
end
|
222
|
+
observer = Glimmer::DataBinding::Observer.proc {
|
223
|
+
notify_observers('to_s')
|
224
|
+
}
|
225
|
+
observer.observe(self, :first_name)
|
226
|
+
observer.observe(self, :last_name)
|
227
|
+
observer.observe(self, :position)
|
228
|
+
end
|
229
|
+
|
230
|
+
def determine_type_from_position(specified_position = nil)
|
231
|
+
specified_position ||= position
|
232
|
+
@type = EMPLOYMENT_TYPE_POSITIONS.keys.detect {|key| position.include?(key)}
|
233
|
+
@type = 'Sales' if position == 'CEO'
|
234
|
+
@type = 'Finance' if position == 'CFO'
|
235
|
+
@type = 'HR' if position == 'CIO'
|
236
|
+
@type = 'Engineering' if position == 'CTO'
|
237
|
+
end
|
238
|
+
|
239
|
+
def position_options
|
240
|
+
[
|
241
|
+
'CEO',
|
242
|
+
'CFO',
|
243
|
+
'CIO',
|
244
|
+
'CTO',
|
245
|
+
'VP Sales',
|
246
|
+
'VP HR',
|
247
|
+
'VP Engineering',
|
248
|
+
'VP Finance',
|
249
|
+
'Sales Director',
|
250
|
+
'HR Director',
|
251
|
+
'Engineering Director',
|
252
|
+
'Finance Director',
|
253
|
+
'Sales Manager',
|
254
|
+
'HR Manager',
|
255
|
+
'Engineering Manager',
|
256
|
+
'Finance Manager',
|
257
|
+
'Senior Sales Person',
|
258
|
+
'Sales Person',
|
259
|
+
'Junior Sales Person',
|
260
|
+
'Senior HR Staff',
|
261
|
+
'HR Staff',
|
262
|
+
'Junior HR Staff',
|
263
|
+
'Senior Engineer',
|
264
|
+
'Engineer',
|
265
|
+
'Junior Engineer',
|
266
|
+
'Senior Accountant',
|
267
|
+
'Accountant',
|
268
|
+
'Junior Accountant',
|
269
|
+
]
|
270
|
+
end
|
271
|
+
|
272
|
+
def health_insurance_options
|
273
|
+
ALL_HEALTH_INSURANCES
|
274
|
+
end
|
275
|
+
|
276
|
+
def desk_location_options
|
277
|
+
Employee.all_desk_locations
|
278
|
+
end
|
279
|
+
|
280
|
+
def subordinates
|
281
|
+
@subordinates ||= []
|
282
|
+
end
|
283
|
+
|
284
|
+
def to_s
|
285
|
+
"#{first_name} #{last_name} (#{position})"
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
include Glimmer::UI::CustomShell
|
290
|
+
|
291
|
+
before_body {
|
292
|
+
Employee.selected_employee = Employee.ceo
|
293
|
+
}
|
294
|
+
|
295
|
+
after_body {
|
296
|
+
@tree.items.first.expanded = true
|
297
|
+
}
|
298
|
+
|
299
|
+
body {
|
300
|
+
shell {
|
301
|
+
fill_layout {
|
302
|
+
margin_width 15
|
303
|
+
margin_height 15
|
304
|
+
}
|
305
|
+
text 'Hello, Tree!'
|
306
|
+
minimum_size 900, 600
|
307
|
+
|
308
|
+
sash_form {
|
309
|
+
weights 1, 2
|
310
|
+
|
311
|
+
composite {
|
312
|
+
fill_layout {
|
313
|
+
margin_width 5
|
314
|
+
margin_height 5
|
315
|
+
}
|
316
|
+
@tree = tree {
|
317
|
+
items bind(Employee, :ceo), tree_properties(children: :subordinates, text: :to_s)
|
318
|
+
selection bind(Employee, :selected_employee)
|
319
|
+
}
|
320
|
+
}
|
321
|
+
|
322
|
+
composite {
|
323
|
+
grid_layout 2, false
|
324
|
+
|
325
|
+
label {
|
326
|
+
layout_data(:fill, :center, false, false)
|
327
|
+
text 'First Name:'
|
328
|
+
font height: 16, style: :bold
|
329
|
+
}
|
330
|
+
text {
|
331
|
+
layout_data(:fill, :center, true, false)
|
332
|
+
text bind(Employee, "selected_employee.first_name")
|
333
|
+
font height: 16
|
334
|
+
}
|
335
|
+
|
336
|
+
label {
|
337
|
+
layout_data(:fill, :center, false, false)
|
338
|
+
text 'First Name:'
|
339
|
+
font height: 16, style: :bold
|
340
|
+
}
|
341
|
+
text {
|
342
|
+
layout_data(:fill, :center, true, false)
|
343
|
+
text bind(Employee, "selected_employee.last_name")
|
344
|
+
font height: 16
|
345
|
+
}
|
346
|
+
|
347
|
+
label {
|
348
|
+
layout_data(:fill, :center, false, false)
|
349
|
+
text 'Position:'
|
350
|
+
font height: 16, style: :bold
|
351
|
+
}
|
352
|
+
combo {
|
353
|
+
layout_data(:fill, :center, true, false)
|
354
|
+
selection bind(Employee, "selected_employee.position")
|
355
|
+
font height: 16
|
356
|
+
}
|
357
|
+
|
358
|
+
label {
|
359
|
+
layout_data(:fill, :center, false, false)
|
360
|
+
text 'Salary:'
|
361
|
+
font height: 16, style: :bold
|
362
|
+
}
|
363
|
+
composite {
|
364
|
+
layout_data(:fill, :center, true, false)
|
365
|
+
row_layout {
|
366
|
+
margin_width 0
|
367
|
+
margin_height 0
|
368
|
+
}
|
369
|
+
label {
|
370
|
+
text '$'
|
371
|
+
font height: 20
|
372
|
+
}
|
373
|
+
spinner {
|
374
|
+
maximum 999_999
|
375
|
+
minimum 0
|
376
|
+
selection bind(Employee, "selected_employee.salary")
|
377
|
+
font height: 16
|
378
|
+
}
|
379
|
+
}
|
380
|
+
|
381
|
+
label {
|
382
|
+
layout_data(:fill, :center, false, false)
|
383
|
+
text 'Health Insurance:'
|
384
|
+
font height: 16, style: :bold
|
385
|
+
}
|
386
|
+
combo(:read_only) {
|
387
|
+
layout_data(:fill, :center, true, false)
|
388
|
+
selection bind(Employee, "selected_employee.health_insurance")
|
389
|
+
font height: 16
|
390
|
+
}
|
391
|
+
|
392
|
+
label {
|
393
|
+
layout_data(:fill, :center, false, false)
|
394
|
+
text 'Desk Location:'
|
395
|
+
font height: 16, style: :bold
|
396
|
+
}
|
397
|
+
combo(:read_only) {
|
398
|
+
layout_data(:fill, :center, true, false)
|
399
|
+
selection bind(Employee, "selected_employee.desk_location")
|
400
|
+
font height: 16
|
401
|
+
}
|
402
|
+
|
403
|
+
label {
|
404
|
+
layout_data(:fill, :center, false, false)
|
405
|
+
text 'Sales Bonus Percentage:'
|
406
|
+
font height: 16, style: :bold
|
407
|
+
}
|
408
|
+
composite {
|
409
|
+
layout_data(:fill, :center, true, false)
|
410
|
+
row_layout {
|
411
|
+
margin_width 0
|
412
|
+
margin_height 0
|
413
|
+
}
|
414
|
+
spinner {
|
415
|
+
maximum 100
|
416
|
+
minimum 0
|
417
|
+
selection bind(Employee, "selected_employee.sales_bonus_percentage")
|
418
|
+
font height: 16
|
419
|
+
}
|
420
|
+
label {
|
421
|
+
text '%'
|
422
|
+
font height: 20
|
423
|
+
}
|
424
|
+
}
|
425
|
+
|
426
|
+
label {
|
427
|
+
layout_data(:fill, :center, false, false)
|
428
|
+
text 'Merit Bonus:'
|
429
|
+
font height: 16, style: :bold
|
430
|
+
}
|
431
|
+
composite {
|
432
|
+
layout_data(:fill, :center, true, false)
|
433
|
+
row_layout {
|
434
|
+
margin_width 0
|
435
|
+
margin_height 0
|
436
|
+
}
|
437
|
+
label {
|
438
|
+
text '$'
|
439
|
+
font height: 20
|
440
|
+
}
|
441
|
+
spinner {
|
442
|
+
maximum 999_999
|
443
|
+
minimum 0
|
444
|
+
selection bind(Employee, "selected_employee.merit_bonus")
|
445
|
+
font height: 16
|
446
|
+
}
|
447
|
+
}
|
448
|
+
|
449
|
+
[:work_expense, :technology_expense, :travel_expense, :client_expense, :sponsorship_expense, :food_expense, :office_expense].each do |attribute|
|
450
|
+
label {
|
451
|
+
layout_data(:fill, :center, false, false)
|
452
|
+
text "#{attribute.to_s.split('_').map(&:capitalize).join(' ')}:"
|
453
|
+
font height: 16, style: :bold
|
454
|
+
}
|
455
|
+
composite {
|
456
|
+
layout_data(:fill, :center, true, false)
|
457
|
+
row_layout {
|
458
|
+
margin_width 0
|
459
|
+
margin_height 0
|
460
|
+
}
|
461
|
+
label {
|
462
|
+
text '$'
|
463
|
+
font height: 20
|
464
|
+
}
|
465
|
+
spinner {
|
466
|
+
digits 2
|
467
|
+
maximum 999_999_00
|
468
|
+
minimum 0
|
469
|
+
increment 100
|
470
|
+
selection bind(Employee, "selected_employee.#{attribute}", on_read: ->(v) {v.to_f * 100}, on_write: ->(v) {v.to_f / 100})
|
471
|
+
font height: 16
|
472
|
+
}
|
473
|
+
}
|
474
|
+
end
|
475
|
+
|
476
|
+
}
|
477
|
+
|
478
|
+
}
|
479
|
+
|
480
|
+
}
|
481
|
+
|
482
|
+
}
|
483
|
+
end
|
484
|
+
|
485
|
+
HelloTree.launch
|