glimmer 0.1.10.470 → 0.1.11.SWT4.14
Sign up to get free protection for your applications and to get access to all the features.
- 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
|