glimmer 0.7.1 → 0.7.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/{README.markdown → README.md} +85 -17
- data/VERSION +1 -1
- data/lib/glimmer/data_binding/model_binding.rb +4 -4
- data/lib/glimmer/data_binding/observable_model.rb +1 -3
- data/lib/glimmer/data_binding/table_items_binding.rb +1 -0
- data/lib/glimmer/data_binding/tree_items_binding.rb +30 -11
- data/lib/glimmer/dsl/engine.rb +8 -7
- data/lib/glimmer/dsl/swt/widget_expression.rb +8 -1
- data/lib/glimmer/launcher.rb +6 -0
- data/lib/glimmer/scaffold.rb +3 -3
- data/lib/glimmer/swt/shell_proxy.rb +36 -32
- data/lib/glimmer/swt/tab_item_proxy.rb +6 -0
- data/lib/glimmer/swt/tree_proxy.rb +120 -0
- data/lib/glimmer/swt/widget_listener_proxy.rb +21 -4
- data/lib/glimmer/swt/widget_proxy.rb +60 -25
- data/lib/glimmer/ui/custom_widget.rb +4 -0
- metadata +7 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 94497522f529a193db5b827f739dcf4eab4a23c0c0ac583d7352cd7bd8270a83
|
4
|
+
data.tar.gz: a7a6a6ff9816f5be2422b5bd53c020f8152b47a436cd2cc805690e3af3cb5612
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '095cae0665dbdb73713608a2b2ba9029e0693a33796e4e61ee8463f7f4dcdb385ef04f6fa5f1b3ef2cc48db11492b6bb1c6adff6eeb9de89639a7a1993c3ae1a'
|
7
|
+
data.tar.gz: 5513aac74d33b07ee14dbc430938e1f059a5a76a842d6dbbfef2b29c5fede52f2c57a3aea2053835b411da346bd3c7dca9bdddea385742363a6bf6ed8dbb7d40
|
@@ -1,12 +1,16 @@
|
|
1
|
-
# Glimmer 0.7.
|
1
|
+
# Glimmer 0.7.6 Beta (Desktop Development Library for Ruby)
|
2
2
|
[![Gem Version](https://badge.fury.io/rb/glimmer.svg)](http://badge.fury.io/rb/glimmer)
|
3
|
-
[![
|
3
|
+
[![Travis CI](https://travis-ci.com/AndyObtiva/glimmer.svg?branch=master)](https://travis-ci.com/github/AndyObtiva/glimmer)
|
4
|
+
<!-- [![Coverage Status](https://coveralls.io/repos/github/AndyObtiva/glimmer/badge.svg?branch=master)](https://coveralls.io/github/AndyObtiva/glimmer?branch=master) -->
|
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
|
6
|
+
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.
|
7
|
+
|
8
|
+
[<img src="https://covers.oreillystatic.com/images/9780596519650/lrg.jpg" width=105 /><br />
|
9
|
+
Featured in<br />JRuby Cookbook](http://shop.oreilly.com/product/9780596519650.do)
|
6
10
|
|
7
11
|
## Examples
|
8
12
|
|
9
|
-
### Hello World
|
13
|
+
### Hello, World!
|
10
14
|
|
11
15
|
Glimmer code (from `samples/hello/hello_world.rb`):
|
12
16
|
```ruby
|
@@ -70,12 +74,10 @@ NOTE: Glimmer is in beta mode. Please help make better by adopting for small or
|
|
70
74
|
|
71
75
|
## Table of Contents
|
72
76
|
|
73
|
-
|
74
|
-
- [Glimmer 0.7.1 Beta (JRuby Desktop UI DSL + Data-Binding)](#glimmer-058-beta-jruby-desktop-ui-dsl--data-binding)
|
77
|
+
- [Glimmer 0.7.6 Beta (Desktop Development Library for Ruby)](#glimmer-075-beta-desktop-development-library-for-ruby)
|
75
78
|
- [Examples](#examples)
|
76
|
-
- [Hello World](#hello-world)
|
79
|
+
- [Hello, World!](#hello-world)
|
77
80
|
- [Tic Tac Toe](#tic-tac-toe)
|
78
|
-
- [Table of Contents](#table-of-contents)
|
79
81
|
- [Background](#background)
|
80
82
|
- [Platform Support](#platform-support)
|
81
83
|
- [Pre-requisites](#pre-requisites)
|
@@ -85,6 +87,7 @@ NOTE: Glimmer is in beta mode. Please help make better by adopting for small or
|
|
85
87
|
- [Glimmer Command](#glimmer-command)
|
86
88
|
- [Basic Usage](#basic-usage)
|
87
89
|
- [Advanced Usage](#advanced-usage)
|
90
|
+
- [Scaffolding](#scaffolding)
|
88
91
|
- [Girb (Glimmer irb) Command](#girb-glimmer-irb-command)
|
89
92
|
- [Glimmer DSL Syntax](#glimmer-dsl-syntax)
|
90
93
|
- [Widgets](#widgets)
|
@@ -99,6 +102,9 @@ NOTE: Glimmer is in beta mode. Please help make better by adopting for small or
|
|
99
102
|
- [Miscellaneous](#miscellaneous)
|
100
103
|
- [Glimmer Style Guide](#glimmer-style-guide)
|
101
104
|
- [Samples](#samples)
|
105
|
+
- [Hello Samples](#hello-samples)
|
106
|
+
- [Elaborate Samples](#elaborate-samples)
|
107
|
+
- [In Production](#in-production)
|
102
108
|
- [SWT Reference](#swt-reference)
|
103
109
|
- [SWT Packages](#swt-packages)
|
104
110
|
- [Logging](#logging)
|
@@ -111,15 +117,14 @@ NOTE: Glimmer is in beta mode. Please help make better by adopting for small or
|
|
111
117
|
- [Self Signed Certificate](#self-signed-certificate)
|
112
118
|
- [Gotchas](#gotchas)
|
113
119
|
- [Resources](#resources)
|
120
|
+
- [Help](#help)
|
121
|
+
- [Issues](#issues)
|
122
|
+
- [IRC Channel](#irc-channel)
|
114
123
|
- [Feature Suggestions](#feature-suggestions)
|
115
124
|
- [Change Log](#change-log)
|
116
125
|
- [Contributing](#contributing)
|
117
126
|
- [Contributors](#contributors)
|
118
127
|
- [License](#license)
|
119
|
-
<!-- TOC END -->
|
120
|
-
|
121
|
-
|
122
|
-
|
123
128
|
## Background
|
124
129
|
|
125
130
|
Ruby is a dynamically-typed object-oriented language, which provides great productivity gains due to its powerful expressive syntax and dynamic nature. While it is proven by the Ruby on Rails framework for web development, it currently lacks a robust platform-independent framework for building desktop applications. Given that Java libraries can now be utilized in Ruby code through JRuby, Eclipse technologies, such as SWT, JFace, and RCP can help fill the gap of desktop application development with Ruby.
|
@@ -164,7 +169,7 @@ Please follow these instructions to make the `glimmer` command available on your
|
|
164
169
|
|
165
170
|
Run this command to install directly:
|
166
171
|
```
|
167
|
-
jgem install glimmer -v 0.7.
|
172
|
+
jgem install glimmer -v 0.7.6
|
168
173
|
```
|
169
174
|
|
170
175
|
`jgem` is JRuby's version of `gem` command.
|
@@ -175,7 +180,7 @@ Otherwise, you may also run `jruby -S gem install ...`
|
|
175
180
|
|
176
181
|
Add the following to `Gemfile`:
|
177
182
|
```
|
178
|
-
gem 'glimmer', '~> 0.7.
|
183
|
+
gem 'glimmer', '~> 0.7.6'
|
179
184
|
```
|
180
185
|
|
181
186
|
And, then run:
|
@@ -734,6 +739,7 @@ Glimmer ships with SWT style **smart defaults** so you wouldn't have to set them
|
|
734
739
|
|
735
740
|
- `text(:border)`
|
736
741
|
- `table(:border)`
|
742
|
+
- `tree(:border, :virtual, :v_scroll, :h_scroll)`
|
737
743
|
- `spinner(:border)`
|
738
744
|
- `list(:border, :v_scroll)`
|
739
745
|
- `button(:push)`
|
@@ -1075,7 +1081,7 @@ https://help.eclipse.org/2019-12/nftopic/org.eclipse.platform.doc.isv/reference/
|
|
1075
1081
|
|
1076
1082
|
Data-binding is done with `bind` command following widget property to bind and taking model and bindable attribute as arguments.
|
1077
1083
|
|
1078
|
-
|
1084
|
+
#### General data-binding examples:
|
1079
1085
|
|
1080
1086
|
`text bind(contact, :first_name)`
|
1081
1087
|
|
@@ -1098,6 +1104,10 @@ This example also specifies a converter on read of the model property, but via a
|
|
1098
1104
|
|
1099
1105
|
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
1106
|
|
1107
|
+
`text bind(contact, 'address.street', read_only: true)
|
1108
|
+
|
1109
|
+
This is read-ohly data-binding. It doesn't update contact.address.street when widget text property is changed.
|
1110
|
+
|
1101
1111
|
`text bind(contact, 'addresses[1].street')`
|
1102
1112
|
|
1103
1113
|
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 +1126,8 @@ This example demonstrates nested indexed computed value data binding whereby the
|
|
1116
1126
|
|
1117
1127
|
Example from [samples/hello/hello_combo.rb](samples/hello_combo.rb) sample (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
|
1118
1128
|
|
1129
|
+
#### Combo
|
1130
|
+
|
1119
1131
|
![Hello Combo](images/glimmer-hello-combo.png)
|
1120
1132
|
|
1121
1133
|
![Hello Combo](images/glimmer-hello-combo-expanded.png)
|
@@ -1159,6 +1171,8 @@ HelloCombo.new.launch
|
|
1159
1171
|
|
1160
1172
|
`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
1173
|
|
1174
|
+
#### List
|
1175
|
+
|
1162
1176
|
Example from [samples/hello/hello_list_single_selection.rb](samples/hello_list_single_selection.rb) sample:
|
1163
1177
|
|
1164
1178
|
![Hello List Single Selection](images/glimmer-hello-list-single-selection.png)
|
@@ -1240,6 +1254,45 @@ Note that in all the data-binding examples above, there was also an observer att
|
|
1240
1254
|
|
1241
1255
|
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
1256
|
|
1257
|
+
#### Tree
|
1258
|
+
|
1259
|
+
The SWT Tree widget visualizes a tree data-structure, such as an employment or composition hierarchy.
|
1260
|
+
|
1261
|
+
To data-bind a Tree, you need the root model, the children querying method, and the text display attribute on each child.
|
1262
|
+
|
1263
|
+
This involves using the `bind` keyword mentioned above in addition to a special `tree_properties` keyword that takes the children and text attribute methods.
|
1264
|
+
|
1265
|
+
Example:
|
1266
|
+
|
1267
|
+
```ruby
|
1268
|
+
shell {
|
1269
|
+
@tree = tree {
|
1270
|
+
items bind(company, :owner), tree_properties(children: :coworkers, text: :name)
|
1271
|
+
selection bind(company, :selected_coworker)
|
1272
|
+
}
|
1273
|
+
}
|
1274
|
+
```
|
1275
|
+
|
1276
|
+
The code above includes two data-bindings:
|
1277
|
+
- 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.
|
1278
|
+
- Tree `selection`, which binds the single tree item selected by the user to the attribute denoted by the `bind` keyword
|
1279
|
+
|
1280
|
+
Additionally, Tree `items` data-binding automatically stores each node model unto the SWT TreeItem object via `setData` method. This enables things like searchability.
|
1281
|
+
|
1282
|
+
The tree widget in Glimmer is represented by a subclass of `WidgetProxy` called `TreeProxy`.
|
1283
|
+
TreeProxy includes a `depth_first_search` method that takes a block to look for a tree item.
|
1284
|
+
|
1285
|
+
Example:
|
1286
|
+
|
1287
|
+
```ruby
|
1288
|
+
found_array = @tree.depth_first_search { |tree_item| tree_item.getData == company.owner }
|
1289
|
+
```
|
1290
|
+
|
1291
|
+
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.
|
1292
|
+
|
1293
|
+
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
|
1294
|
+
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.
|
1295
|
+
|
1243
1296
|
### Observer
|
1244
1297
|
|
1245
1298
|
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.
|
@@ -1925,7 +1978,7 @@ glimmer samples/elaborate/contact_manager.rb # demonstrates table data-binding
|
|
1925
1978
|
glimmer samples/elaborate/tic_tac_toe.rb # demonstrates a full MVC application
|
1926
1979
|
```
|
1927
1980
|
|
1928
|
-
![Gladiator](images/glimmer-gladiator.png)
|
1981
|
+
![Gladiator](https://raw.githubusercontent.com/AndyObtiva/glimmer-cs-gladiator/v0.1.5/images/glimmer-gladiator.png)
|
1929
1982
|
|
1930
1983
|
[Gladiator](https://github.com/AndyObtiva/glimmer-cs-gladiator) (short for Glimmer Editor) is a Glimmer sample project under on-going development.
|
1931
1984
|
You may check it out to learn how to build a Glimmer Custom Shell gem.
|
@@ -2194,10 +2247,25 @@ Exec failed with code 2 command [[/usr/bin/SetFile, -c, icnC, /var/folders/4_/g1
|
|
2194
2247
|
|
2195
2248
|
## Resources
|
2196
2249
|
|
2250
|
+
* [Code Master Blog](http://andymaleh.blogspot.com/search/label/Glimmer)
|
2197
2251
|
* [Eclipse Zone Tutorial](http://eclipse.dzone.com/articles/an-introduction-glimmer)
|
2198
2252
|
* [InfoQ Article](http://www.infoq.com/news/2008/02/glimmer-jruby-swt)
|
2199
2253
|
* [RubyConf 2008 Video](https://confreaks.tv/videos/rubyconf2008-desktop-development-with-glimmer)
|
2200
|
-
* [
|
2254
|
+
* [JRuby Cookbook by Justin Edelson & Henry Liu](http://shop.oreilly.com/product/9780596519650.do)
|
2255
|
+
|
2256
|
+
## Help
|
2257
|
+
|
2258
|
+
### Issues
|
2259
|
+
|
2260
|
+
You may submit [issues](https://github.com/AndyObtiva/glimmer/issues) on [GitHub](https://github.com/AndyObtiva/glimmer/issues).
|
2261
|
+
|
2262
|
+
[Click here to submit an issue.](https://github.com/AndyObtiva/glimmer/issues)
|
2263
|
+
|
2264
|
+
### IRC Channel
|
2265
|
+
|
2266
|
+
If you need live help, try the [#glimmer](http://widget.mibbit.com/?settings=7514b8a196f8f1de939a351245db7aa8&server=irc.mibbit.net&channel=%23glimmer) IRC channel on [irc.mibbit.net](http://widget.mibbit.com/?settings=7514b8a196f8f1de939a351245db7aa8&server=irc.mibbit.net&channel=%23glimmer). If no one was available, you may [leave a GitHub issue](https://github.com/AndyObtiva/glimmer/issues) to schedule a meetup on IRC.
|
2267
|
+
|
2268
|
+
[Click here to connect to #glimmer IRC channel immediately via a web interface.](http://widget.mibbit.com/?settings=7514b8a196f8f1de939a351245db7aa8&server=irc.mibbit.net&channel=%23glimmer)
|
2201
2269
|
|
2202
2270
|
## Feature Suggestions
|
2203
2271
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.7.
|
1
|
+
0.7.6
|
@@ -203,10 +203,9 @@ module Glimmer
|
|
203
203
|
end
|
204
204
|
|
205
205
|
def evaluate_property
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
end
|
206
|
+
value = nil
|
207
|
+
value = invoke_property_reader(model, property_name) unless model.nil?
|
208
|
+
convert_on_read(value)
|
210
209
|
end
|
211
210
|
|
212
211
|
def evaluate_options_property
|
@@ -233,6 +232,7 @@ module Glimmer
|
|
233
232
|
end
|
234
233
|
|
235
234
|
def invoke_property_writer(object, property_expression, value)
|
235
|
+
return if @binding_options[:read_only]
|
236
236
|
value = convert_on_write(value)
|
237
237
|
if property_indexed?(property_expression)
|
238
238
|
property_method = '[]='
|
@@ -40,9 +40,7 @@ module Glimmer
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def property_observer_hash
|
43
|
-
|
44
|
-
@property_observers = Hash.new unless @property_observers
|
45
|
-
@property_observers
|
43
|
+
@property_observers ||= Hash.new
|
46
44
|
end
|
47
45
|
|
48
46
|
def property_observer_list(property_name)
|
@@ -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,26 +30,40 @@ 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
|
+
old_tree_items = parent.all_tree_items
|
42
|
+
old_tree_item_expansion_by_data = old_tree_items.reduce({}) {|hash, ti| hash.merge(ti.getData => ti.getExpanded)}
|
43
|
+
old_tree_items.each do |tree_item|
|
44
|
+
tree_item.getData('observer_registrations').each do |key, observer_registration|
|
45
|
+
observer_registration.unregister
|
46
|
+
end
|
47
|
+
end
|
38
48
|
parent.swt_widget.removeAll
|
39
49
|
populate_tree_node(model_tree_root_node, parent.swt_widget, tree_properties)
|
50
|
+
parent.all_tree_items.each { |ti| ti.setExpanded(!!old_tree_item_expansion_by_data[ti.getData]) }
|
51
|
+
tree_item_to_select = parent.depth_first_search {|ti| ti.getData == selected_tree_item_model}
|
52
|
+
parent.swt_widget.setSelection(tree_item_to_select)
|
40
53
|
end
|
41
54
|
|
42
55
|
def populate_tree_node(model_tree_node, parent, tree_properties)
|
43
|
-
|
44
|
-
|
56
|
+
return if model_tree_node.nil?
|
57
|
+
# TODO anticipate default tree properties if none were passed (like literal values text and children)
|
58
|
+
tree_item = TreeItem.new(parent, SWT::SWTProxy[:none])
|
59
|
+
observer_registrations = @tree_properties.reduce({}) do |hash, key_value_pair|
|
60
|
+
hash.merge(key_value_pair.first => observe(model_tree_node, key_value_pair.last))
|
61
|
+
end
|
62
|
+
tree_item.setData('observer_registrations', observer_registrations)
|
63
|
+
tree_item.setData(model_tree_node)
|
64
|
+
tree_item.setText((model_tree_node && model_tree_node.send(tree_properties[:text])).to_s)
|
45
65
|
[model_tree_node && model_tree_node.send(tree_properties[:children])].flatten.to_a.compact.each do |child|
|
46
|
-
|
47
|
-
populate_tree_node(child, table_item, tree_properties)
|
66
|
+
populate_tree_node(child, tree_item, tree_properties)
|
48
67
|
end
|
49
68
|
end
|
50
69
|
end
|
data/lib/glimmer/dsl/engine.rb
CHANGED
@@ -100,7 +100,7 @@ module Glimmer
|
|
100
100
|
return Glimmer::DSL::Engine.interpret(keyword, *args, &block)
|
101
101
|
rescue => e
|
102
102
|
Glimmer::DSL::Engine.reset
|
103
|
-
raise e if static_expression_dsl.nil?
|
103
|
+
raise e if static_expression_dsl.nil? || !Glimmer::DSL::Engine.static_expressions[keyword][static_expression_dsl].is_a?(TopLevelExpression)
|
104
104
|
end
|
105
105
|
end
|
106
106
|
raise Glimmer::Error, "Unsupported keyword: #{keyword}" unless static_expression_dsl || retrieved_static_expression
|
@@ -153,12 +153,13 @@ module Glimmer
|
|
153
153
|
#
|
154
154
|
# For example, a shell widget would get properties set and children added
|
155
155
|
def add_content(parent, expression, &block)
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
156
|
+
if block_given? && expression.is_a?(ParentExpression)
|
157
|
+
dsl_stack.push(expression.class.dsl)
|
158
|
+
parent_stack.push(parent)
|
159
|
+
expression.add_content(parent, &block)
|
160
|
+
parent_stack.pop
|
161
|
+
dsl_stack.pop
|
162
|
+
end
|
162
163
|
end
|
163
164
|
|
164
165
|
# Current parent while evaluating Glimmer DSL (nil if just started or done evaluatiing)
|
@@ -17,7 +17,13 @@ module Glimmer
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def interpret(parent, keyword, *args, &block)
|
20
|
-
|
20
|
+
begin
|
21
|
+
class_name = "#{keyword.camelcase(:upper)}Proxy".to_sym
|
22
|
+
widget_class = Glimmer::SWT.const_get(class_name)
|
23
|
+
rescue
|
24
|
+
widget_class = Glimmer::SWT::WidgetProxy
|
25
|
+
end
|
26
|
+
widget_class.new(keyword, parent, args)
|
21
27
|
end
|
22
28
|
end
|
23
29
|
end
|
@@ -25,3 +31,4 @@ module Glimmer
|
|
25
31
|
end
|
26
32
|
|
27
33
|
require 'glimmer/swt/widget_proxy'
|
34
|
+
require 'glimmer/swt/tree_proxy'
|
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)
|
@@ -135,6 +140,7 @@ module Glimmer
|
|
135
140
|
private
|
136
141
|
|
137
142
|
def launch_application
|
143
|
+
load File.expand_path('./Rakefile') if File.exist?(File.expand_path('./Rakefile'))
|
138
144
|
threads = @application_paths.map do |application_path|
|
139
145
|
Thread.new do
|
140
146
|
self.class.launch(
|
data/lib/glimmer/scaffold.rb
CHANGED
@@ -286,8 +286,6 @@ class Scaffold
|
|
286
286
|
app_view.open
|
287
287
|
end
|
288
288
|
end
|
289
|
-
|
290
|
-
#{class_name(app_name)}.new.open
|
291
289
|
MULTI_LINE_STRING
|
292
290
|
end
|
293
291
|
|
@@ -307,8 +305,10 @@ class Scaffold
|
|
307
305
|
def app_bin_file(app_name)
|
308
306
|
<<~MULTI_LINE_STRING
|
309
307
|
#!/usr/bin/env ruby
|
310
|
-
|
308
|
+
|
311
309
|
require_relative '../app/#{file_name(app_name)}'
|
310
|
+
|
311
|
+
#{class_name(app_name)}.new.open
|
312
312
|
MULTI_LINE_STRING
|
313
313
|
end
|
314
314
|
|
@@ -20,33 +20,39 @@ module Glimmer
|
|
20
20
|
alias opened_before? opened_before
|
21
21
|
|
22
22
|
# Instantiates ShellProxy with same arguments expected by SWT Shell
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
23
|
+
# if swt_widget keyword arg was passed, then it is assumed the shell has already been instantiated
|
24
|
+
# and the proxy wraps it instead of creating a new one.
|
25
|
+
def initialize(*args, swt_widget: nil)
|
26
|
+
if swt_widget
|
27
|
+
@swt_widget = swt_widget
|
28
|
+
else
|
29
|
+
if args.first.is_a?(ShellProxy)
|
30
|
+
args[0] = args[0].swt_widget
|
31
|
+
end
|
32
|
+
style_args = args.select {|arg| arg.is_a?(Symbol) || arg.is_a?(String)}
|
33
|
+
if style_args.any?
|
34
|
+
style_arg_start_index = args.index(style_args.first)
|
35
|
+
style_arg_last_index = args.index(style_args.last)
|
36
|
+
args[style_arg_start_index..style_arg_last_index] = SWTProxy[style_args]
|
37
|
+
end
|
38
|
+
if args.first.nil? || (!args.first.is_a?(Display) && !args.first.is_a?(Shell))
|
39
|
+
@display = DisplayProxy.instance.swt_display
|
40
|
+
args = [@display] + args
|
41
|
+
end
|
42
|
+
args = args.compact
|
43
|
+
@swt_widget = Shell.new(*args)
|
44
|
+
@swt_widget.setLayout(FillLayout.new)
|
45
|
+
@swt_widget.setMinimumSize(WIDTH_MIN, HEIGHT_MIN)
|
46
|
+
on_event_show do
|
47
|
+
Thread.new do
|
48
|
+
sleep(0.25)
|
49
|
+
async_exec do
|
50
|
+
@swt_widget.setActive unless @swt_widget.isDisposed
|
51
|
+
end
|
47
52
|
end
|
48
53
|
end
|
49
54
|
end
|
55
|
+
@display ||= @swt_widget.getDisplay
|
50
56
|
end
|
51
57
|
|
52
58
|
# Centers shell within monitor it is in
|
@@ -96,16 +102,14 @@ module Glimmer
|
|
96
102
|
end
|
97
103
|
|
98
104
|
def pack_same_size
|
99
|
-
minimum_size = @swt_widget.getMinimumSize
|
100
105
|
bounds = @swt_widget.getBounds
|
101
|
-
@swt_widget.
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
}
|
106
|
+
width = @swt_widget.getBounds.width
|
107
|
+
height = @swt_widget.getBounds.height
|
108
|
+
x = @swt_widget.getBounds.x
|
109
|
+
y = @swt_widget.getBounds.y
|
106
110
|
@swt_widget.pack
|
107
|
-
@swt_widget.
|
108
|
-
@swt_widget.
|
111
|
+
@swt_widget.setSize(width, height)
|
112
|
+
@swt_widget.setLocation(x, y)
|
109
113
|
end
|
110
114
|
|
111
115
|
def content(&block)
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'glimmer/swt/widget_proxy'
|
2
|
+
|
3
|
+
module Glimmer
|
4
|
+
module SWT
|
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
|
+
|
19
|
+
# Performs depth first search for tree items matching block condition
|
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
|
22
|
+
def depth_first_search(&condition)
|
23
|
+
found = []
|
24
|
+
recursive_depth_first_search(swt_widget.getItems.first, found, &condition)
|
25
|
+
found.to_java(TreeItem)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns all tree items including descendants
|
29
|
+
def all_tree_items
|
30
|
+
depth_first_search
|
31
|
+
end
|
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
|
+
|
101
|
+
private
|
102
|
+
|
103
|
+
def recursive_depth_first_search(tree_item, found, &condition)
|
104
|
+
return if tree_item.nil?
|
105
|
+
found << tree_item if condition.nil? || condition.call(tree_item)
|
106
|
+
tree_item.getItems.each do |child_tree_item|
|
107
|
+
recursive_depth_first_search(child_tree_item, found, &condition)
|
108
|
+
end
|
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
|
118
|
+
end
|
119
|
+
end
|
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
|
}
|
@@ -102,10 +105,24 @@ module Glimmer
|
|
102
105
|
end
|
103
106
|
end
|
104
107
|
|
108
|
+
def pack_same_size
|
109
|
+
bounds = @swt_widget.getBounds
|
110
|
+
listener = on_control_resized {
|
111
|
+
@swt_widget.setSize(bounds.width, bounds.height)
|
112
|
+
@swt_widget.setLocation(bounds.x, bounds.y)
|
113
|
+
}
|
114
|
+
if @swt_widget.is_a?(Composite)
|
115
|
+
@swt_widget.layout(true, true)
|
116
|
+
else
|
117
|
+
@swt_widget.pack(true)
|
118
|
+
end
|
119
|
+
@swt_widget.removeControlListener(listener.swt_listener)
|
120
|
+
end
|
121
|
+
|
105
122
|
def widget_property_listener_installers
|
106
123
|
@swt_widget_property_listener_installers ||= {
|
107
124
|
Java::OrgEclipseSwtWidgets::Control => {
|
108
|
-
:focus =>
|
125
|
+
:focus => lambda do |observer|
|
109
126
|
on_focus_gained { |focus_event|
|
110
127
|
observer.call(true)
|
111
128
|
}
|
@@ -115,12 +132,12 @@ module Glimmer
|
|
115
132
|
end,
|
116
133
|
},
|
117
134
|
Java::OrgEclipseSwtWidgets::Text => {
|
118
|
-
:text =>
|
135
|
+
:text => lambda do |observer|
|
119
136
|
on_modify_text { |modify_event|
|
120
137
|
observer.call(@swt_widget.getText)
|
121
138
|
}
|
122
139
|
end,
|
123
|
-
:caret_position =>
|
140
|
+
:caret_position => lambda do |observer|
|
124
141
|
on_event_keydown { |event|
|
125
142
|
observer.call(@swt_widget.getCaretPosition)
|
126
143
|
}
|
@@ -134,7 +151,21 @@ module Glimmer
|
|
134
151
|
observer.call(@swt_widget.getCaretPosition)
|
135
152
|
}
|
136
153
|
end,
|
137
|
-
:
|
154
|
+
:selection => lambda do |observer|
|
155
|
+
on_event_keydown { |event|
|
156
|
+
observer.call(@swt_widget.getSelection)
|
157
|
+
}
|
158
|
+
on_event_keyup { |event|
|
159
|
+
observer.call(@swt_widget.getSelection)
|
160
|
+
}
|
161
|
+
on_event_mousedown { |event|
|
162
|
+
observer.call(@swt_widget.getSelection)
|
163
|
+
}
|
164
|
+
on_event_mouseup { |event|
|
165
|
+
observer.call(@swt_widget.getSelection)
|
166
|
+
}
|
167
|
+
end,
|
168
|
+
:selection_count => lambda do |observer|
|
138
169
|
on_event_keydown { |event|
|
139
170
|
observer.call(@swt_widget.getSelectionCount)
|
140
171
|
}
|
@@ -148,7 +179,7 @@ module Glimmer
|
|
148
179
|
observer.call(@swt_widget.getSelectionCount)
|
149
180
|
}
|
150
181
|
end,
|
151
|
-
:top_index =>
|
182
|
+
:top_index => lambda do |observer|
|
152
183
|
@last_top_index = @swt_widget.getTopIndex
|
153
184
|
on_paint_control { |event|
|
154
185
|
if @swt_widget.getTopIndex != @last_top_index
|
@@ -159,33 +190,33 @@ module Glimmer
|
|
159
190
|
end,
|
160
191
|
},
|
161
192
|
Java::OrgEclipseSwtCustom::StyledText => {
|
162
|
-
:text =>
|
193
|
+
:text => lambda do |observer|
|
163
194
|
on_modify_text { |modify_event|
|
164
195
|
observer.call(@swt_widget.getText)
|
165
196
|
}
|
166
197
|
end,
|
167
198
|
},
|
168
199
|
Java::OrgEclipseSwtWidgets::Button => {
|
169
|
-
:selection =>
|
200
|
+
:selection => lambda do |observer|
|
170
201
|
on_widget_selected { |selection_event|
|
171
202
|
observer.call(@swt_widget.getSelection)
|
172
203
|
}
|
173
204
|
end
|
174
205
|
},
|
175
206
|
Java::OrgEclipseSwtWidgets::MenuItem => {
|
176
|
-
:selection =>
|
207
|
+
:selection => lambda do |observer|
|
177
208
|
on_widget_selected { |selection_event|
|
178
209
|
observer.call(@swt_widget.getSelection)
|
179
210
|
}
|
180
211
|
end
|
181
212
|
},
|
182
213
|
Java::OrgEclipseSwtWidgets::Spinner => {
|
183
|
-
:selection =>
|
214
|
+
:selection => lambda do |observer|
|
184
215
|
on_widget_selected { |selection_event|
|
185
216
|
observer.call(@swt_widget.getSelection)
|
186
217
|
}
|
187
218
|
end
|
188
|
-
}
|
219
|
+
},
|
189
220
|
}
|
190
221
|
end
|
191
222
|
|
@@ -307,10 +338,12 @@ module Glimmer
|
|
307
338
|
end
|
308
339
|
|
309
340
|
def add_listener(underscored_listener_name, &block)
|
310
|
-
widget_add_listener_method, listener_class, listener_method = self.class.find_listener(@swt_widget.getClass, underscored_listener_name)
|
311
|
-
|
341
|
+
widget_add_listener_method, listener_class, listener_method = self.class.find_listener(@swt_widget.getClass, underscored_listener_name)
|
342
|
+
widget_listener_proxy = nil
|
343
|
+
safe_block = lambda { |event| block.call(event) unless @swt_widget.isDisposed }
|
344
|
+
listener = listener_class.new(listener_method => safe_block)
|
312
345
|
@swt_widget.send(widget_add_listener_method, listener)
|
313
|
-
WidgetListenerProxy.new(listener)
|
346
|
+
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)
|
314
347
|
end
|
315
348
|
|
316
349
|
# Looks through SWT class add***Listener methods till it finds one for which
|
@@ -361,8 +394,10 @@ module Glimmer
|
|
361
394
|
|
362
395
|
def add_swt_event_listener(swt_constant, &block)
|
363
396
|
event_type = SWTProxy[swt_constant]
|
364
|
-
|
365
|
-
|
397
|
+
widget_listener_proxy = nil
|
398
|
+
safe_block = lambda { |event| block.call(event) unless @swt_widget.isDisposed }
|
399
|
+
@swt_widget.addListener(event_type, &safe_block)
|
400
|
+
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)
|
366
401
|
end
|
367
402
|
|
368
403
|
def widget_custom_attribute_mapping
|
@@ -395,7 +430,7 @@ module Glimmer
|
|
395
430
|
end
|
396
431
|
|
397
432
|
def property_type_converters
|
398
|
-
color_converter =
|
433
|
+
color_converter = lambda do |value|
|
399
434
|
if value.is_a?(Symbol) || value.is_a?(String)
|
400
435
|
ColorProxy.new(value).swt_color
|
401
436
|
else
|
@@ -405,7 +440,7 @@ module Glimmer
|
|
405
440
|
# TODO consider detecting type on widget method and automatically invoking right converter (e.g. :to_s for String, :to_i for Integer)
|
406
441
|
@property_type_converters ||= {
|
407
442
|
:background => color_converter,
|
408
|
-
:background_image =>
|
443
|
+
:background_image => lambda do |value|
|
409
444
|
if value.is_a?(String)
|
410
445
|
if value.start_with?('uri:classloader')
|
411
446
|
value = value.sub(/^uri\:classloader\:\//, '')
|
@@ -426,7 +461,7 @@ module Glimmer
|
|
426
461
|
end
|
427
462
|
end,
|
428
463
|
:foreground => color_converter,
|
429
|
-
:font =>
|
464
|
+
:font => lambda do |value|
|
430
465
|
if value.is_a?(Hash)
|
431
466
|
font_properties = value
|
432
467
|
FontProxy.new(self, font_properties).swt_font
|
@@ -434,17 +469,17 @@ module Glimmer
|
|
434
469
|
value
|
435
470
|
end
|
436
471
|
end,
|
437
|
-
:items =>
|
472
|
+
:items => lambda do |value|
|
438
473
|
value.to_java :string
|
439
474
|
end,
|
440
|
-
:text =>
|
475
|
+
:text => lambda do |value|
|
441
476
|
if swt_widget.is_a?(Browser)
|
442
477
|
value.to_s
|
443
478
|
else
|
444
479
|
value.to_s
|
445
480
|
end
|
446
481
|
end,
|
447
|
-
:visible =>
|
482
|
+
:visible => lambda do |value|
|
448
483
|
!!value
|
449
484
|
end,
|
450
485
|
}
|
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.6
|
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-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -192,9 +192,7 @@ dependencies:
|
|
192
192
|
- - "~>"
|
193
193
|
- !ruby/object:Gem::Version
|
194
194
|
version: 0.8.1
|
195
|
-
description:
|
196
|
-
that enables productive and efficient authoring of desktop user-interfaces using
|
197
|
-
the robust Eclipse SWT library
|
195
|
+
description: Desktop Development Library for Ruby
|
198
196
|
email: andy.am@gmail.com
|
199
197
|
executables:
|
200
198
|
- glimmer
|
@@ -202,10 +200,10 @@ executables:
|
|
202
200
|
extensions: []
|
203
201
|
extra_rdoc_files:
|
204
202
|
- LICENSE.txt
|
205
|
-
- README.
|
203
|
+
- README.md
|
206
204
|
files:
|
207
205
|
- LICENSE.txt
|
208
|
-
- README.
|
206
|
+
- README.md
|
209
207
|
- RUBY_VERSION
|
210
208
|
- VERSION
|
211
209
|
- bin/girb
|
@@ -292,6 +290,7 @@ files:
|
|
292
290
|
- lib/glimmer/swt/shell_proxy.rb
|
293
291
|
- lib/glimmer/swt/swt_proxy.rb
|
294
292
|
- lib/glimmer/swt/tab_item_proxy.rb
|
293
|
+
- lib/glimmer/swt/tree_proxy.rb
|
295
294
|
- lib/glimmer/swt/widget_listener_proxy.rb
|
296
295
|
- lib/glimmer/swt/widget_proxy.rb
|
297
296
|
- lib/glimmer/ui/custom_shell.rb
|
@@ -327,5 +326,5 @@ requirements: []
|
|
327
326
|
rubygems_version: 3.0.6
|
328
327
|
signing_key:
|
329
328
|
specification_version: 4
|
330
|
-
summary: Desktop
|
329
|
+
summary: Desktop Development Library for Ruby
|
331
330
|
test_files: []
|