glimmer 0.1.10.470 → 0.1.11.SWT4.14
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/README.markdown +13 -3
- data/RELEASE.md +6 -0
- data/VERSION +1 -1
- data/config/swt.yml +5 -0
- data/glimmer.gemspec +12 -9
- data/lib/command_handlers/bind_command_handler.rb +13 -5
- data/lib/command_handlers/combo_selection_data_binding_command_handler.rb +15 -15
- data/lib/command_handlers/data_binding_command_handler.rb +20 -21
- data/lib/command_handlers/list_selection_data_binding_command_handler.rb +15 -15
- data/lib/command_handlers/models/block_observer.rb +13 -0
- data/lib/command_handlers/models/{list_observer.rb → list_selection_binding.rb} +13 -7
- data/lib/command_handlers/models/model_binding.rb +102 -0
- data/lib/command_handlers/models/observable_model.rb +10 -1
- data/lib/command_handlers/models/observer.rb +9 -0
- data/lib/command_handlers/models/{table_items_updater.rb → table_items_binding.rb} +10 -9
- data/lib/command_handlers/models/{tree_items_updater.rb → tree_items_binding.rb} +8 -6
- data/lib/command_handlers/models/{widget_observer.rb → widget_binding.rb} +5 -1
- data/lib/command_handlers/table_items_data_binding_command_handler.rb +4 -4
- data/lib/command_handlers/tree_items_data_binding_command_handler.rb +4 -4
- data/lib/glimmer_application.rb +38 -18
- data/samples/hello_tab.rb +8 -8
- data/spec/lib/glimmer__data_binding__spec.rb +117 -0
- metadata +12 -9
- data/lib/command_handlers/models/model_observer.rb +0 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e969215624dc4b042727fb8cf0ab47397e9b70e499b59df66ce971b45acb54d7
|
4
|
+
data.tar.gz: 84f2da9b3e691d1360d7a9db1345b11a7ecbd00adc15f7c8176fd7ed27023db3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3cc0172f53ed935dfe09ce6dd3f154c563e71c3fa6d403a2772acb5c36d6f2cb06143c8fb77b01590eafa2a0dded33a158977cd805244f603f092540326863ee
|
7
|
+
data.tar.gz: dee9c61db200aeec1573631c4767ad9488d8b806df361e538c665457380ef7f74cdf919b0ff09366a96a1bad5f66113659262fe5fb041b8ce8c2dbe7198f69d9
|
data/README.markdown
CHANGED
@@ -45,7 +45,7 @@ Please follow these instructions to make the `glimmer` command available on your
|
|
45
45
|
|
46
46
|
Add the following to `Gemfile`:
|
47
47
|
```
|
48
|
-
gem 'glimmer', '~> 0.1.
|
48
|
+
gem 'glimmer', '~> 0.1.11.SWT4.14'
|
49
49
|
```
|
50
50
|
|
51
51
|
And, then run:
|
@@ -57,7 +57,7 @@ bundle install
|
|
57
57
|
|
58
58
|
Run this command to get directly:
|
59
59
|
```
|
60
|
-
gem install glimmer -v 0.1.
|
60
|
+
gem install glimmer -v 0.1.11.SWT4.14
|
61
61
|
```
|
62
62
|
|
63
63
|
## Usage
|
@@ -109,11 +109,15 @@ Data-binding is done with `bind` command following widget property to bind and t
|
|
109
109
|
|
110
110
|
Data-binding examples:
|
111
111
|
- `text bind(contact, :first_name)`
|
112
|
+
- `text bind(contact, 'address.street')`
|
112
113
|
- `text bind(contact, :name, computed_by: [:first_name, :last_name])`
|
113
114
|
|
114
115
|
The first example binds the text property of a widget like `label` to the first name of a contact model.
|
115
116
|
|
116
|
-
The second example
|
117
|
+
The second example binds the text property of a widget like `label` to the nested street of
|
118
|
+
the address of a contact. This is called nested property data binding.
|
119
|
+
|
120
|
+
The third example demonstrates computed value data binding whereby the value of `name` depends on changes to both `first_name` and `last_name`
|
117
121
|
|
118
122
|
You may learn more about Glimmer's syntax by reading the Eclipse Zone Tutorial mentioned in resources and opening up the samples under the `samples` folder.
|
119
123
|
|
@@ -170,6 +174,12 @@ Windows is supported by JRuby and the Eclipse SWT library Glimmer runs on. Howev
|
|
170
174
|
|
171
175
|
Same as Windows
|
172
176
|
|
177
|
+
## Feature Suggestions
|
178
|
+
|
179
|
+
These features have been suggested. You might see them in a future version of Glimmer. You are welcome to contribute more feature suggestions.
|
180
|
+
|
181
|
+
- bind_collection: an iterator that enables spawning widgets based on a collection (e.g. spawn 2 `AddressWidget`s if `user.addresses` bind collection contains 2 addresses)
|
182
|
+
|
173
183
|
## Contributing to Glimmer
|
174
184
|
|
175
185
|
Please follow these instructions if you would like to help us develop Glimmer:
|
data/RELEASE.md
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.11.SWT4.14
|
data/config/swt.yml
ADDED
@@ -0,0 +1,5 @@
|
|
1
|
+
SWT:
|
2
|
+
'4.14':
|
3
|
+
mac_x86_64: http://mirror.csclub.uwaterloo.ca/eclipse/eclipse/downloads/drops4/R-4.14-201912100610/swt-4.14-cocoa-macosx-x86_64.zip
|
4
|
+
linux_x86_64: http://mirror.csclub.uwaterloo.ca/eclipse/eclipse/downloads/drops4/R-4.14-201912100610/swt-4.14-gtk-linux-x86_64.zip
|
5
|
+
windows_x86_64: http://mirror.csclub.uwaterloo.ca/eclipse/eclipse/downloads/drops4/R-4.14-201912100610/swt-4.14-win32-win32-x86_64.zip
|
data/glimmer.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: glimmer 0.1.
|
5
|
+
# stub: glimmer 0.1.11.SWT4.14 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "glimmer".freeze
|
9
|
-
s.version = "0.1.
|
9
|
+
s.version = "0.1.11.SWT4.14"
|
10
10
|
|
11
|
-
s.required_rubygems_version = Gem::Requirement.new("
|
11
|
+
s.required_rubygems_version = Gem::Requirement.new("> 1.3.1".freeze) if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib".freeze]
|
13
13
|
s.authors = ["AndyMaleh".freeze]
|
14
|
-
s.date = "
|
14
|
+
s.date = "2020-02-28"
|
15
15
|
s.description = "JRuby Desktop UI DSL + Data-Binding library that enables easy and efficient authoring of user-interfaces using the robust platform-independent Eclipse SWT library".freeze
|
16
16
|
s.email = "andy.am@gmail.com".freeze
|
17
17
|
s.executables = ["glimmer".freeze, "girb".freeze]
|
@@ -34,6 +34,7 @@ Gem::Specification.new do |s|
|
|
34
34
|
"bin/girb",
|
35
35
|
"bin/girb_runner.rb",
|
36
36
|
"bin/glimmer",
|
37
|
+
"config/swt.yml",
|
37
38
|
"glimmer.gemspec",
|
38
39
|
"images/Bitter-sweet.jpg",
|
39
40
|
"lib/command_handler.rb",
|
@@ -44,19 +45,21 @@ Gem::Specification.new do |s|
|
|
44
45
|
"lib/command_handlers/combo_selection_data_binding_command_handler.rb",
|
45
46
|
"lib/command_handlers/data_binding_command_handler.rb",
|
46
47
|
"lib/command_handlers/list_selection_data_binding_command_handler.rb",
|
47
|
-
"lib/command_handlers/models/
|
48
|
-
"lib/command_handlers/models/
|
48
|
+
"lib/command_handlers/models/block_observer.rb",
|
49
|
+
"lib/command_handlers/models/list_selection_binding.rb",
|
50
|
+
"lib/command_handlers/models/model_binding.rb",
|
49
51
|
"lib/command_handlers/models/observable_array.rb",
|
50
52
|
"lib/command_handlers/models/observable_model.rb",
|
53
|
+
"lib/command_handlers/models/observer.rb",
|
51
54
|
"lib/command_handlers/models/r_runnable.rb",
|
52
55
|
"lib/command_handlers/models/r_shell.rb",
|
53
56
|
"lib/command_handlers/models/r_tab_item_composite.rb",
|
54
57
|
"lib/command_handlers/models/r_widget.rb",
|
55
58
|
"lib/command_handlers/models/r_widget_listener.rb",
|
56
59
|
"lib/command_handlers/models/r_widget_packages.rb",
|
57
|
-
"lib/command_handlers/models/
|
58
|
-
"lib/command_handlers/models/
|
59
|
-
"lib/command_handlers/models/
|
60
|
+
"lib/command_handlers/models/table_items_binding.rb",
|
61
|
+
"lib/command_handlers/models/tree_items_binding.rb",
|
62
|
+
"lib/command_handlers/models/widget_binding.rb",
|
60
63
|
"lib/command_handlers/shell_command_handler.rb",
|
61
64
|
"lib/command_handlers/tab_item_command_handler.rb",
|
62
65
|
"lib/command_handlers/table_column_properties_data_binding_command_handler.rb",
|
@@ -1,9 +1,9 @@
|
|
1
1
|
require File.dirname(__FILE__) + "/../command_handler"
|
2
2
|
require File.dirname(__FILE__) + "/models/r_widget"
|
3
|
-
require File.dirname(__FILE__) + "/models/
|
3
|
+
require File.dirname(__FILE__) + "/models/model_binding"
|
4
4
|
|
5
5
|
# Responsible for setting up the return value of the bind keyword (command symbol)
|
6
|
-
# as a
|
6
|
+
# as a ModelBinding. It is then used by another command handler like
|
7
7
|
# DataBindingCommandHandler for text and selection properties on Text and Spinner
|
8
8
|
# or TableItemsDataBindingCommandHandler for items in a Table
|
9
9
|
class BindCommandHandler
|
@@ -41,9 +41,17 @@ class BindCommandHandler
|
|
41
41
|
|
42
42
|
def do_handle(parent, command_symbol, *args, &block)
|
43
43
|
property_type = args[2] if (args.size == 3) && !args[2].is_a?(Hash)
|
44
|
-
|
45
|
-
|
46
|
-
|
44
|
+
binding_options = args[2] if args[2].is_a?(Hash)
|
45
|
+
binding_options = args[3] if args[3].is_a?(Hash)
|
46
|
+
ModelBinding.new(args[0], args[1].to_s, property_type, binding_options)
|
47
|
+
#TODO replace ModelObserver with something else. It's inaccurate
|
48
|
+
# it doesn't observe the model, it updates it, observing the widget
|
49
|
+
# yet also contains information about observing the model, like the property
|
50
|
+
# to observe. That's the real object spit out here. Must name is something else.
|
51
|
+
# Maybe call ModelBinding and spin off Observer as ModelPropertyUpdateCommand
|
52
|
+
# similarly create a WidgetPropertyUpdateCommand (execute not update method)
|
53
|
+
# Have an observer be a general thin skeleton with an update method instead.
|
54
|
+
# In the future, switch observer to a simple block.
|
47
55
|
end
|
48
56
|
|
49
57
|
end
|
@@ -4,7 +4,7 @@ require File.dirname(__FILE__) + "/models/r_widget"
|
|
4
4
|
class ComboSelectionDataBindingCommandHandler
|
5
5
|
include CommandHandler
|
6
6
|
include Glimmer
|
7
|
-
|
7
|
+
|
8
8
|
include_package 'org.eclipse.swt.widgets'
|
9
9
|
|
10
10
|
def can_handle?(parent, command_symbol, *args, &block)
|
@@ -12,28 +12,28 @@ class ComboSelectionDataBindingCommandHandler
|
|
12
12
|
parent.widget.is_a?(Combo) and
|
13
13
|
command_symbol.to_s == "selection" and
|
14
14
|
args.size == 1 and
|
15
|
-
args[0].is_a?(
|
15
|
+
args[0].is_a?(ModelBinding) and
|
16
16
|
args[0].evaluate_options_property.is_a?(Array) and
|
17
17
|
block == nil
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
def do_handle(parent, command_symbol, *args, &block)
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
model =
|
21
|
+
model_binding = args[0]
|
22
|
+
widget_binding = WidgetBinding.new(parent, "items")
|
23
|
+
widget_binding.update(model_binding.evaluate_options_property)
|
24
|
+
model = model_binding.base_model
|
25
25
|
model.extend ObservableModel unless model.is_a?(ObservableModel)
|
26
|
-
model.add_observer(
|
26
|
+
model.add_observer(model_binding.options_property_name, widget_binding)
|
27
|
+
|
28
|
+
widget_binding = WidgetBinding.new(parent, "text")
|
29
|
+
widget_binding.update(model_binding.evaluate_property)
|
30
|
+
model.add_observer(model_binding.property_name_expression, widget_binding)
|
27
31
|
|
28
|
-
widget_observer = WidgetObserver.new(parent, "text")
|
29
|
-
widget_observer.update(model_observer.evaluate_property)
|
30
|
-
model.add_observer(model_observer.property_name, widget_observer)
|
31
|
-
|
32
32
|
add_contents(parent) {
|
33
33
|
on_widget_selected {
|
34
|
-
|
34
|
+
model_binding.update(widget_binding.evaluate_property)
|
35
35
|
}
|
36
|
-
}
|
36
|
+
}
|
37
37
|
end
|
38
38
|
|
39
|
-
end
|
39
|
+
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
require File.dirname(__FILE__) + "/../command_handler"
|
2
2
|
require File.dirname(__FILE__) + "/models/r_widget"
|
3
3
|
require File.dirname(__FILE__) + "/models/observable_model"
|
4
|
-
require File.dirname(__FILE__) + "/models/
|
5
|
-
require File.dirname(__FILE__) + "/models/
|
4
|
+
require File.dirname(__FILE__) + "/models/model_binding"
|
5
|
+
require File.dirname(__FILE__) + "/models/widget_binding"
|
6
6
|
|
7
7
|
# Responsible for wiring two-way data-binding for text and selection properties
|
8
8
|
# on Text, Button, and Spinner widgets.
|
9
9
|
# Does so by using the output of the bind(model, property) command in the form
|
10
|
-
# of a
|
10
|
+
# of a ModelBinding, which is then connected to an anonymous widget observer
|
11
11
|
# (aka widget_data_binder as per widget_data_binders array)
|
12
12
|
#
|
13
13
|
# Depends on BindCommandHandler
|
@@ -19,28 +19,28 @@ class DataBindingCommandHandler
|
|
19
19
|
|
20
20
|
@@widget_data_binders = {
|
21
21
|
Java::OrgEclipseSwtWidgets::Text => {
|
22
|
-
:text => Proc.new do |rwidget,
|
22
|
+
:text => Proc.new do |rwidget, model_binding|
|
23
23
|
add_contents(rwidget) {
|
24
24
|
on_modify_text { |modify_event|
|
25
|
-
|
25
|
+
model_binding.update(rwidget.widget.getText)
|
26
26
|
}
|
27
27
|
}
|
28
28
|
end,
|
29
29
|
},
|
30
30
|
Java::OrgEclipseSwtWidgets::Button => {
|
31
|
-
:selection => Proc.new do |rwidget,
|
31
|
+
:selection => Proc.new do |rwidget, model_binding|
|
32
32
|
add_contents(rwidget) {
|
33
33
|
on_widget_selected { |selection_event|
|
34
|
-
|
34
|
+
model_binding.update(rwidget.widget.getSelection)
|
35
35
|
}
|
36
36
|
}
|
37
37
|
end
|
38
38
|
},
|
39
39
|
Java::OrgEclipseSwtWidgets::Spinner => {
|
40
|
-
:selection => Proc.new do |rwidget,
|
40
|
+
:selection => Proc.new do |rwidget, model_binding|
|
41
41
|
add_contents(rwidget) {
|
42
42
|
on_widget_selected { |selection_event|
|
43
|
-
|
43
|
+
model_binding.update(rwidget.widget.getSelection)
|
44
44
|
}
|
45
45
|
}
|
46
46
|
end
|
@@ -50,25 +50,24 @@ class DataBindingCommandHandler
|
|
50
50
|
def can_handle?(parent, command_symbol, *args, &block)
|
51
51
|
(parent.is_a?(RWidget) and
|
52
52
|
args.size == 1 and
|
53
|
-
args[0].is_a?(
|
53
|
+
args[0].is_a?(ModelBinding))
|
54
54
|
end
|
55
55
|
|
56
56
|
def do_handle(parent, command_symbol, *args, &block)
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
model =
|
63
|
-
|
64
|
-
|
65
|
-
computed_by_property_names = model_observer.observer_options[:computed_by]
|
57
|
+
model_binding = args[0]
|
58
|
+
widget_binding_parameters = [parent, command_symbol.to_s]
|
59
|
+
widget_binding_parameters << proc {|value| model_binding.evaluate_property} if model_binding.binding_options.has_key?(:computed_by)
|
60
|
+
widget_binding = WidgetBinding.new(*widget_binding_parameters)
|
61
|
+
widget_binding.update(model_binding.evaluate_property)
|
62
|
+
model = model_binding.model
|
63
|
+
model_binding.add_observer(widget_binding)
|
64
|
+
computed_by_property_names = model_binding.binding_options[:computed_by]
|
66
65
|
computed_by_property_names&.each do |computed_by_property_name|
|
67
|
-
model.add_observer(computed_by_property_name,
|
66
|
+
model.add_observer(computed_by_property_name, widget_binding)
|
68
67
|
end
|
69
68
|
widget_data_binder_map = @@widget_data_binders[parent.widget.class]
|
70
69
|
widget_data_binder = widget_data_binder_map[command_symbol.to_s.to_sym] if widget_data_binder_map
|
71
|
-
widget_data_binder.call(parent,
|
70
|
+
widget_data_binder.call(parent, model_binding) if widget_data_binder
|
72
71
|
end
|
73
72
|
|
74
73
|
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
require File.dirname(__FILE__) + "/../command_handler"
|
2
2
|
require File.dirname(__FILE__) + "/models/r_widget"
|
3
|
-
require File.dirname(__FILE__) + "/models/
|
3
|
+
require File.dirname(__FILE__) + "/models/list_selection_binding"
|
4
4
|
|
5
5
|
class ListSelectionDataBindingCommandHandler
|
6
6
|
include CommandHandler
|
7
7
|
include Glimmer
|
8
|
-
|
8
|
+
|
9
9
|
include_package 'org.eclipse.swt.widgets'
|
10
10
|
|
11
11
|
def can_handle?(parent, command_symbol, *args, &block)
|
@@ -13,30 +13,30 @@ class ListSelectionDataBindingCommandHandler
|
|
13
13
|
parent.widget.is_a?(List) and
|
14
14
|
command_symbol.to_s == "selection" and
|
15
15
|
args.size == 1 and
|
16
|
-
args[0].is_a?(
|
16
|
+
args[0].is_a?(ModelBinding) and
|
17
17
|
args[0].evaluate_options_property.is_a?(Array) and
|
18
18
|
block == nil
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
def do_handle(parent, command_symbol, *args, &block)
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
model =
|
22
|
+
model_binding = args[0]
|
23
|
+
widget_binding = WidgetBinding.new(parent, "items")
|
24
|
+
widget_binding.update(model_binding.evaluate_options_property)
|
25
|
+
model = model_binding.base_model
|
26
26
|
model.extend ObservableModel unless model.is_a?(ObservableModel)
|
27
|
-
model.add_observer(
|
27
|
+
model.add_observer(model_binding.options_property_name, widget_binding)
|
28
28
|
|
29
29
|
property_type = :string
|
30
30
|
property_type = :array if parent.has_style?(:multi)
|
31
|
-
|
32
|
-
|
33
|
-
model.add_observer(
|
34
|
-
|
31
|
+
list_selection_binding = ListSelectionBinding.new(parent, property_type)
|
32
|
+
list_selection_binding.update(model_binding.evaluate_property)
|
33
|
+
model.add_observer(model_binding.property_name_expression, list_selection_binding)
|
34
|
+
|
35
35
|
add_contents(parent) {
|
36
36
|
on_widget_selected {
|
37
|
-
|
37
|
+
model_binding.update(list_selection_binding.evaluate_property)
|
38
38
|
}
|
39
39
|
}
|
40
40
|
end
|
41
41
|
|
42
|
-
end
|
42
|
+
end
|
@@ -1,25 +1,32 @@
|
|
1
|
-
|
1
|
+
require File.dirname(__FILE__) + "/observer"
|
2
|
+
|
3
|
+
# SWT List widget selection binding
|
4
|
+
class ListSelectionBinding
|
5
|
+
include Observer
|
6
|
+
|
2
7
|
attr_reader :widget
|
3
8
|
@@property_type_updaters = {
|
4
|
-
:string => lambda { |widget, value| widget.widget.select(widget.widget.index_of(value.to_s)) },
|
9
|
+
:string => lambda { |widget, value| widget.widget.select(widget.widget.index_of(value.to_s)) },
|
5
10
|
:array => lambda { |widget, value| widget.widget.selection=((value or []).to_java :string) }
|
6
11
|
}
|
7
12
|
@@property_evaluators = {
|
8
|
-
:string => lambda do |selection_array|
|
13
|
+
:string => lambda do |selection_array|
|
9
14
|
return nil if selection_array.empty?
|
10
15
|
selection_array[0]
|
11
|
-
end,
|
12
|
-
:array => lambda do |selection_array|
|
16
|
+
end,
|
17
|
+
:array => lambda do |selection_array|
|
13
18
|
selection_array
|
14
19
|
end
|
15
20
|
}
|
21
|
+
# Initialize with list widget and property_type
|
22
|
+
# property_type :string represents default list single selection
|
23
|
+
# property_type :array represents list multi selection
|
16
24
|
def initialize(widget, property_type)
|
17
25
|
property_type = :string if property_type.nil? or property_type == :undefined
|
18
26
|
@widget = widget
|
19
27
|
@property_type = property_type
|
20
28
|
end
|
21
29
|
def update(value)
|
22
|
-
raise "hell" if value == ["Canada"]
|
23
30
|
@@property_type_updaters[@property_type].call(@widget, value) unless evaluate_property == value
|
24
31
|
end
|
25
32
|
def evaluate_property
|
@@ -28,4 +35,3 @@ class ListObserver
|
|
28
35
|
return property_value
|
29
36
|
end
|
30
37
|
end
|
31
|
-
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/observer"
|
2
|
+
|
3
|
+
class ModelBinding
|
4
|
+
include Observer
|
5
|
+
|
6
|
+
attr_reader :property_type, :binding_options
|
7
|
+
@@property_type_converters = {
|
8
|
+
:undefined => lambda { |value| value },
|
9
|
+
:fixnum => lambda { |value| value.to_i },
|
10
|
+
:array => lambda { |value| value.to_a }
|
11
|
+
}
|
12
|
+
def initialize(base_model, property_name_expression, property_type = :undefined, binding_options = nil)
|
13
|
+
property_type = :undefined if property_type.nil?
|
14
|
+
@base_model = base_model
|
15
|
+
@property_name_expression = property_name_expression
|
16
|
+
@property_type = property_type
|
17
|
+
@binding_options = binding_options || {}
|
18
|
+
end
|
19
|
+
def model
|
20
|
+
nested_property? ? nested_model : base_model
|
21
|
+
end
|
22
|
+
# e.g. person.address.state returns [person, person.address]
|
23
|
+
def nested_models
|
24
|
+
@nested_models = [base_model]
|
25
|
+
model_property_names.reduce(base_model) do |reduced_model, nested_model_property_name|
|
26
|
+
reduced_model.send(nested_model_property_name).tap do |new_reduced_model|
|
27
|
+
@nested_models << new_reduced_model
|
28
|
+
end
|
29
|
+
end
|
30
|
+
@nested_models
|
31
|
+
end
|
32
|
+
def nested_model
|
33
|
+
nested_models.last
|
34
|
+
end
|
35
|
+
def base_model
|
36
|
+
@base_model
|
37
|
+
end
|
38
|
+
def property_name
|
39
|
+
nested_property? ? nested_property_name : property_name_expression
|
40
|
+
end
|
41
|
+
# All nested property names
|
42
|
+
# e.g. property name expression "address.state" gives [:address, :state]
|
43
|
+
def nested_property_names
|
44
|
+
property_name_expression.split(".")
|
45
|
+
end
|
46
|
+
# Final nested property name
|
47
|
+
# e.g. property name expression "address.state" gives :state
|
48
|
+
def nested_property_name
|
49
|
+
nested_property_names.last
|
50
|
+
end
|
51
|
+
# Model representing nested property names
|
52
|
+
# e.g. property name expression "address.state" gives [:address]
|
53
|
+
def model_property_names
|
54
|
+
nested_property_names[0...-1]
|
55
|
+
end
|
56
|
+
def nested_property?
|
57
|
+
property_name_expression.include?(".")
|
58
|
+
end
|
59
|
+
def property_name_expression
|
60
|
+
@property_name_expression
|
61
|
+
end
|
62
|
+
def nested_property_observers_for(observer)
|
63
|
+
@nested_property_observers_collection ||= {}
|
64
|
+
unless @nested_property_observers_collection.has_key?(observer)
|
65
|
+
@nested_property_observers_collection[observer] = nested_property_names.reduce({}) do |output, property_name|
|
66
|
+
output.merge(
|
67
|
+
property_name => BlockObserver.new do |changed_value|
|
68
|
+
# Ensure reattaching observers when a higher level nested property is updated (e.g. person.address changes reattaches person.address.street observer)
|
69
|
+
add_observer(observer)
|
70
|
+
observer.update(evaluate_property)
|
71
|
+
end
|
72
|
+
)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
@nested_property_observers_collection[observer]
|
76
|
+
end
|
77
|
+
def add_observer(observer)
|
78
|
+
if nested_property?
|
79
|
+
nested_property_observers = nested_property_observers_for(observer)
|
80
|
+
nested_models.zip(nested_property_names).each do |model, property_name|
|
81
|
+
model.extend ObservableModel unless model.is_a?(ObservableModel)
|
82
|
+
model.add_observer(property_name, nested_property_observers[property_name]) unless model.has_observer?(property_name, nested_property_observers[property_name])
|
83
|
+
end
|
84
|
+
else
|
85
|
+
model.extend ObservableModel unless model.is_a?(ObservableModel)
|
86
|
+
model.add_observer(property_name, observer)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
def update(value)
|
90
|
+
converted_value = @@property_type_converters[@property_type].call(value)
|
91
|
+
model.send(property_name + "=", converted_value) unless evaluate_property == converted_value
|
92
|
+
end
|
93
|
+
def evaluate_property
|
94
|
+
model.send(property_name)
|
95
|
+
end
|
96
|
+
def evaluate_options_property
|
97
|
+
model.send(property_name + "_options")
|
98
|
+
end
|
99
|
+
def options_property_name
|
100
|
+
self.property_name + "_options"
|
101
|
+
end
|
102
|
+
end
|
@@ -1,10 +1,19 @@
|
|
1
1
|
require 'set'
|
2
|
+
|
3
|
+
require File.dirname(__FILE__) + "/block_observer"
|
4
|
+
|
2
5
|
module ObservableModel
|
3
6
|
|
4
|
-
|
7
|
+
# Takes observer as an object or a block updater
|
8
|
+
def add_observer(property_name, observer = nil, &updater)
|
9
|
+
observer ||= BlockObserver.new(&updater)
|
5
10
|
property_observer_list(property_name) << observer
|
6
11
|
end
|
7
12
|
|
13
|
+
def has_observer?(property_name, observer)
|
14
|
+
property_observer_list(property_name).include?(observer)
|
15
|
+
end
|
16
|
+
|
8
17
|
def property_observer_hash
|
9
18
|
@property_observers = Hash.new unless @property_observers
|
10
19
|
@property_observers
|
@@ -1,18 +1,20 @@
|
|
1
1
|
require File.dirname(__FILE__) + "/observable_array"
|
2
2
|
require File.dirname(__FILE__) + "/observable_model"
|
3
|
+
require File.dirname(__FILE__) + "/observer"
|
3
4
|
|
4
|
-
class
|
5
|
+
class TableItemsBinding
|
6
|
+
include Observer
|
5
7
|
include_package 'org.eclipse.swt'
|
6
8
|
include_package 'org.eclipse.swt.widgets'
|
7
|
-
|
8
|
-
def initialize(parent,
|
9
|
+
|
10
|
+
def initialize(parent, model_binding, column_properties)
|
9
11
|
@table = parent
|
10
|
-
@
|
12
|
+
@model_binding = model_binding
|
11
13
|
@column_properties = column_properties
|
12
|
-
update(@
|
13
|
-
model =
|
14
|
+
update(@model_binding.evaluate_property)
|
15
|
+
model = model_binding.base_model
|
14
16
|
model.extend(ObservableModel) unless model.is_a?(ObservableModel)
|
15
|
-
model.add_observer(
|
17
|
+
model.add_observer(model_binding.property_name_expression, self)
|
16
18
|
end
|
17
19
|
def update(model_collection=nil)
|
18
20
|
if model_collection and model_collection.is_a?(Array)
|
@@ -31,6 +33,5 @@ class TableItemsUpdater
|
|
31
33
|
end
|
32
34
|
end
|
33
35
|
end
|
34
|
-
|
36
|
+
|
35
37
|
end
|
36
|
-
|
@@ -1,18 +1,20 @@
|
|
1
1
|
require File.dirname(__FILE__) + "/observable_array"
|
2
2
|
require File.dirname(__FILE__) + "/observable_model"
|
3
|
+
require File.dirname(__FILE__) + "/observer"
|
3
4
|
|
4
|
-
class
|
5
|
+
class TreeItemsBinding
|
6
|
+
include Observer
|
5
7
|
include_package 'org.eclipse.swt'
|
6
8
|
include_package 'org.eclipse.swt.widgets'
|
7
9
|
|
8
|
-
def initialize(parent,
|
10
|
+
def initialize(parent, model_binding, tree_properties)
|
9
11
|
@tree = parent
|
10
|
-
@
|
12
|
+
@model_binding = model_binding
|
11
13
|
@tree_properties = [tree_properties].flatten.first.to_h
|
12
|
-
update(@
|
13
|
-
model =
|
14
|
+
update(@model_binding.evaluate_property)
|
15
|
+
model = model_binding.base_model
|
14
16
|
model.extend(ObservableModel) unless model.is_a?(ObservableModel)
|
15
|
-
model.add_observer(
|
17
|
+
model.add_observer(model_binding.property_name_expression, self)
|
16
18
|
end
|
17
19
|
def update(model_tree_root_node=nil)
|
18
20
|
if model_tree_root_node and model_tree_root_node.respond_to?(@tree_properties[:children])
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require File.dirname(__FILE__) + "/../command_handler"
|
2
2
|
require File.dirname(__FILE__) + "/models/r_widget"
|
3
|
-
require File.dirname(__FILE__) + "/models/
|
3
|
+
require File.dirname(__FILE__) + "/models/table_items_binding"
|
4
4
|
|
5
5
|
#Depends on BindCommandHandler and TableColumnPropertiesDataBindingCommandHandler
|
6
6
|
class TableItemsDataBindingCommandHandler
|
@@ -13,16 +13,16 @@ class TableItemsDataBindingCommandHandler
|
|
13
13
|
parent.widget.is_a?(Table) and
|
14
14
|
command_symbol.to_s == "items" and
|
15
15
|
args.size == 2 and
|
16
|
-
args[0].is_a?(
|
16
|
+
args[0].is_a?(ModelBinding) and
|
17
17
|
args[0].evaluate_property.is_a?(Array) and
|
18
18
|
args[1].is_a?(Array) and
|
19
19
|
block == nil
|
20
20
|
end
|
21
21
|
|
22
22
|
def do_handle(parent, command_symbol, *args, &block)
|
23
|
-
|
23
|
+
model_binding = args[0]
|
24
24
|
column_properties = args[1]
|
25
|
-
|
25
|
+
TableItemsBinding.new(parent, model_binding, column_properties)
|
26
26
|
end
|
27
27
|
|
28
28
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require File.dirname(__FILE__) + "/../command_handler"
|
2
2
|
require File.dirname(__FILE__) + "/models/r_widget"
|
3
|
-
require File.dirname(__FILE__) + "/models/
|
3
|
+
require File.dirname(__FILE__) + "/models/tree_items_binding"
|
4
4
|
|
5
5
|
class TreeItemsDataBindingCommandHandler
|
6
6
|
include CommandHandler
|
@@ -12,16 +12,16 @@ class TreeItemsDataBindingCommandHandler
|
|
12
12
|
(parent.widget.is_a?(Tree)) and
|
13
13
|
(command_symbol.to_s == "items") and
|
14
14
|
(args.size == 2) and
|
15
|
-
(args[0].is_a?(
|
15
|
+
(args[0].is_a?(ModelBinding)) and
|
16
16
|
(!args[0].evaluate_property.is_a?(Array)) and
|
17
17
|
(args[1].is_a?(Array) && !args[1].empty? && args[1].first.is_a?(Hash)) and
|
18
18
|
(block == nil)
|
19
19
|
end
|
20
20
|
|
21
21
|
def do_handle(parent, command_symbol, *args, &block)
|
22
|
-
|
22
|
+
model_binding = args[0]
|
23
23
|
tree_properties = args[1]
|
24
|
-
|
24
|
+
TreeItemsBinding.new(parent, model_binding, tree_properties)
|
25
25
|
end
|
26
26
|
|
27
27
|
end
|
data/lib/glimmer_application.rb
CHANGED
@@ -1,22 +1,21 @@
|
|
1
1
|
require 'net/http'
|
2
2
|
require 'fileutils'
|
3
3
|
require 'os'
|
4
|
+
require 'yaml'
|
4
5
|
|
5
6
|
class GlimmerApplication
|
6
7
|
SWT_ZIP_FILE = File.join(`echo ~`.strip, '.glimmer', 'vendor', 'swt.zip')
|
7
8
|
SWT_JAR_FILE = File.join(File.dirname(SWT_ZIP_FILE), 'swt.jar')
|
8
9
|
|
9
10
|
OPERATING_SYSTEMS = ["mac", "windows", "linux"]
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
attr_reader :setup_requested, :application
|
11
|
+
REGEX_SETUP = /--setup/
|
12
|
+
REGEX_SWT_VERSION = /[0-9]+[.0-9]*/
|
13
|
+
REGEX_APPLICATION = /.+/
|
14
|
+
REGEX_OPTIONS = [
|
15
|
+
REGEX_SETUP, REGEX_SWT_VERSION, REGEX_APPLICATION
|
16
|
+
].map {|re| "(#{re})?"}.join("\s*")
|
17
|
+
|
18
|
+
attr_reader :setup_requested, :swt_version_specified, :application
|
20
19
|
alias :setup_requested? :setup_requested
|
21
20
|
|
22
21
|
# Accepts the following options string:
|
@@ -26,8 +25,10 @@ class GlimmerApplication
|
|
26
25
|
# or
|
27
26
|
# app_file_path.rb
|
28
27
|
def initialize(options)
|
29
|
-
|
30
|
-
@
|
28
|
+
options_regex_match = options.join(' ').match(REGEX_OPTIONS)
|
29
|
+
@setup_requested = !!options_regex_match[1]
|
30
|
+
@swt_version_specified = options_regex_match[2]
|
31
|
+
@application = options_regex_match[3]
|
31
32
|
end
|
32
33
|
|
33
34
|
def start
|
@@ -35,7 +36,7 @@ class GlimmerApplication
|
|
35
36
|
|
36
37
|
setup if setup_requested? || !File.exist?(SWT_JAR_FILE)
|
37
38
|
|
38
|
-
if application
|
39
|
+
if application && File.exist?(SWT_JAR_FILE)
|
39
40
|
puts "Starting Glimmer Application #{application}"
|
40
41
|
system "ruby #{additional_options} -J-classpath \"#{SWT_JAR_FILE}\" #{application}"
|
41
42
|
end
|
@@ -43,18 +44,21 @@ class GlimmerApplication
|
|
43
44
|
|
44
45
|
def usage
|
45
46
|
puts <<-MULTILINE
|
46
|
-
Usage: glimmer [--setup] [application_ruby_file_path.rb]
|
47
|
+
Usage: glimmer [--setup] [SWT_VERSION] [application_ruby_file_path.rb]
|
47
48
|
|
48
49
|
Example 1: glimmer hello_combo.rb
|
49
50
|
This runs the Glimmer application hello_combo.rb
|
50
|
-
If the SWT Jar is missing, it downloads
|
51
|
+
If the SWT Jar is missing, it first downloads the latest version supported.
|
51
52
|
|
52
53
|
Example 2: glimmer --setup hello_combo.rb
|
53
54
|
This performs setup and then runs the Glimmer application hello_combo.rb
|
54
|
-
It downloads and sets up the SWT jar whether missing or not.
|
55
|
+
It downloads and sets up the latest SWT jar whether missing or not.
|
55
56
|
|
56
57
|
Example 3: glimmer --setup
|
57
|
-
This downloads and sets up the SWT jar whether missing or not.
|
58
|
+
This downloads and sets up the latest SWT jar whether missing or not.
|
59
|
+
|
60
|
+
Example 4: glimmer --setup 4.14
|
61
|
+
This downloads and sets up the SWT jar specified version 4.14 whether missing or not.
|
58
62
|
MULTILINE
|
59
63
|
end
|
60
64
|
|
@@ -65,6 +69,8 @@ This downloads and sets up the SWT jar whether missing or not.
|
|
65
69
|
puts "Unzipping #{SWT_ZIP_FILE}"
|
66
70
|
`unzip -o #{SWT_ZIP_FILE} -d #{File.dirname(SWT_ZIP_FILE)}`
|
67
71
|
puts "Finished unzipping"
|
72
|
+
rescue => e
|
73
|
+
puts e.message
|
68
74
|
end
|
69
75
|
|
70
76
|
def download(file)
|
@@ -77,7 +83,21 @@ This downloads and sets up the SWT jar whether missing or not.
|
|
77
83
|
end
|
78
84
|
|
79
85
|
def platform_swt_url
|
80
|
-
|
86
|
+
swt_config[swt_version][platform_swt_url_key]
|
87
|
+
rescue
|
88
|
+
raise "SWT version #{swt_version} is not available for download!"
|
89
|
+
end
|
90
|
+
|
91
|
+
def swt_config
|
92
|
+
@swt_config ||= YAML.load_file(File.join(__FILE__, '..', '..', 'config', 'swt.yml'))['SWT']
|
93
|
+
end
|
94
|
+
|
95
|
+
def swt_version
|
96
|
+
swt_version_specified || swt_latest_version
|
97
|
+
end
|
98
|
+
|
99
|
+
def swt_latest_version
|
100
|
+
@swt_latest_version ||= swt_config.keys.max_by {|v| v.split('.').reverse.map(&:to_i).each_with_index.map {|n, i| n*(1000**i)}.sum}
|
81
101
|
end
|
82
102
|
|
83
103
|
def platform_swt_url_key
|
data/samples/hello_tab.rb
CHANGED
@@ -4,18 +4,18 @@ class HelloTab
|
|
4
4
|
include Glimmer
|
5
5
|
def launch
|
6
6
|
shell {
|
7
|
-
text "
|
7
|
+
text "Hello Tab"
|
8
8
|
tab_folder {
|
9
9
|
tab_item {
|
10
|
-
text "
|
11
|
-
label {
|
12
|
-
text "Hello World!"
|
10
|
+
text "English"
|
11
|
+
label {
|
12
|
+
text "Hello World!"
|
13
13
|
}
|
14
14
|
}
|
15
15
|
tab_item {
|
16
|
-
text "
|
17
|
-
label {
|
18
|
-
text "Bonjour Univers!"
|
16
|
+
text "French"
|
17
|
+
label {
|
18
|
+
text "Bonjour Univers!"
|
19
19
|
}
|
20
20
|
}
|
21
21
|
}
|
@@ -23,4 +23,4 @@ class HelloTab
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
-
HelloTab.new.launch
|
26
|
+
HelloTab.new.launch
|
@@ -31,6 +31,14 @@ describe "Glimmer Data Binding" do
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
+
class Address
|
35
|
+
attr_accessor :street, :city, :state, :zip
|
36
|
+
end
|
37
|
+
|
38
|
+
class PersonWithNestedProperties
|
39
|
+
attr_accessor :address1, :address2
|
40
|
+
end
|
41
|
+
|
34
42
|
it "tests text widget data binding string property" do
|
35
43
|
person = Person.new
|
36
44
|
person.name = "Bruce Ting"
|
@@ -284,4 +292,113 @@ describe "Glimmer Data Binding" do
|
|
284
292
|
expect(person.adult).to eq(true)
|
285
293
|
end
|
286
294
|
|
295
|
+
context "nested data binding" do
|
296
|
+
|
297
|
+
it "tests text widget data binding to nested string property" do
|
298
|
+
person = PersonWithNestedProperties.new
|
299
|
+
person.address1 = Address.new
|
300
|
+
person.address2 = Address.new
|
301
|
+
|
302
|
+
person.address1.street = "20 Naper Ave"
|
303
|
+
person.address1.city = "Indianapolis"
|
304
|
+
person.address1.state = "IN"
|
305
|
+
person.address1.zip = "46183"
|
306
|
+
|
307
|
+
person.address2.street = "101 Confession St"
|
308
|
+
person.address2.city = "Denver"
|
309
|
+
person.address2.state = "CO"
|
310
|
+
person.address2.zip = "80014"
|
311
|
+
|
312
|
+
@target = shell {
|
313
|
+
composite {
|
314
|
+
@address1_street_text_widget = text {
|
315
|
+
text bind(person, "address1.street")
|
316
|
+
}
|
317
|
+
@address1_city_text_widget = text {
|
318
|
+
text bind(person, "address1.city")
|
319
|
+
}
|
320
|
+
@address1_state_text_widget = text {
|
321
|
+
text bind(person, "address1.state")
|
322
|
+
}
|
323
|
+
@address1_zip_text_widget = text {
|
324
|
+
text bind(person, "address1.zip")
|
325
|
+
}
|
326
|
+
}
|
327
|
+
composite {
|
328
|
+
@address2_street_text_widget = text {
|
329
|
+
text bind(person, "address2.street")
|
330
|
+
}
|
331
|
+
@address2_city_text_widget = text {
|
332
|
+
text bind(person, "address2.city")
|
333
|
+
}
|
334
|
+
@address2_state_text_widget = text {
|
335
|
+
text bind(person, "address2.state")
|
336
|
+
}
|
337
|
+
@address2_zip_text_widget = text {
|
338
|
+
text bind(person, "address2.zip")
|
339
|
+
}
|
340
|
+
}
|
341
|
+
}
|
342
|
+
|
343
|
+
expect(@address1_street_text_widget.widget.getText).to eq("20 Naper Ave")
|
344
|
+
expect(@address1_city_text_widget.widget.getText).to eq("Indianapolis")
|
345
|
+
expect(@address1_state_text_widget.widget.getText).to eq("IN")
|
346
|
+
expect(@address1_zip_text_widget.widget.getText).to eq("46183")
|
347
|
+
|
348
|
+
expect(@address2_street_text_widget.widget.getText).to eq("101 Confession St")
|
349
|
+
expect(@address2_city_text_widget.widget.getText).to eq("Denver")
|
350
|
+
expect(@address2_state_text_widget.widget.getText).to eq("CO")
|
351
|
+
expect(@address2_zip_text_widget.widget.getText).to eq("80014")
|
352
|
+
|
353
|
+
person.address1.street = "123 Main St"
|
354
|
+
person.address1.city = "Chicago"
|
355
|
+
person.address1.state = "IL"
|
356
|
+
person.address1.zip = "60654"
|
357
|
+
|
358
|
+
person.address2.street = "100 Park Ave"
|
359
|
+
person.address2.city = "San Diego"
|
360
|
+
person.address2.state = "CA"
|
361
|
+
person.address2.zip = "92014"
|
362
|
+
|
363
|
+
expect(@address1_street_text_widget.widget.getText).to eq("123 Main St")
|
364
|
+
expect(@address1_city_text_widget.widget.getText).to eq("Chicago")
|
365
|
+
expect(@address1_state_text_widget.widget.getText).to eq("IL")
|
366
|
+
expect(@address1_zip_text_widget.widget.getText).to eq("60654")
|
367
|
+
|
368
|
+
expect(@address2_street_text_widget.widget.getText).to eq("100 Park Ave")
|
369
|
+
expect(@address2_city_text_widget.widget.getText).to eq("San Diego")
|
370
|
+
expect(@address2_state_text_widget.widget.getText).to eq("CA")
|
371
|
+
expect(@address2_zip_text_widget.widget.getText).to eq("92014")
|
372
|
+
|
373
|
+
person.address2 = person.address1
|
374
|
+
|
375
|
+
expect(@address2_street_text_widget.widget.getText).to eq("123 Main St")
|
376
|
+
expect(@address2_city_text_widget.widget.getText).to eq("Chicago")
|
377
|
+
expect(@address2_state_text_widget.widget.getText).to eq("IL")
|
378
|
+
expect(@address2_zip_text_widget.widget.getText).to eq("60654")
|
379
|
+
|
380
|
+
person.address2 = Address.new
|
381
|
+
|
382
|
+
person.address2.street = "101 Confession St"
|
383
|
+
person.address2.city = "Denver"
|
384
|
+
person.address2.state = "CO"
|
385
|
+
person.address2.zip = "80014"
|
386
|
+
|
387
|
+
expect(@address2_street_text_widget.widget.getText).to eq("101 Confession St")
|
388
|
+
expect(@address2_city_text_widget.widget.getText).to eq("Denver")
|
389
|
+
expect(@address2_state_text_widget.widget.getText).to eq("CO")
|
390
|
+
expect(@address2_zip_text_widget.widget.getText).to eq("80014")
|
391
|
+
|
392
|
+
person.address2.street = "123 Main St"
|
393
|
+
person.address2.city = "Chicago"
|
394
|
+
person.address2.state = "IL"
|
395
|
+
person.address2.zip = "60654"
|
396
|
+
|
397
|
+
expect(@address2_street_text_widget.widget.getText).to eq("123 Main St")
|
398
|
+
expect(@address2_city_text_widget.widget.getText).to eq("Chicago")
|
399
|
+
expect(@address2_state_text_widget.widget.getText).to eq("IL")
|
400
|
+
expect(@address2_zip_text_widget.widget.getText).to eq("60654")
|
401
|
+
end
|
402
|
+
|
403
|
+
end
|
287
404
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: glimmer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.11.SWT4.14
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- AndyMaleh
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-02-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -161,6 +161,7 @@ files:
|
|
161
161
|
- bin/girb
|
162
162
|
- bin/girb_runner.rb
|
163
163
|
- bin/glimmer
|
164
|
+
- config/swt.yml
|
164
165
|
- glimmer.gemspec
|
165
166
|
- images/Bitter-sweet.jpg
|
166
167
|
- lib/command_handler.rb
|
@@ -171,19 +172,21 @@ files:
|
|
171
172
|
- lib/command_handlers/combo_selection_data_binding_command_handler.rb
|
172
173
|
- lib/command_handlers/data_binding_command_handler.rb
|
173
174
|
- lib/command_handlers/list_selection_data_binding_command_handler.rb
|
174
|
-
- lib/command_handlers/models/
|
175
|
-
- lib/command_handlers/models/
|
175
|
+
- lib/command_handlers/models/block_observer.rb
|
176
|
+
- lib/command_handlers/models/list_selection_binding.rb
|
177
|
+
- lib/command_handlers/models/model_binding.rb
|
176
178
|
- lib/command_handlers/models/observable_array.rb
|
177
179
|
- lib/command_handlers/models/observable_model.rb
|
180
|
+
- lib/command_handlers/models/observer.rb
|
178
181
|
- lib/command_handlers/models/r_runnable.rb
|
179
182
|
- lib/command_handlers/models/r_shell.rb
|
180
183
|
- lib/command_handlers/models/r_tab_item_composite.rb
|
181
184
|
- lib/command_handlers/models/r_widget.rb
|
182
185
|
- lib/command_handlers/models/r_widget_listener.rb
|
183
186
|
- lib/command_handlers/models/r_widget_packages.rb
|
184
|
-
- lib/command_handlers/models/
|
185
|
-
- lib/command_handlers/models/
|
186
|
-
- lib/command_handlers/models/
|
187
|
+
- lib/command_handlers/models/table_items_binding.rb
|
188
|
+
- lib/command_handlers/models/tree_items_binding.rb
|
189
|
+
- lib/command_handlers/models/widget_binding.rb
|
187
190
|
- lib/command_handlers/shell_command_handler.rb
|
188
191
|
- lib/command_handlers/tab_item_command_handler.rb
|
189
192
|
- lib/command_handlers/table_column_properties_data_binding_command_handler.rb
|
@@ -255,9 +258,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
255
258
|
version: '0'
|
256
259
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
257
260
|
requirements:
|
258
|
-
- - "
|
261
|
+
- - ">"
|
259
262
|
- !ruby/object:Gem::Version
|
260
|
-
version:
|
263
|
+
version: 1.3.1
|
261
264
|
requirements: []
|
262
265
|
rubyforge_project:
|
263
266
|
rubygems_version: 2.7.10
|
@@ -1,28 +0,0 @@
|
|
1
|
-
class ModelObserver
|
2
|
-
attr_reader :model, :property_name, :property_type, :observer_options
|
3
|
-
@@property_type_converters = {
|
4
|
-
:undefined => lambda { |value| value },
|
5
|
-
:fixnum => lambda { |value| value.to_i },
|
6
|
-
:array => lambda { |value| value.to_a }
|
7
|
-
}
|
8
|
-
def initialize(model, property_name, property_type = :undefined, observer_options = nil)
|
9
|
-
property_type = :undefined if property_type.nil?
|
10
|
-
@model = model
|
11
|
-
@property_name = property_name
|
12
|
-
@property_type = property_type
|
13
|
-
@observer_options = observer_options || {}
|
14
|
-
end
|
15
|
-
def update(value)
|
16
|
-
converted_value = @@property_type_converters[@property_type].call(value)
|
17
|
-
@model.send(@property_name + "=", converted_value) unless evaluate_property == converted_value
|
18
|
-
end
|
19
|
-
def evaluate_property
|
20
|
-
@model.send(@property_name)
|
21
|
-
end
|
22
|
-
def evaluate_options_property
|
23
|
-
@model.send(@property_name + "_options")
|
24
|
-
end
|
25
|
-
def options_property_name
|
26
|
-
self.property_name + "_options"
|
27
|
-
end
|
28
|
-
end
|