glimmer 0.7.4 → 0.7.5
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 +58 -5
- data/VERSION +1 -1
- data/lib/glimmer/data_binding/table_items_binding.rb +1 -0
- data/lib/glimmer/data_binding/tree_items_binding.rb +27 -12
- data/lib/glimmer/launcher.rb +5 -0
- data/lib/glimmer/swt/tab_item_proxy.rb +6 -0
- data/lib/glimmer/swt/tree_proxy.rb +97 -1
- data/lib/glimmer/swt/widget_listener_proxy.rb +21 -4
- data/lib/glimmer/swt/widget_proxy.rb +32 -25
- data/lib/glimmer/ui/custom_widget.rb +4 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 711519083aeec2914eccf820d3c43a799b2f688f04f7ae99403bee8a1bd0985c
|
4
|
+
data.tar.gz: f9121704b98f1f0186be043275873d80c15cd93427b6bfc5580473c379135d0b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cfa41f350b10c401ab3da3bcb8ddd065a53742771b09569f9502c0b57b492637a1d1333ebe8fc1123813772ed016d64130093c5f78518a196b8cf813446dc51b
|
7
|
+
data.tar.gz: 85fae54ea7fdaa91f709bae749725f4b8b2bd3cd6c7c23889e1a812a0f5739f8d659e699fc8cb6d75fb6914bcde1f4ab9ff7145e60150732692d9a9d9d729773
|
data/README.markdown
CHANGED
@@ -1,9 +1,12 @@
|
|
1
|
-
# Glimmer 0.7.
|
1
|
+
# Glimmer 0.7.5 Beta (Desktop Development Library for Ruby)
|
2
2
|
[](http://badge.fury.io/rb/glimmer)
|
3
3
|
[](https://coveralls.io/github/AndyObtiva/glimmer?branch=master)
|
4
4
|
|
5
5
|
Glimmer is a native-UI cross-platform desktop development library written in Ruby. Glimmer's main innovation is a JRuby DSL that enables productive and efficient authoring of desktop application user-interfaces while relying on the robust Eclipse SWT library. Glimmer additionally innovates by having built-in data-binding support to greatly facilitate synchronizing the UI with domain models. As a result, that achieves true decoupling of object oriented components, enabling developers to solve business problems without worrying about UI concerns, or alternatively drive development UI-first, and then write clean business models test-first afterwards.
|
6
6
|
|
7
|
+
[<img src="https://covers.oreillystatic.com/images/9780596519650/lrg.jpg" width=105 /><br />
|
8
|
+
Featured in<br />JRuby Cookbook](http://shop.oreilly.com/product/9780596519650.do)
|
9
|
+
|
7
10
|
## Examples
|
8
11
|
|
9
12
|
### Hello, World!
|
@@ -71,7 +74,7 @@ NOTE: Glimmer is in beta mode. Please help make better by adopting for small or
|
|
71
74
|
## Table of Contents
|
72
75
|
|
73
76
|
<!-- TOC START min:1 max:3 link:true asterisk:false update:true -->
|
74
|
-
- [Glimmer 0.7.
|
77
|
+
- [Glimmer 0.7.5 Beta (JRuby Desktop UI DSL + Data-Binding)](#glimmer-058-beta-jruby-desktop-ui-dsl--data-binding)
|
75
78
|
- [Examples](#examples)
|
76
79
|
- [Hello World](#hello-world)
|
77
80
|
- [Tic Tac Toe](#tic-tac-toe)
|
@@ -164,7 +167,7 @@ Please follow these instructions to make the `glimmer` command available on your
|
|
164
167
|
|
165
168
|
Run this command to install directly:
|
166
169
|
```
|
167
|
-
jgem install glimmer -v 0.7.
|
170
|
+
jgem install glimmer -v 0.7.5
|
168
171
|
```
|
169
172
|
|
170
173
|
`jgem` is JRuby's version of `gem` command.
|
@@ -175,7 +178,7 @@ Otherwise, you may also run `jruby -S gem install ...`
|
|
175
178
|
|
176
179
|
Add the following to `Gemfile`:
|
177
180
|
```
|
178
|
-
gem 'glimmer', '~> 0.7.
|
181
|
+
gem 'glimmer', '~> 0.7.5'
|
179
182
|
```
|
180
183
|
|
181
184
|
And, then run:
|
@@ -734,6 +737,7 @@ Glimmer ships with SWT style **smart defaults** so you wouldn't have to set them
|
|
734
737
|
|
735
738
|
- `text(:border)`
|
736
739
|
- `table(:border)`
|
740
|
+
- `tree(:border, :virtual, :v_scroll, :h_scroll)`
|
737
741
|
- `spinner(:border)`
|
738
742
|
- `list(:border, :v_scroll)`
|
739
743
|
- `button(:push)`
|
@@ -1075,7 +1079,7 @@ https://help.eclipse.org/2019-12/nftopic/org.eclipse.platform.doc.isv/reference/
|
|
1075
1079
|
|
1076
1080
|
Data-binding is done with `bind` command following widget property to bind and taking model and bindable attribute as arguments.
|
1077
1081
|
|
1078
|
-
|
1082
|
+
#### General data-binding examples:
|
1079
1083
|
|
1080
1084
|
`text bind(contact, :first_name)`
|
1081
1085
|
|
@@ -1098,6 +1102,10 @@ This example also specifies a converter on read of the model property, but via a
|
|
1098
1102
|
|
1099
1103
|
This is a block shortcut version of the syntax above it. It facilitates formatting model data for read-only widgets since it's a very common view concern. It also saves the developer from having to create a separate formatter/presenter for the model when the view can be an active view that handles common simple formatting operations directly.
|
1100
1104
|
|
1105
|
+
`text bind(contact, 'address.street', read_only: true)
|
1106
|
+
|
1107
|
+
This is read-ohly data-binding. It doesn't update contact.address.street when widget text property is changed.
|
1108
|
+
|
1101
1109
|
`text bind(contact, 'addresses[1].street')`
|
1102
1110
|
|
1103
1111
|
This example binds the text property of a widget like `label` to the nested indexed address street of a contact. This is called nested indexed property data binding.
|
@@ -1116,6 +1124,8 @@ This example demonstrates nested indexed computed value data binding whereby the
|
|
1116
1124
|
|
1117
1125
|
Example from [samples/hello/hello_combo.rb](samples/hello_combo.rb) sample (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
|
1118
1126
|
|
1127
|
+
#### Combo
|
1128
|
+
|
1119
1129
|

|
1120
1130
|
|
1121
1131
|

|
@@ -1159,6 +1169,8 @@ HelloCombo.new.launch
|
|
1159
1169
|
|
1160
1170
|
`combo` widget is data-bound to the country of a person. Note that it expects `person` object to have `:country` attribute and `:country_options` attribute containing all available countries.
|
1161
1171
|
|
1172
|
+
#### List
|
1173
|
+
|
1162
1174
|
Example from [samples/hello/hello_list_single_selection.rb](samples/hello_list_single_selection.rb) sample:
|
1163
1175
|
|
1164
1176
|

|
@@ -1240,6 +1252,45 @@ Note that in all the data-binding examples above, there was also an observer att
|
|
1240
1252
|
|
1241
1253
|
You may learn more about Glimmer's data-binding syntax by reading the [Eclipse Zone Tutorial](http://eclipse.dzone.com/articles/an-introduction-glimmer) mentioned in resources and opening up the samples under the [samples](samples) directory.
|
1242
1254
|
|
1255
|
+
#### Tree
|
1256
|
+
|
1257
|
+
The SWT Tree widget visualizes a tree data-structure, such as an employment or composition hierarchy.
|
1258
|
+
|
1259
|
+
To data-bind a Tree, you need the root model, the children querying method, and the text display attribute on each child.
|
1260
|
+
|
1261
|
+
This involves using the `bind` keyword mentioned above in addition to a special `tree_properties` keyword that takes the children and text attribute methods.
|
1262
|
+
|
1263
|
+
Example:
|
1264
|
+
|
1265
|
+
```ruby
|
1266
|
+
shell {
|
1267
|
+
@tree = tree {
|
1268
|
+
items bind(company, :owner), tree_properties(children: :coworkers, text: :name)
|
1269
|
+
selection bind(company, :selected_coworker)
|
1270
|
+
}
|
1271
|
+
}
|
1272
|
+
```
|
1273
|
+
|
1274
|
+
The code above includes two data-bindings:
|
1275
|
+
- Tree `items`, which first bind to the root node (company.owner), and then dig down via `coworkers` `children` method, using the `name` `text` attribute for displaying each tree item.
|
1276
|
+
- Tree `selection`, which binds the single tree item selected by the user to the attribute denoted by the `bind` keyword
|
1277
|
+
|
1278
|
+
Additionally, Tree `items` data-binding automatically stores each node model unto the SWT TreeItem object via `setData` method. This enables things like searchability.
|
1279
|
+
|
1280
|
+
The tree widget in Glimmer is represented by a subclass of `WidgetProxy` called `TreeProxy`.
|
1281
|
+
TreeProxy includes a `depth_first_search` method that takes a block to look for a tree item.
|
1282
|
+
|
1283
|
+
Example:
|
1284
|
+
|
1285
|
+
```ruby
|
1286
|
+
found_array = @tree.depth_first_search { |tree_item| tree_item.getData == company.owner }
|
1287
|
+
```
|
1288
|
+
|
1289
|
+
This finds the root node. The array is a Java array. This enables easy passing of it to SWT `Tree#setSelection` method, which expects a Java array of `TreeItem` objects.
|
1290
|
+
|
1291
|
+
To edit a tree, you must invoke `TreeProxy#edit_selected_tree_item` or `TreeProxy#edit_tree_item`. This automatically leverages the SWT TreeEditor custom class behind the scenes, displaying
|
1292
|
+
a text widget to the user to change the selected or passed tree item text into something else. It automatically persists the change to `items` data-bound model on ENTER/FOCUS-OUT or cancels on ESC/NO-CHANGE.
|
1293
|
+
|
1243
1294
|
### Observer
|
1244
1295
|
|
1245
1296
|
Glimmer comes with `Observer` module, which is used internally for data-binding, but can also be used externally for custom use of the Observer Pattern. It is hidden when observing widgets, and used explicitly when observing models.
|
@@ -2198,6 +2249,8 @@ Exec failed with code 2 command [[/usr/bin/SetFile, -c, icnC, /var/folders/4_/g1
|
|
2198
2249
|
* [InfoQ Article](http://www.infoq.com/news/2008/02/glimmer-jruby-swt)
|
2199
2250
|
* [RubyConf 2008 Video](https://confreaks.tv/videos/rubyconf2008-desktop-development-with-glimmer)
|
2200
2251
|
* [Code Blog](http://andymaleh.blogspot.com/search/label/Glimmer)
|
2252
|
+
* [JRuby Cookbook by Justin Edelson & Henry Liu](http://shop.oreilly.com/product/9780596519650.do)
|
2253
|
+
|
2201
2254
|
|
2202
2255
|
## Feature Suggestions
|
2203
2256
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.7.
|
1
|
+
0.7.5
|
@@ -17,7 +17,12 @@ module Glimmer
|
|
17
17
|
@tree = parent
|
18
18
|
@model_binding = model_binding
|
19
19
|
@tree_properties = [tree_properties].flatten.first.to_h
|
20
|
-
|
20
|
+
if @tree.respond_to?(:tree_properties=)
|
21
|
+
@tree.tree_properties = @tree_properties
|
22
|
+
else # assume custom widget
|
23
|
+
@tree.body_root.tree_properties = @tree_properties
|
24
|
+
end
|
25
|
+
call
|
21
26
|
model = model_binding.base_model
|
22
27
|
observe(model, model_binding.property_name_expression)
|
23
28
|
@tree.on_widget_disposed do |dispose_event|
|
@@ -25,27 +30,37 @@ module Glimmer
|
|
25
30
|
end
|
26
31
|
end
|
27
32
|
|
28
|
-
def call(
|
29
|
-
|
30
|
-
observe(model_tree_root_node, @tree_properties[:text])
|
31
|
-
observe(model_tree_root_node, @tree_properties[:children])
|
32
|
-
@model_tree_root_node = model_tree_root_node
|
33
|
-
end
|
33
|
+
def call(new_value=nil)
|
34
|
+
@model_tree_root_node = @model_binding.evaluate_property
|
34
35
|
populate_tree(@model_tree_root_node, @tree, @tree_properties)
|
35
36
|
end
|
36
37
|
|
37
38
|
def populate_tree(model_tree_root_node, parent, tree_properties)
|
39
|
+
# TODO make it change things by delta instead of removing all
|
40
|
+
selected_tree_item_model = parent.swt_widget.getSelection.map(&:getData).first
|
41
|
+
parent.all_tree_items.each do |tree_item|
|
42
|
+
tree_item.getData('observer_registrations').each do |key, observer_registration|
|
43
|
+
observer_registration.unregister
|
44
|
+
end
|
45
|
+
end
|
38
46
|
parent.swt_widget.removeAll
|
39
47
|
populate_tree_node(model_tree_root_node, parent.swt_widget, tree_properties)
|
48
|
+
tree_item_to_select = parent.depth_first_search {|ti| ti.getData == selected_tree_item_model}
|
49
|
+
parent.swt_widget.setSelection(tree_item_to_select)
|
40
50
|
end
|
41
51
|
|
42
52
|
def populate_tree_node(model_tree_node, parent, tree_properties)
|
43
|
-
|
44
|
-
|
45
|
-
|
53
|
+
return if model_tree_node.nil?
|
54
|
+
# TODO anticipate default tree properties if none were passed (like literal values text and children)
|
55
|
+
tree_item = TreeItem.new(parent, SWT::SWTProxy[:none])
|
56
|
+
observer_registrations = @tree_properties.reduce({}) do |hash, key_value_pair|
|
57
|
+
hash.merge(key_value_pair.first => observe(model_tree_node, key_value_pair.last))
|
58
|
+
end
|
59
|
+
tree_item.setData('observer_registrations', observer_registrations)
|
60
|
+
tree_item.setData(model_tree_node)
|
61
|
+
tree_item.setText((model_tree_node && model_tree_node.send(tree_properties[:text])).to_s)
|
46
62
|
[model_tree_node && model_tree_node.send(tree_properties[:children])].flatten.to_a.compact.each do |child|
|
47
|
-
|
48
|
-
populate_tree_node(child, table_item, tree_properties)
|
63
|
+
populate_tree_node(child, tree_item, tree_properties)
|
49
64
|
end
|
50
65
|
end
|
51
66
|
end
|
data/lib/glimmer/launcher.rb
CHANGED
@@ -116,6 +116,11 @@ module Glimmer
|
|
116
116
|
end
|
117
117
|
end
|
118
118
|
end
|
119
|
+
|
120
|
+
attr_reader :application_paths
|
121
|
+
attr_reader :env_vars
|
122
|
+
attr_reader :glimmer_options
|
123
|
+
attr_reader :jruby_options
|
119
124
|
|
120
125
|
def initialize(raw_options)
|
121
126
|
@application_paths = extract_application_paths(raw_options)
|
@@ -3,22 +3,118 @@ require 'glimmer/swt/widget_proxy'
|
|
3
3
|
module Glimmer
|
4
4
|
module SWT
|
5
5
|
class TreeProxy < Glimmer::SWT::WidgetProxy
|
6
|
+
include Glimmer
|
7
|
+
|
8
|
+
attr_reader :tree_editor, :tree_editor_text_proxy
|
9
|
+
attr_accessor :tree_properties
|
10
|
+
|
11
|
+
def initialize(underscored_widget_name, parent, args)
|
12
|
+
super
|
13
|
+
@tree_editor = TreeEditor.new(swt_widget)
|
14
|
+
@tree_editor.horizontalAlignment = SWTProxy[:left]
|
15
|
+
@tree_editor.grabHorizontal = true
|
16
|
+
@tree_editor.minimumHeight = 20
|
17
|
+
end
|
18
|
+
|
6
19
|
# Performs depth first search for tree items matching block condition
|
7
|
-
#
|
20
|
+
# If no condition block is passed, returns all tree items
|
21
|
+
# Returns a Java TreeItem array to easily set as selection on org.eclipse.swt.Tree if needed
|
8
22
|
def depth_first_search(&condition)
|
9
23
|
found = []
|
10
24
|
recursive_depth_first_search(swt_widget.getItems.first, found, &condition)
|
11
25
|
found.to_java(TreeItem)
|
12
26
|
end
|
27
|
+
|
28
|
+
# Returns all tree items including descendants
|
29
|
+
def all_tree_items
|
30
|
+
depth_first_search
|
31
|
+
end
|
13
32
|
|
33
|
+
def widget_property_listener_installers
|
34
|
+
super.merge({
|
35
|
+
Java::OrgEclipseSwtWidgets::Tree => {
|
36
|
+
selection: lambda do |observer|
|
37
|
+
on_widget_selected { |selection_event|
|
38
|
+
observer.call(@swt_widget.getSelection)
|
39
|
+
}
|
40
|
+
end
|
41
|
+
},
|
42
|
+
})
|
43
|
+
end
|
44
|
+
|
45
|
+
def edit_in_progress?
|
46
|
+
!!@edit_in_progress
|
47
|
+
end
|
48
|
+
|
49
|
+
def edit_selected_tree_item(before_write: nil, after_write: nil, after_cancel: nil)
|
50
|
+
edit_tree_item(swt_widget.getSelection.first, before_write: before_write, after_write: after_write, after_cancel: after_cancel)
|
51
|
+
end
|
52
|
+
|
53
|
+
def edit_tree_item(tree_item, before_write: nil, after_write: nil, after_cancel: nil)
|
54
|
+
return if tree_item.nil?
|
55
|
+
content {
|
56
|
+
@tree_editor_text_proxy = text {
|
57
|
+
focus true
|
58
|
+
text tree_item.getText
|
59
|
+
action_taken = false
|
60
|
+
cancel = lambda {
|
61
|
+
@tree_editor_text_proxy.swt_widget.dispose
|
62
|
+
@tree_editor_text_proxy = nil
|
63
|
+
after_cancel&.call
|
64
|
+
@edit_in_progress = false
|
65
|
+
}
|
66
|
+
action = lambda { |event|
|
67
|
+
if !action_taken && !@edit_in_progress
|
68
|
+
action_taken = true
|
69
|
+
@edit_in_progress = true
|
70
|
+
new_text = @tree_editor_text_proxy.swt_widget.getText
|
71
|
+
if new_text == tree_item.getText
|
72
|
+
cancel.call
|
73
|
+
else
|
74
|
+
before_write&.call
|
75
|
+
tree_item.setText(new_text)
|
76
|
+
model = tree_item.getData
|
77
|
+
model.send("#{tree_properties[:text]}=", new_text) # makes tree update itself, so must search for selected tree item again
|
78
|
+
edited_tree_item = depth_first_search { |ti| ti.getData == model }.first
|
79
|
+
swt_widget.showItem(edited_tree_item)
|
80
|
+
@tree_editor_text_proxy.swt_widget.dispose
|
81
|
+
@tree_editor_text_proxy = nil
|
82
|
+
after_write&.call(edited_tree_item)
|
83
|
+
@edit_in_progress = false
|
84
|
+
end
|
85
|
+
end
|
86
|
+
}
|
87
|
+
on_focus_lost(&action)
|
88
|
+
on_key_pressed { |key_event|
|
89
|
+
if key_event.keyCode == swt(:cr)
|
90
|
+
action.call(key_event)
|
91
|
+
elsif key_event.keyCode == swt(:esc)
|
92
|
+
cancel.call
|
93
|
+
end
|
94
|
+
}
|
95
|
+
}
|
96
|
+
@tree_editor_text_proxy.swt_widget.selectAll
|
97
|
+
}
|
98
|
+
@tree_editor.setEditor(@tree_editor_text_proxy.swt_widget, tree_item);
|
99
|
+
end
|
100
|
+
|
14
101
|
private
|
15
102
|
|
16
103
|
def recursive_depth_first_search(tree_item, found, &condition)
|
104
|
+
return if tree_item.nil?
|
17
105
|
found << tree_item if condition.nil? || condition.call(tree_item)
|
18
106
|
tree_item.getItems.each do |child_tree_item|
|
19
107
|
recursive_depth_first_search(child_tree_item, found, &condition)
|
20
108
|
end
|
21
109
|
end
|
110
|
+
|
111
|
+
def property_type_converters
|
112
|
+
super.merge({
|
113
|
+
selection: lambda do |value|
|
114
|
+
depth_first_search {|ti| ti.getData == value}
|
115
|
+
end,
|
116
|
+
})
|
117
|
+
end
|
22
118
|
end
|
23
119
|
end
|
24
120
|
end
|
@@ -5,12 +5,29 @@ module Glimmer
|
|
5
5
|
# Follows the Proxy Design Pattern
|
6
6
|
class WidgetListenerProxy
|
7
7
|
|
8
|
-
attr_reader :swt_listener
|
8
|
+
attr_reader :swt_widget, :swt_listener, :widget_add_listener_method, :swt_listener_class, :swt_listener_method, :event_type, :swt_constant
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
def initialize(swt_listener)
|
10
|
+
def initialize(swt_widget:, swt_listener:, widget_add_listener_method: nil, swt_listener_class: nil, swt_listener_method: nil, event_type: nil, swt_constant: nil)
|
11
|
+
@swt_widget = swt_widget
|
13
12
|
@swt_listener = swt_listener
|
13
|
+
@widget_add_listener_method = widget_add_listener_method
|
14
|
+
@swt_listener_class = swt_listener_class
|
15
|
+
@swt_listener_method = swt_listener_method
|
16
|
+
@event_type = event_type
|
17
|
+
@swt_constant = swt_constant
|
18
|
+
end
|
19
|
+
|
20
|
+
def widget_remove_listener_method
|
21
|
+
@widget_add_listener_method.sub('add', 'remove')
|
22
|
+
end
|
23
|
+
|
24
|
+
def unregister
|
25
|
+
# TODO consider renaming to deregister (and in Observer too)
|
26
|
+
if @event_type
|
27
|
+
@swt_widget.removeListener(@event_type, @swt_listener)
|
28
|
+
else
|
29
|
+
@swt_widget.send(widget_remove_listener_method, @swt_listener)
|
30
|
+
end
|
14
31
|
end
|
15
32
|
end
|
16
33
|
end
|
@@ -5,6 +5,8 @@ require 'glimmer/swt/font_proxy'
|
|
5
5
|
require 'glimmer/swt/swt_proxy'
|
6
6
|
require 'glimmer/data_binding/observable_widget'
|
7
7
|
|
8
|
+
# TODO refactor to make file smaller and extract sub-widget-proxies out of this
|
9
|
+
|
8
10
|
module Glimmer
|
9
11
|
module SWT
|
10
12
|
# Proxy for SWT Widget objects
|
@@ -23,6 +25,7 @@ module Glimmer
|
|
23
25
|
DEFAULT_STYLES = {
|
24
26
|
"text" => [:border],
|
25
27
|
"table" => [:border],
|
28
|
+
"tree" => [:virtual, :border, :h_scroll, :v_scroll],
|
26
29
|
"spinner" => [:border],
|
27
30
|
"styled_text" => [:border],
|
28
31
|
"list" => [:border, :v_scroll],
|
@@ -31,17 +34,17 @@ module Glimmer
|
|
31
34
|
}
|
32
35
|
|
33
36
|
DEFAULT_INITIALIZERS = {
|
34
|
-
"composite" =>
|
37
|
+
"composite" => lambda do |composite|
|
35
38
|
composite.setLayout(GridLayout.new)
|
36
39
|
end,
|
37
|
-
"table" =>
|
40
|
+
"table" => lambda do |table|
|
38
41
|
table.setHeaderVisible(true)
|
39
42
|
table.setLinesVisible(true)
|
40
43
|
end,
|
41
|
-
"table_column" =>
|
44
|
+
"table_column" => lambda do |table_column|
|
42
45
|
table_column.setWidth(80)
|
43
46
|
end,
|
44
|
-
"group" =>
|
47
|
+
"group" => lambda do |group|
|
45
48
|
group.setLayout(GridLayout.new)
|
46
49
|
end,
|
47
50
|
}
|
@@ -119,7 +122,7 @@ module Glimmer
|
|
119
122
|
def widget_property_listener_installers
|
120
123
|
@swt_widget_property_listener_installers ||= {
|
121
124
|
Java::OrgEclipseSwtWidgets::Control => {
|
122
|
-
:focus =>
|
125
|
+
:focus => lambda do |observer|
|
123
126
|
on_focus_gained { |focus_event|
|
124
127
|
observer.call(true)
|
125
128
|
}
|
@@ -129,12 +132,12 @@ module Glimmer
|
|
129
132
|
end,
|
130
133
|
},
|
131
134
|
Java::OrgEclipseSwtWidgets::Text => {
|
132
|
-
:text =>
|
135
|
+
:text => lambda do |observer|
|
133
136
|
on_modify_text { |modify_event|
|
134
137
|
observer.call(@swt_widget.getText)
|
135
138
|
}
|
136
139
|
end,
|
137
|
-
:caret_position =>
|
140
|
+
:caret_position => lambda do |observer|
|
138
141
|
on_event_keydown { |event|
|
139
142
|
observer.call(@swt_widget.getCaretPosition)
|
140
143
|
}
|
@@ -148,7 +151,7 @@ module Glimmer
|
|
148
151
|
observer.call(@swt_widget.getCaretPosition)
|
149
152
|
}
|
150
153
|
end,
|
151
|
-
:selection_count =>
|
154
|
+
:selection_count => lambda do |observer|
|
152
155
|
on_event_keydown { |event|
|
153
156
|
observer.call(@swt_widget.getSelectionCount)
|
154
157
|
}
|
@@ -162,7 +165,7 @@ module Glimmer
|
|
162
165
|
observer.call(@swt_widget.getSelectionCount)
|
163
166
|
}
|
164
167
|
end,
|
165
|
-
:top_index =>
|
168
|
+
:top_index => lambda do |observer|
|
166
169
|
@last_top_index = @swt_widget.getTopIndex
|
167
170
|
on_paint_control { |event|
|
168
171
|
if @swt_widget.getTopIndex != @last_top_index
|
@@ -173,33 +176,33 @@ module Glimmer
|
|
173
176
|
end,
|
174
177
|
},
|
175
178
|
Java::OrgEclipseSwtCustom::StyledText => {
|
176
|
-
:text =>
|
179
|
+
:text => lambda do |observer|
|
177
180
|
on_modify_text { |modify_event|
|
178
181
|
observer.call(@swt_widget.getText)
|
179
182
|
}
|
180
183
|
end,
|
181
184
|
},
|
182
185
|
Java::OrgEclipseSwtWidgets::Button => {
|
183
|
-
:selection =>
|
186
|
+
:selection => lambda do |observer|
|
184
187
|
on_widget_selected { |selection_event|
|
185
188
|
observer.call(@swt_widget.getSelection)
|
186
189
|
}
|
187
190
|
end
|
188
191
|
},
|
189
192
|
Java::OrgEclipseSwtWidgets::MenuItem => {
|
190
|
-
:selection =>
|
193
|
+
:selection => lambda do |observer|
|
191
194
|
on_widget_selected { |selection_event|
|
192
195
|
observer.call(@swt_widget.getSelection)
|
193
196
|
}
|
194
197
|
end
|
195
198
|
},
|
196
199
|
Java::OrgEclipseSwtWidgets::Spinner => {
|
197
|
-
:selection =>
|
200
|
+
:selection => lambda do |observer|
|
198
201
|
on_widget_selected { |selection_event|
|
199
202
|
observer.call(@swt_widget.getSelection)
|
200
203
|
}
|
201
204
|
end
|
202
|
-
}
|
205
|
+
},
|
203
206
|
}
|
204
207
|
end
|
205
208
|
|
@@ -321,10 +324,12 @@ module Glimmer
|
|
321
324
|
end
|
322
325
|
|
323
326
|
def add_listener(underscored_listener_name, &block)
|
324
|
-
widget_add_listener_method, listener_class, listener_method = self.class.find_listener(@swt_widget.getClass, underscored_listener_name)
|
325
|
-
|
327
|
+
widget_add_listener_method, listener_class, listener_method = self.class.find_listener(@swt_widget.getClass, underscored_listener_name)
|
328
|
+
widget_listener_proxy = nil
|
329
|
+
safe_block = lambda { |event| block.call(event) unless @swt_widget.isDisposed }
|
330
|
+
listener = listener_class.new(listener_method => safe_block)
|
326
331
|
@swt_widget.send(widget_add_listener_method, listener)
|
327
|
-
WidgetListenerProxy.new(listener)
|
332
|
+
widget_listener_proxy = WidgetListenerProxy.new(swt_widget: @swt_widget, swt_listener: listener, widget_add_listener_method: widget_add_listener_method, swt_listener_class: listener_class, swt_listener_method: listener_method)
|
328
333
|
end
|
329
334
|
|
330
335
|
# Looks through SWT class add***Listener methods till it finds one for which
|
@@ -375,8 +380,10 @@ module Glimmer
|
|
375
380
|
|
376
381
|
def add_swt_event_listener(swt_constant, &block)
|
377
382
|
event_type = SWTProxy[swt_constant]
|
378
|
-
|
379
|
-
|
383
|
+
widget_listener_proxy = nil
|
384
|
+
safe_block = lambda { |event| block.call(event) unless @swt_widget.isDisposed }
|
385
|
+
@swt_widget.addListener(event_type, &safe_block)
|
386
|
+
widget_listener_proxy = WidgetListenerProxy.new(swt_widget: @swt_widget, swt_listener: @swt_widget.getListeners(event_type).last, event_type: event_type, swt_constant: swt_constant)
|
380
387
|
end
|
381
388
|
|
382
389
|
def widget_custom_attribute_mapping
|
@@ -409,7 +416,7 @@ module Glimmer
|
|
409
416
|
end
|
410
417
|
|
411
418
|
def property_type_converters
|
412
|
-
color_converter =
|
419
|
+
color_converter = lambda do |value|
|
413
420
|
if value.is_a?(Symbol) || value.is_a?(String)
|
414
421
|
ColorProxy.new(value).swt_color
|
415
422
|
else
|
@@ -419,7 +426,7 @@ module Glimmer
|
|
419
426
|
# TODO consider detecting type on widget method and automatically invoking right converter (e.g. :to_s for String, :to_i for Integer)
|
420
427
|
@property_type_converters ||= {
|
421
428
|
:background => color_converter,
|
422
|
-
:background_image =>
|
429
|
+
:background_image => lambda do |value|
|
423
430
|
if value.is_a?(String)
|
424
431
|
if value.start_with?('uri:classloader')
|
425
432
|
value = value.sub(/^uri\:classloader\:\//, '')
|
@@ -440,7 +447,7 @@ module Glimmer
|
|
440
447
|
end
|
441
448
|
end,
|
442
449
|
:foreground => color_converter,
|
443
|
-
:font =>
|
450
|
+
:font => lambda do |value|
|
444
451
|
if value.is_a?(Hash)
|
445
452
|
font_properties = value
|
446
453
|
FontProxy.new(self, font_properties).swt_font
|
@@ -448,17 +455,17 @@ module Glimmer
|
|
448
455
|
value
|
449
456
|
end
|
450
457
|
end,
|
451
|
-
:items =>
|
458
|
+
:items => lambda do |value|
|
452
459
|
value.to_java :string
|
453
460
|
end,
|
454
|
-
:text =>
|
461
|
+
:text => lambda do |value|
|
455
462
|
if swt_widget.is_a?(Browser)
|
456
463
|
value.to_s
|
457
464
|
else
|
458
465
|
value.to_s
|
459
466
|
end
|
460
467
|
end,
|
461
|
-
:visible =>
|
468
|
+
:visible => lambda do |value|
|
462
469
|
!!value
|
463
470
|
end,
|
464
471
|
}
|
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.7.
|
4
|
+
version: 0.7.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- AndyMaleh
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-05-
|
11
|
+
date: 2020-05-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|