glimmer 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.markdown +82 -6
- data/lib/command_handlers/combo_selection_data_binding_command_handler.rb +0 -1
- data/lib/command_handlers/list_selection_data_binding_command_handler.rb +0 -1
- data/lib/command_handlers/models/list_selection_binding.rb +3 -1
- data/lib/command_handlers/models/model_binding.rb +5 -6
- data/lib/command_handlers/models/observable_array.rb +1 -2
- data/lib/command_handlers/models/observable_model.rb +4 -1
- data/lib/command_handlers/models/observer.rb +8 -0
- data/lib/command_handlers/models/r_widget.rb +5 -4
- data/lib/command_handlers/models/table_items_binding.rb +5 -5
- data/lib/command_handlers/models/tree_items_binding.rb +5 -6
- data/lib/command_handlers/models/widget_binding.rb +3 -1
- data/lib/glimmer.rb +12 -5
- data/lib/swt_packages.rb +11 -0
- metadata +2 -2
- data/lib/command_handlers/models/r_widget_packages.rb +0 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c1cfa3ffb6be614db3b3e6509edf06c483067889a384c0ffbe94cfb27eea3c73
|
4
|
+
data.tar.gz: 4e30d971345d5df61a8ffcd7d736cc71cf2e7992dfe75fba39763ecba1bcbc6d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: be20760fda63f6b5458fd00ddcdd1f008057a3b376ad11dbaaa9ee488c0ec72cf67d9322b9f6673d23ff8c49679dc636ef98b17db0a8092fdabf41010f400074
|
7
|
+
data.tar.gz: 221280c0420afd17a8f843b2691b445ee2da99240d7b916e4f3af52eec1772458aa846393db9dbc6c44ba8ee1874b53ad517a946ffb05a39653fd669cd771163
|
data/README.markdown
CHANGED
@@ -5,9 +5,11 @@ Glimmer is a cross-platform Ruby desktop development library. Glimmer's main inn
|
|
5
5
|
|
6
6
|
You may learn more by reading this article: [Eclipse Zone Tutorial](http://eclipse.dzone.com/articles/an-introduction-glimmer)
|
7
7
|
|
8
|
-
##
|
8
|
+
## Examples
|
9
9
|
|
10
|
-
|
10
|
+
### Hello World
|
11
|
+
|
12
|
+
Glimmer code (from `samples/hello_world.rb`):
|
11
13
|
```ruby
|
12
14
|
include Glimmer
|
13
15
|
|
@@ -21,13 +23,47 @@ shell {
|
|
21
23
|
|
22
24
|
Run:
|
23
25
|
```
|
24
|
-
glimmer hello_world.rb
|
26
|
+
glimmer samples/hello_world.rb
|
25
27
|
```
|
26
28
|
|
27
29
|
Glimmer app:
|
28
30
|
|
29
|
-
![
|
31
|
+
![Hello World](https://github.com/AndyObtiva/glimmer/raw/master/images/glimmer-hello-world.png)
|
32
|
+
|
33
|
+
### Tic Tac Toe
|
30
34
|
|
35
|
+
Glimmer code (from `samples/tictactoe/tic_tac_toe.rb`):
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
shell {
|
39
|
+
text "Tic-Tac-Toe"
|
40
|
+
composite {
|
41
|
+
layout GridLayout.new(3,true)
|
42
|
+
(1..3).each { |row|
|
43
|
+
(1..3).each { |column|
|
44
|
+
button {
|
45
|
+
layout_data GridData.new(:fill.swt_constant, :fill.swt_constant, true, true)
|
46
|
+
text bind(@tic_tac_toe_board.box(row, column), :sign)
|
47
|
+
enabled bind(@tic_tac_toe_board.box(row, column), :empty)
|
48
|
+
on_widget_selected {
|
49
|
+
@tic_tac_toe_board.mark_box(row, column)
|
50
|
+
}
|
51
|
+
}
|
52
|
+
}
|
53
|
+
}
|
54
|
+
}
|
55
|
+
}
|
56
|
+
```
|
57
|
+
|
58
|
+
Run:
|
59
|
+
|
60
|
+
```
|
61
|
+
glimmer samples/tictactoe/tic_tac_toe.rb
|
62
|
+
```
|
63
|
+
|
64
|
+
Glimmer app:
|
65
|
+
|
66
|
+
![Tic Tac Toe](https://github.com/AndyObtiva/glimmer/raw/master/images/glimmer-tic-tac-toe.png)
|
31
67
|
|
32
68
|
## Resources
|
33
69
|
|
@@ -66,14 +102,14 @@ Please follow these instructions to make the `glimmer` command available on your
|
|
66
102
|
|
67
103
|
Run this command to install directly:
|
68
104
|
```
|
69
|
-
jgem install glimmer -v 0.3.
|
105
|
+
jgem install glimmer -v 0.3.2
|
70
106
|
```
|
71
107
|
|
72
108
|
### Option 2: Bundler
|
73
109
|
|
74
110
|
Add the following to `Gemfile`:
|
75
111
|
```
|
76
|
-
gem 'glimmer', '~> 0.3.
|
112
|
+
gem 'glimmer', '~> 0.3.2'
|
77
113
|
```
|
78
114
|
|
79
115
|
And, then run:
|
@@ -148,6 +184,43 @@ The fifth example demonstrates nested indexed computed value data binding whereb
|
|
148
184
|
|
149
185
|
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.
|
150
186
|
|
187
|
+
### Observer/Observable
|
188
|
+
|
189
|
+
Glimmer comes with the two classes `Observer`/`Observable`, which are used internally for data-binding, but can also be used externally for custom use of the Observer Pattern.
|
190
|
+
|
191
|
+
In summary, the class that needs to observe an object, must include Observer and implement `#update(changed_value)` method. The class to be observed doesn't need to do anything. It will automatically be enhanced by Glimmer for observation.
|
192
|
+
|
193
|
+
Observers can be a good mechanism for displaying dialog messages with Glimmer (using SWT's `MessageBox`).
|
194
|
+
|
195
|
+
Look at `samples/tictactoe/tic_tac_toe.rb` for an `Observer` dialog message example.
|
196
|
+
|
197
|
+
```ruby
|
198
|
+
observe(@tic_tac_toe_board, "game_status")
|
199
|
+
```
|
200
|
+
|
201
|
+
```ruby
|
202
|
+
def update(game_status)
|
203
|
+
display_win_message if game_status == TicTacToeBoard::WIN
|
204
|
+
display_draw_message if game_status == TicTacToeBoard::DRAW
|
205
|
+
end
|
206
|
+
|
207
|
+
def display_win_message
|
208
|
+
display_game_over_message("Player #{@tic_tac_toe_board.winning_sign} has won!")
|
209
|
+
end
|
210
|
+
|
211
|
+
def display_draw_message
|
212
|
+
display_game_over_message("Draw!")
|
213
|
+
end
|
214
|
+
|
215
|
+
def display_game_over_message(message)
|
216
|
+
message_box = MessageBox.new(@shell.widget)
|
217
|
+
message_box.setText("Game Over")
|
218
|
+
message_box.setMessage(message)
|
219
|
+
message_box.open
|
220
|
+
@tic_tac_toe_board.reset
|
221
|
+
end
|
222
|
+
```
|
223
|
+
|
151
224
|
## Samples
|
152
225
|
|
153
226
|
Check the "samples" folder for examples on how to write Glimmer applications. To run them, make sure to install the `glimmer` gem first and then use the `glimmer` command.
|
@@ -232,6 +305,9 @@ These features have been suggested. You might see them in a future version of Gl
|
|
232
305
|
a new component and extend the DSL with it
|
233
306
|
- **Nested indexed property data binding**: a complementary feature to nested property data binding that binds to a collection element by index (e.g. `bind(user, 'addresses[1].street')`)
|
234
307
|
- **bind_collection**: an iterator that enables spawning widgets based on a variable collection (e.g. `bind_collection('user.addresses') { |address| address_widget {...} }` spawns 3 `AddressWidget`s if `user.addresses` is set with 3 addresses; and replaces with 2 `AddressWidget`s if `user.addresses` is reset with 2 addresses only). Needs further thought on naming and functionality.
|
308
|
+
- Automatic relayout of "glimmer components" when disposing one or as an option
|
309
|
+
- Consider using Ruby Refinements for Glimmer
|
310
|
+
|
235
311
|
|
236
312
|
## Contributors
|
237
313
|
|
@@ -22,7 +22,6 @@ class ComboSelectionDataBindingCommandHandler
|
|
22
22
|
widget_binding = WidgetBinding.new(parent, "items")
|
23
23
|
widget_binding.update(model_binding.evaluate_options_property)
|
24
24
|
model = model_binding.base_model
|
25
|
-
model.extend(ObservableModel) unless model.is_a?(ObservableModel)
|
26
25
|
widget_binding.observe(model, model_binding.options_property_name)
|
27
26
|
|
28
27
|
widget_binding = WidgetBinding.new(parent, "text")
|
@@ -23,7 +23,6 @@ class ListSelectionDataBindingCommandHandler
|
|
23
23
|
widget_binding = WidgetBinding.new(parent, "items")
|
24
24
|
widget_binding.update(model_binding.evaluate_options_property)
|
25
25
|
model = model_binding.base_model
|
26
|
-
model.extend(ObservableModel) unless model.is_a?(ObservableModel)
|
27
26
|
#TODO make this options observer dependent and all similar observers in widget specific data binding handlers
|
28
27
|
widget_binding.observe(model, model_binding.options_property_name)
|
29
28
|
|
@@ -1,7 +1,9 @@
|
|
1
|
+
require_relative 'observable'
|
1
2
|
require_relative 'observer'
|
2
3
|
require_relative 'block_observer'
|
3
4
|
|
4
5
|
class ModelBinding
|
6
|
+
include Observable
|
5
7
|
include Observer
|
6
8
|
|
7
9
|
attr_reader :property_type, :binding_options
|
@@ -110,7 +112,6 @@ class ModelBinding
|
|
110
112
|
elsif nested_property?
|
111
113
|
add_nested_observers(observer)
|
112
114
|
else
|
113
|
-
model.extend(ObservableModel) unless model.is_a?(ObservableModel)
|
114
115
|
observer.observe(model, property_name)
|
115
116
|
observer.add_dependent([self, nil] => [observer, model, property_name])
|
116
117
|
end
|
@@ -124,7 +125,6 @@ class ModelBinding
|
|
124
125
|
elsif nested_property?
|
125
126
|
nested_property_observers_for(observer).clear
|
126
127
|
else
|
127
|
-
model.extend(ObservableModel) unless model.is_a?(ObservableModel)
|
128
128
|
observer.unobserve(model, property_name)
|
129
129
|
end
|
130
130
|
end
|
@@ -155,12 +155,11 @@ class ModelBinding
|
|
155
155
|
parent_property_name = nil if parent_property_name.to_s.start_with?('[')
|
156
156
|
unless model.nil?
|
157
157
|
if property_indexed?(property_name)
|
158
|
-
|
159
|
-
nested_property_observer.observe(model)
|
158
|
+
# TODO figure out a way to deal with this more uniformly
|
159
|
+
nested_property_observer.observe(model)
|
160
160
|
parent_observer.add_dependent([parent_model, parent_property_name] => [nested_property_observer, model, nil])
|
161
161
|
else
|
162
|
-
|
163
|
-
nested_property_observer.observe(model, property_name) unless model.has_observer?(nested_property_observer, property_name)
|
162
|
+
nested_property_observer.observe(model, property_name)
|
164
163
|
parent_observer.add_dependent([parent_model, parent_property_name] => [nested_property_observer, model, property_name])
|
165
164
|
end
|
166
165
|
end
|
@@ -7,10 +7,10 @@ module ObservableArray
|
|
7
7
|
include Observable
|
8
8
|
|
9
9
|
def add_observer(observer, element_properties=nil)
|
10
|
+
return observer if has_observer?(observer) && element_properties.nil?
|
10
11
|
property_observer_list << observer
|
11
12
|
[element_properties].flatten.compact.each do |property|
|
12
13
|
each do |element|
|
13
|
-
element.extend(ObservableModel) unless element.is_a?(ObservableModel)
|
14
14
|
observer.observe(element, property)
|
15
15
|
end
|
16
16
|
end
|
@@ -21,7 +21,6 @@ module ObservableArray
|
|
21
21
|
property_observer_list.delete(observer)
|
22
22
|
[element_properties].flatten.compact.each do |property|
|
23
23
|
each do |element|
|
24
|
-
element.extend(ObservableModel) unless element.is_a?(ObservableModel)
|
25
24
|
observer.unobserve(element, property)
|
26
25
|
end
|
27
26
|
end
|
@@ -54,6 +54,7 @@ module ObservableModel
|
|
54
54
|
|
55
55
|
def add_property_writer_observers(property_name)
|
56
56
|
property_writer_name = "#{property_name}="
|
57
|
+
method(property_writer_name)
|
57
58
|
ensure_array_object_observer(property_name, send(property_name))
|
58
59
|
begin
|
59
60
|
method("__original_#{property_writer_name}")
|
@@ -69,6 +70,9 @@ module ObservableModel
|
|
69
70
|
end
|
70
71
|
end_eval
|
71
72
|
end
|
73
|
+
rescue => e
|
74
|
+
# ignore writing if no property writer exists
|
75
|
+
Glimmer.logger.debug "No need to observe property writer: #{property_writer_name}\n#{e.message}\n#{e.backtrace.join("\n")}"
|
72
76
|
end
|
73
77
|
|
74
78
|
def unregister_dependent_observers(property_name, old_value)
|
@@ -81,7 +85,6 @@ module ObservableModel
|
|
81
85
|
|
82
86
|
def ensure_array_object_observer(property_name, object, old_object = nil)
|
83
87
|
return unless object.is_a?(Array)
|
84
|
-
object.extend(ObservableArray) unless object.is_a?(ObservableArray)
|
85
88
|
array_object_observer = array_object_observer_for(property_name)
|
86
89
|
array_object_observer.observe(object)
|
87
90
|
property_observer_list(property_name).each do |observer|
|
@@ -25,6 +25,14 @@ module Observer
|
|
25
25
|
# registers observer in an observable on a property (optional)
|
26
26
|
# observer maintains registration list to unregister later
|
27
27
|
def register(observable, property = nil)
|
28
|
+
unless observable.is_a?(Observable)
|
29
|
+
# TODO refactor code to be more smart/polymorphic/automated and honor open/closed principle
|
30
|
+
if observable.is_a?(Array)
|
31
|
+
observable.extend(ObservableArray)
|
32
|
+
else
|
33
|
+
observable.extend(ObservableModel)
|
34
|
+
end
|
35
|
+
end
|
28
36
|
observable.add_observer(*[self, property].compact)
|
29
37
|
[observable, property].tap do |registration|
|
30
38
|
self.registrations << registration
|
@@ -1,9 +1,10 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require_relative "r_widget_listener"
|
2
|
+
require_relative "r_runnable"
|
3
3
|
|
4
4
|
class RWidget
|
5
|
-
|
6
|
-
|
5
|
+
include_package 'org.eclipse.swt'
|
6
|
+
include_package 'org.eclipse.swt.widgets'
|
7
|
+
include_package 'org.eclipse.swt.layout'
|
7
8
|
include Parent
|
8
9
|
|
9
10
|
attr_reader :widget
|
@@ -1,9 +1,11 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
require_relative 'observable_array'
|
2
|
+
require_relative 'observable_model'
|
3
|
+
require_relative 'observable'
|
4
|
+
require_relative 'observer'
|
4
5
|
|
5
6
|
class TableItemsBinding
|
6
7
|
include Glimmer
|
8
|
+
include Observable
|
7
9
|
include Observer
|
8
10
|
include_package 'org.eclipse.swt'
|
9
11
|
include_package 'org.eclipse.swt.widgets'
|
@@ -14,7 +16,6 @@ class TableItemsBinding
|
|
14
16
|
@column_properties = column_properties
|
15
17
|
update(@model_binding.evaluate_property)
|
16
18
|
model = model_binding.base_model
|
17
|
-
model.extend(ObservableModel) unless model.is_a?(ObservableModel)
|
18
19
|
observe(model, model_binding.property_name_expression)
|
19
20
|
add_contents(@table) {
|
20
21
|
on_widget_disposed { |dispose_event|
|
@@ -24,7 +25,6 @@ class TableItemsBinding
|
|
24
25
|
end
|
25
26
|
def update(model_collection=nil)
|
26
27
|
if model_collection and model_collection.is_a?(Array)
|
27
|
-
model_collection.extend(ObservableArray) unless model_collection.is_a?(ObservableArray)
|
28
28
|
observe(model_collection, @column_properties)
|
29
29
|
@model_collection = model_collection
|
30
30
|
end
|
@@ -1,9 +1,11 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
require_relative 'observable_array'
|
2
|
+
require_relative 'observable_model'
|
3
|
+
require_relative 'observable'
|
4
|
+
require_relative 'observer'
|
4
5
|
|
5
6
|
class TreeItemsBinding
|
6
7
|
include Glimmer
|
8
|
+
include Observable
|
7
9
|
include Observer
|
8
10
|
include_package 'org.eclipse.swt'
|
9
11
|
include_package 'org.eclipse.swt.widgets'
|
@@ -14,7 +16,6 @@ class TreeItemsBinding
|
|
14
16
|
@tree_properties = [tree_properties].flatten.first.to_h
|
15
17
|
update(@model_binding.evaluate_property)
|
16
18
|
model = model_binding.base_model
|
17
|
-
model.extend(ObservableModel) unless model.is_a?(ObservableModel)
|
18
19
|
observe(model, model_binding.property_name_expression)
|
19
20
|
add_contents(@tree) {
|
20
21
|
on_widget_disposed { |dispose_event|
|
@@ -24,7 +25,6 @@ class TreeItemsBinding
|
|
24
25
|
end
|
25
26
|
def update(model_tree_root_node=nil)
|
26
27
|
if model_tree_root_node and model_tree_root_node.respond_to?(@tree_properties[:children])
|
27
|
-
model_tree_root_node.extend(ObservableModel) unless model_tree_root_node.is_a?(ObservableModel)
|
28
28
|
observe(model_tree_root_node, @tree_properties[:text])
|
29
29
|
observe(model_tree_root_node, @tree_properties[:children])
|
30
30
|
@model_tree_root_node = model_tree_root_node
|
@@ -39,7 +39,6 @@ class TreeItemsBinding
|
|
39
39
|
table_item = TreeItem.new(parent, SWT::NONE)
|
40
40
|
table_item.setText((model_tree_node && model_tree_node.send(tree_properties[:text])).to_s)
|
41
41
|
[model_tree_node && model_tree_node.send(tree_properties[:children])].flatten.to_a.compact.each do |child|
|
42
|
-
child.extend(ObservableModel) unless child.is_a?(ObservableModel)
|
43
42
|
observe(child, @tree_properties[:text])
|
44
43
|
populate_tree_node(child, table_item, tree_properties)
|
45
44
|
end
|
data/lib/glimmer.rb
CHANGED
@@ -7,13 +7,20 @@ require "rubygems"
|
|
7
7
|
require "facets"
|
8
8
|
require "logger"
|
9
9
|
require "java"
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
require_relative "string"
|
11
|
+
require_relative "symbol"
|
12
|
+
require_relative "parent"
|
13
|
+
require_relative "swt_packages"
|
13
14
|
|
14
15
|
module Glimmer
|
15
|
-
|
16
|
-
|
16
|
+
#TODO make it configurable to include or not include
|
17
|
+
include SwtPackages
|
18
|
+
def self.included(klass)
|
19
|
+
klass.include SwtPackages
|
20
|
+
end
|
21
|
+
def self.extended(klass)
|
22
|
+
klass.include SwtPackages
|
23
|
+
end
|
17
24
|
|
18
25
|
@@parent_stack = []
|
19
26
|
@@logger = Logger.new(STDOUT).tap {|logger| logger.level = Logger::WARN}
|
data/lib/swt_packages.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# edit to add more packages and support custom widgets
|
2
|
+
module SwtPackages
|
3
|
+
def self.included(klass)
|
4
|
+
klass.class_eval do
|
5
|
+
include_package 'org.eclipse.swt'
|
6
|
+
include_package 'org.eclipse.swt.widgets'
|
7
|
+
include_package 'org.eclipse.swt.layout'
|
8
|
+
include_package 'org.eclipse.swt.graphics'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: glimmer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- AndyMaleh
|
@@ -171,7 +171,6 @@ files:
|
|
171
171
|
- lib/command_handlers/models/r_tab_item_composite.rb
|
172
172
|
- lib/command_handlers/models/r_widget.rb
|
173
173
|
- lib/command_handlers/models/r_widget_listener.rb
|
174
|
-
- lib/command_handlers/models/r_widget_packages.rb
|
175
174
|
- lib/command_handlers/models/table_items_binding.rb
|
176
175
|
- lib/command_handlers/models/tree_items_binding.rb
|
177
176
|
- lib/command_handlers/models/widget_binding.rb
|
@@ -189,6 +188,7 @@ files:
|
|
189
188
|
- lib/parent.rb
|
190
189
|
- lib/shine.rb
|
191
190
|
- lib/string.rb
|
191
|
+
- lib/swt_packages.rb
|
192
192
|
- lib/symbol.rb
|
193
193
|
- lib/xml_command_handlers.rb
|
194
194
|
- lib/xml_command_handlers/html_command_handler.rb
|