glimmer 0.8.1 → 0.8.2
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.md +114 -19
- data/VERSION +1 -1
- data/lib/glimmer/data_binding/table_items_binding.rb +14 -5
- data/lib/glimmer/dsl/swt/message_box_expression.rb +29 -0
- data/lib/glimmer/dsl/swt/widget_expression.rb +1 -0
- data/lib/glimmer/package.rb +48 -0
- data/lib/glimmer/rake_task.rb +11 -42
- data/lib/glimmer/swt/message_box_proxy.rb +48 -0
- data/lib/glimmer/swt/shell_proxy.rb +8 -13
- data/lib/glimmer/swt/table_proxy.rb +150 -0
- data/lib/glimmer/swt/tree_proxy.rb +1 -1
- metadata +9 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fbe97823fd25586221485191db661a4cb6fe71d8d9be9e89b60d617d5f496540
|
4
|
+
data.tar.gz: d81b11d52ce3f0fe1fdb46d9f1a6c286ccd95c3021118f71b4f72d7724cd0f41
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 930a0914fc83db952df2eba9321779ee34a3d2819a0dabb05a31615b97b1eb57ff222321bd9db9fa4d6950e0f4e68f6455a66223ac1a1126a1c72be75a8a8b46
|
7
|
+
data.tar.gz: 5ab308d9b3403a9876d8f40f8a51d277cf0c88527f257977f87a21fc530a95a0d3e92d64a6b4025a56b2ed857f3d6b1c4d0d3df10bed7999c25cf90e589d6934
|
data/README.md
CHANGED
@@ -1,7 +1,6 @@
|
|
1
|
-
# Glimmer 0.8.
|
1
|
+
# Glimmer 0.8.2 Beta (Ruby Desktop Development GUI Library)
|
2
2
|
[](http://badge.fury.io/rb/glimmer)
|
3
3
|
[](https://travis-ci.com/github/AndyObtiva/glimmer)
|
4
|
-
[](https://codeclimate.com/github/AndyObtiva/glimmer/test_coverage)
|
5
4
|
[](https://codeclimate.com/github/AndyObtiva/glimmer/maintainability)
|
6
5
|
|
7
6
|
Glimmer is a native-GUI 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 GUI with domain models. As a result, that achieves true decoupling of object oriented components, enabling developers to solve business problems without worrying about GUI concerns, or alternatively drive development GUI-first, and then write clean business models test-first afterwards.
|
@@ -71,11 +70,11 @@ Glimmer app:
|
|
71
70
|
|
72
71
|

|
73
72
|
|
74
|
-
NOTE: Glimmer is in beta mode. Please help make better by adopting for small or low risk projects and providing feedback.
|
73
|
+
NOTE: Glimmer is in beta mode. Please help make better by [contributing](#contributing), adopting for small or low risk projects, and providing feedback.
|
75
74
|
|
76
75
|
## Table of contents
|
77
76
|
|
78
|
-
- [Glimmer 0.8.
|
77
|
+
- [Glimmer 0.8.2 Beta (Ruby Desktop Development GUI Library)](#glimmer-082-beta-ruby-desktop-development-gui-library)
|
79
78
|
- [Examples](#examples)
|
80
79
|
- [Hello, World!](#hello-world)
|
81
80
|
- [Tic Tac Toe](#tic-tac-toe)
|
@@ -89,23 +88,55 @@ NOTE: Glimmer is in beta mode. Please help make better by adopting for small or
|
|
89
88
|
- [Basic Usage](#basic-usage)
|
90
89
|
- [Advanced Usage](#advanced-usage)
|
91
90
|
- [Scaffolding](#scaffolding)
|
91
|
+
- [App](#app)
|
92
|
+
- [Custom Shell](#custom-shell)
|
93
|
+
- [Custom Widget](#custom-widget)
|
94
|
+
- [Custom Shell Gem](#custom-shell-gem)
|
95
|
+
- [Custom Widget Gem](#custom-widget-gem)
|
92
96
|
- [Girb (Glimmer irb) Command](#girb-glimmer-irb-command)
|
93
97
|
- [Glimmer DSL Syntax](#glimmer-dsl-syntax)
|
94
98
|
- [Widgets](#widgets)
|
99
|
+
- [Display](#display)
|
100
|
+
- [SWT Proxies](#swt-proxies)
|
101
|
+
- [Dialog](#dialog)
|
102
|
+
- [Menus](#menus)
|
95
103
|
- [Widget Styles](#widget-styles)
|
104
|
+
- [Explicit SWT Style Bit](#explicit-swt-style-bit)
|
105
|
+
- [Negative SWT Style Bits](#negative-swt-style-bits)
|
106
|
+
- [Extra SWT Styles](#extra-swt-styles)
|
96
107
|
- [Widget Properties](#widget-properties)
|
108
|
+
- [Colors](#colors)
|
109
|
+
- [Fonts](#fonts)
|
97
110
|
- [Layouts](#layouts)
|
98
111
|
- [Layout Data](#layout-data)
|
99
112
|
- [Data-Binding](#data-binding)
|
113
|
+
- [General Examples](#general-examples)
|
114
|
+
- [Combo](#combo)
|
115
|
+
- [List](#list)
|
116
|
+
- [Table](#table)
|
117
|
+
- [Tree](#tree)
|
100
118
|
- [Observer](#observer)
|
119
|
+
- [Observing Widgets](#observing-widgets)
|
120
|
+
- [Observing Models](#observing-models)
|
101
121
|
- [Custom Widgets](#custom-widgets)
|
122
|
+
- [Simple Example](#simple-example)
|
123
|
+
- [Hook Example](#hook-example)
|
124
|
+
- [Content/Options Example](#contentoptions-example)
|
125
|
+
- [Gotcha](#gotcha)
|
102
126
|
- [Custom Shells](#custom-shells)
|
103
127
|
- [Miscellaneous](#miscellaneous)
|
128
|
+
- [Application Menu Items (About/Preferences)](#application-menu-items-aboutpreferences)
|
129
|
+
- [App Name and Version](#app-name-and-version)
|
130
|
+
- [Multi-DSL Support](#multi-dsl-support)
|
131
|
+
- [Video Widget](#video-widget)
|
132
|
+
- [Browser Widget](#browser-widget)
|
104
133
|
- [Glimmer Style Guide](#glimmer-style-guide)
|
105
134
|
- [Samples](#samples)
|
106
135
|
- [Hello Samples](#hello-samples)
|
107
136
|
- [Elaborate Samples](#elaborate-samples)
|
108
137
|
- [External Samples](#external-samples)
|
138
|
+
- [Glimmer Calculator](#glimmer-calculator)
|
139
|
+
- [Gladiator](#gladiator)
|
109
140
|
- [In Production](#in-production)
|
110
141
|
- [SWT Reference](#swt-reference)
|
111
142
|
- [SWT Packages](#swt-packages)
|
@@ -154,7 +185,7 @@ https://www.eclipse.org/swt/faq.php
|
|
154
185
|
|
155
186
|
- SWT 4.15 (comes included in Glimmer gem)
|
156
187
|
- JRuby 9.2.11.1 (supporting Ruby 2.5.x syntax) (find at [https://www.jruby.org/download](https://www.jruby.org/download))
|
157
|
-
-
|
188
|
+
- JDK 8 - 10 (find at [https://www.oracle.com/java/technologies/javase-downloads.html](https://www.oracle.com/java/technologies/javase-downloads.html))
|
158
189
|
- (Optional) RVM is needed for [Scaffolding](#scaffolding) only (find at [https://rvm.io/](https://rvm.io/))
|
159
190
|
|
160
191
|
On **Mac** and **Linux**, an easy way to obtain JRuby is through [RVM](http://rvm.io) by running:
|
@@ -173,7 +204,7 @@ Please follow these instructions to make the `glimmer` command available on your
|
|
173
204
|
|
174
205
|
Run this command to install directly:
|
175
206
|
```
|
176
|
-
jgem install glimmer -v 0.8.
|
207
|
+
jgem install glimmer -v 0.8.2
|
177
208
|
```
|
178
209
|
|
179
210
|
`jgem` is JRuby's version of `gem` command.
|
@@ -184,7 +215,7 @@ Otherwise, you may also run `jruby -S gem install ...`
|
|
184
215
|
|
185
216
|
Add the following to `Gemfile`:
|
186
217
|
```
|
187
|
-
gem 'glimmer', '~> 0.8.
|
218
|
+
gem 'glimmer', '~> 0.8.2'
|
188
219
|
```
|
189
220
|
|
190
221
|
And, then run:
|
@@ -1099,7 +1130,7 @@ https://help.eclipse.org/2019-12/nftopic/org.eclipse.platform.doc.isv/reference/
|
|
1099
1130
|
|
1100
1131
|
Data-binding is done with `bind` command following widget property to bind and taking model and bindable attribute as arguments.
|
1101
1132
|
|
1102
|
-
#### General
|
1133
|
+
#### General Examples
|
1103
1134
|
|
1104
1135
|
`text bind(contact, :first_name)`
|
1105
1136
|
|
@@ -1270,7 +1301,62 @@ The Glimmer code is not much different from above except for passing the `:multi
|
|
1270
1301
|
|
1271
1302
|
Note that in all the data-binding examples above, there was also an observer attached to the `button` widget to trigger an action on the model, which in turn triggers a data-binding update on the `list` or `combo`. Observers will be discussed in more details in the [next section](#observer).
|
1272
1303
|
|
1273
|
-
You may learn more about Glimmer's data-binding syntax by reading the
|
1304
|
+
You may learn more about Glimmer's data-binding syntax by reading the code under the [samples](samples) directory.
|
1305
|
+
|
1306
|
+
#### Table
|
1307
|
+
|
1308
|
+
The SWT Tree widget renders a multi-column data table, such as a contact listing or a sales report.
|
1309
|
+
|
1310
|
+
To data-bind a Table, you need the main model, the collection property, and the text display attribute for each table column.
|
1311
|
+
|
1312
|
+
This involves using the `bind` keyword mentioned above in addition to a special `column_properties` keyword that takes the table column text attribute methods.
|
1313
|
+
|
1314
|
+
It assumes you have defined the table columns via `table_column` widget.
|
1315
|
+
|
1316
|
+
Example:
|
1317
|
+
|
1318
|
+
```ruby
|
1319
|
+
shell {
|
1320
|
+
@table = table {
|
1321
|
+
table_column {
|
1322
|
+
text "Name"
|
1323
|
+
width 120
|
1324
|
+
}
|
1325
|
+
table_column {
|
1326
|
+
text "Age"
|
1327
|
+
width 120
|
1328
|
+
}
|
1329
|
+
table_column {
|
1330
|
+
text "Adult"
|
1331
|
+
width 120
|
1332
|
+
}
|
1333
|
+
items bind(group, :people), column_properties(:name, :age, :adult)
|
1334
|
+
selection bind(group, :selected_person)
|
1335
|
+
}
|
1336
|
+
}
|
1337
|
+
```
|
1338
|
+
|
1339
|
+
The code above includes two data-bindings:
|
1340
|
+
- Table `items`, which first bind to the model collection property (group.people), and then maps each column property (name, age, adult) for displaying each table item column.
|
1341
|
+
- Table `selection`, which binds the single table item selected by the user to the attribute denoted by the `bind` keyword (or binds multiple table items selected for a table with `:multi` SWT style)
|
1342
|
+
|
1343
|
+
Additionally, Table `items` data-binding automatically stores each node model unto the SWT TableItem object via `setData` method. This enables things like searchability.
|
1344
|
+
|
1345
|
+
The table widget in Glimmer is represented by a subclass of `WidgetProxy` called `TableProxy`.
|
1346
|
+
TableProxy includes a `search` method that takes a block to look for a table item.
|
1347
|
+
|
1348
|
+
Example:
|
1349
|
+
|
1350
|
+
```ruby
|
1351
|
+
found_array = @table.search { |table_item| table_item.getData == company.owner }
|
1352
|
+
```
|
1353
|
+
|
1354
|
+
This finds a person. The array is a Java array. This enables easy passing of it to SWT `Table#setSelection` method, which expects a Java array of `TableItem` objects.
|
1355
|
+
|
1356
|
+
To edit a table, you must invoke `TableProxy#edit_selected_table_item(column_index, before_write: nil, after_write: nil, after_cancel: nil)` or `TableProxy#edit_table_item(table_item, column_index, before_write: nil, after_write: nil, after_cancel: nil)`.
|
1357
|
+
This automatically leverages the SWT TableEditor custom class behind the scenes, displaying a text widget to the user to change the selected or
|
1358
|
+
passed table item text into something else.
|
1359
|
+
It automatically persists the change to `items` data-bound model on ENTER/FOCUS-OUT or cancels on ESC/NO-CHANGE.
|
1274
1360
|
|
1275
1361
|
#### Tree
|
1276
1362
|
|
@@ -1486,7 +1572,9 @@ Glimmer supports creating custom widgets with minimal code, which automatically
|
|
1486
1572
|
|
1487
1573
|
Simply create a new class that includes `Glimmer::UI::CustomWidget` and put Glimmer DSL code in its `#body` block (its return value is stored in `#body_root` attribute). Glimmer will then automatically recognize this class by convention when it encounters a keyword matching the class name converted to underscored lowercase (and namespace double-colons `::` replaced with double-underscores `__`)
|
1488
1574
|
|
1489
|
-
#### Example
|
1575
|
+
#### Simple Example
|
1576
|
+
|
1577
|
+
(you may copy/paste in [`girb`](#girb-glimmer-irb-command))
|
1490
1578
|
|
1491
1579
|
Definition:
|
1492
1580
|
```ruby
|
@@ -1512,7 +1600,9 @@ shell {
|
|
1512
1600
|
|
1513
1601
|
As you can see, `RedLabel` became Glimmer DSL keyword: `red_label`
|
1514
1602
|
|
1515
|
-
####
|
1603
|
+
#### Hook Example
|
1604
|
+
|
1605
|
+
(you may copy/paste in [`girb`](#girb-glimmer-irb-command))
|
1516
1606
|
|
1517
1607
|
Definition:
|
1518
1608
|
```ruby
|
@@ -1561,7 +1651,9 @@ Additionally, custom widgets can call the following class methods:
|
|
1561
1651
|
- `::options(*option_names)`: declares a list of options by taking an option name array (symbols/strings). This generates option attribute accessors (e.g. `options :orientation, :bg_color` generates `#orientation`, `#orientation=(v)`, `#bg_color`, and `#bg_color=(v)` attribute accessors)
|
1562
1652
|
- `::option(option_name, default: nil)`: declares a single option taking option name and default value as arguments (also generates attribute accessors just like `::options`)
|
1563
1653
|
|
1564
|
-
#### Content/Options Example
|
1654
|
+
#### Content/Options Example
|
1655
|
+
|
1656
|
+
(you may copy/paste in [`girb`](#girb-glimmer-irb-command))
|
1565
1657
|
|
1566
1658
|
Definition:
|
1567
1659
|
```ruby
|
@@ -2007,15 +2099,15 @@ glimmer samples/elaborate/tic_tac_toe.rb # demonstrates a full MVC application
|
|
2007
2099
|
|
2008
2100
|
### External Samples
|
2009
2101
|
|
2010
|
-
####
|
2102
|
+
#### Glimmer Calculator
|
2011
2103
|
|
2012
|
-
|
2104
|
+
[<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer-cs-calculator/v1.0.0/glimmer-cs-calculator-screenshot.png" />](https://github.com/AndyObtiva/glimmer-cs-calculator)
|
2013
2105
|
|
2014
2106
|
[Glimmer Calculator](https://github.com/AndyObtiva/glimmer-cs-calculator) is a basic calculator sample project demonstrating data-binding and TDD (test-driven-development) with Glimmer following the MVP pattern (Model-View-Presenter).
|
2015
2107
|
|
2016
|
-
####
|
2108
|
+
#### Gladiator
|
2017
2109
|
|
2018
|
-
|
2110
|
+
[<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer-cs-gladiator/v0.1.5/images/glimmer-gladiator.png" />](https://github.com/AndyObtiva/glimmer-cs-gladiator)
|
2019
2111
|
|
2020
2112
|
[Gladiator](https://github.com/AndyObtiva/glimmer-cs-gladiator) (short for Glimmer Editor) is a Glimmer sample project under on-going development.
|
2021
2113
|
You may check it out to learn how to build a Glimmer Custom Shell gem.
|
@@ -2200,6 +2292,8 @@ The Glimmer rake task allows passing extra options to javapackager via:
|
|
2200
2292
|
Example (Rakefile):
|
2201
2293
|
|
2202
2294
|
```ruby
|
2295
|
+
require 'glimmer/rake_task'
|
2296
|
+
|
2203
2297
|
Glimmer::Package.javapackager_extra_args = '-BlicenseType="MIT" -Bmac.category="public.app-category.business" -Bmac.signing-key-developer-id-app="Andy Maleh"'
|
2204
2298
|
```
|
2205
2299
|
|
@@ -2283,10 +2377,11 @@ Exec failed with code 2 command [[/usr/bin/SetFile, -c, icnC, /var/folders/4_/g1
|
|
2283
2377
|
## Resources
|
2284
2378
|
|
2285
2379
|
* [Code Master Blog](http://andymaleh.blogspot.com/search/label/Glimmer)
|
2286
|
-
* [Eclipse Zone Tutorial](http://eclipse.dzone.com/articles/an-introduction-glimmer)
|
2287
|
-
* [InfoQ Article](http://www.infoq.com/news/2008/02/glimmer-jruby-swt)
|
2288
|
-
* [RubyConf 2008 Video](https://confreaks.tv/videos/rubyconf2008-desktop-development-with-glimmer)
|
2289
2380
|
* [JRuby Cookbook by Justin Edelson & Henry Liu](http://shop.oreilly.com/product/9780596519650.do)
|
2381
|
+
* [MountainWest RubyConf 2011 Video](https://confreaks.tv/videos/mwrc2011-whatever-happened-to-desktop-development-in-ruby)
|
2382
|
+
* [RubyConf 2008 Video](https://confreaks.tv/videos/rubyconf2008-desktop-development-with-glimmer)
|
2383
|
+
* [InfoQ Article](http://www.infoq.com/news/2008/02/glimmer-jruby-swt)
|
2384
|
+
* [DZone Tutorial](https://dzone.com/articles/an-introduction-glimmer)
|
2290
2385
|
|
2291
2386
|
## Help
|
2292
2387
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.8.
|
1
|
+
0.8.2
|
@@ -16,6 +16,11 @@ module Glimmer
|
|
16
16
|
@table = parent
|
17
17
|
@model_binding = model_binding
|
18
18
|
@column_properties = column_properties
|
19
|
+
if @table.respond_to?(:column_properties=)
|
20
|
+
@table.column_properties = @column_properties
|
21
|
+
else # assume custom widget
|
22
|
+
@table.body_root.column_properties = @column_properties
|
23
|
+
end
|
19
24
|
call(@model_binding.evaluate_property)
|
20
25
|
model = model_binding.base_model
|
21
26
|
observe(model, model_binding.property_name_expression)
|
@@ -24,23 +29,27 @@ module Glimmer
|
|
24
29
|
end
|
25
30
|
end
|
26
31
|
|
27
|
-
def call(
|
28
|
-
if
|
29
|
-
|
30
|
-
|
31
|
-
@model_collection = model_collection
|
32
|
+
def call(new_model_collection=nil)
|
33
|
+
if new_model_collection and new_model_collection.is_a?(Array)
|
34
|
+
observe(new_model_collection, @column_properties)
|
35
|
+
@model_collection = new_model_collection
|
32
36
|
end
|
33
37
|
populate_table(@model_collection, @table, @column_properties)
|
34
38
|
end
|
35
39
|
|
36
40
|
def populate_table(model_collection, parent, column_properties)
|
41
|
+
selected_table_item_models = parent.swt_widget.getSelection.map(&:getData)
|
37
42
|
parent.swt_widget.removeAll
|
38
43
|
model_collection.each do |model|
|
39
44
|
table_item = TableItem.new(parent.swt_widget, SWT::SWTProxy[:none])
|
40
45
|
for index in 0..(column_properties.size-1)
|
41
46
|
table_item.setText(index, model.send(column_properties[index]).to_s)
|
42
47
|
end
|
48
|
+
table_item.setData(model)
|
43
49
|
end
|
50
|
+
selected_table_items = parent.search {|item| selected_table_item_models.include?(item.getData) }
|
51
|
+
selected_table_items = [parent.swt_widget.getItems.first].to_java(TableItem) if selected_table_items.empty? && !parent.swt_widget.getItems.empty?
|
52
|
+
parent.swt_widget.setSelection(selected_table_items) unless selected_table_items.empty?
|
44
53
|
end
|
45
54
|
end
|
46
55
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'glimmer/dsl/static_expression'
|
2
|
+
require 'glimmer/dsl/parent_expression'
|
3
|
+
require 'glimmer/dsl/top_level_expression'
|
4
|
+
require 'glimmer/swt/shell_proxy'
|
5
|
+
require 'glimmer/swt/message_box_proxy'
|
6
|
+
require 'glimmer/swt/swt_proxy'
|
7
|
+
|
8
|
+
module Glimmer
|
9
|
+
module DSL
|
10
|
+
module SWT
|
11
|
+
class MessageBoxExpression < StaticExpression
|
12
|
+
include TopLevelExpression
|
13
|
+
include ParentExpression
|
14
|
+
|
15
|
+
include_package 'org.eclipse.swt.widgets'
|
16
|
+
|
17
|
+
def can_interpret?(parent, keyword, *args, &block)
|
18
|
+
keyword == 'message_box'
|
19
|
+
end
|
20
|
+
|
21
|
+
def interpret(parent, keyword, *args, &block)
|
22
|
+
potential_parent = args.first
|
23
|
+
parent = args.shift if potential_parent.is_a?(Shell) || (potential_parent.respond_to?(:swt_widget) && potential_parent.swt_widget.is_a?(Shell))
|
24
|
+
Glimmer::SWT::MessageBoxProxy.new(parent, Glimmer::SWT::SWTProxy[args])
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/glimmer/package.rb
CHANGED
@@ -2,6 +2,54 @@ module Glimmer
|
|
2
2
|
module Package
|
3
3
|
class << self
|
4
4
|
attr_accessor :javapackager_extra_args
|
5
|
+
|
6
|
+
def config
|
7
|
+
project_name = File.basename(File.expand_path('.'))
|
8
|
+
if !File.exists?('config/warble.rb')
|
9
|
+
puts 'Generating JAR configuration (config/warble.rb) to use with Warbler...'
|
10
|
+
system('mkdir -p config')
|
11
|
+
system('warble config')
|
12
|
+
new_config = File.read('config/warble.rb').split("\n").inject('') do |output, line|
|
13
|
+
if line.include?('config.dirs =')
|
14
|
+
line = line.sub('# ', '').sub(/=[^=\n]+$/, '= %w(app config db lib script bin docs fonts icons images sounds videos)')
|
15
|
+
end
|
16
|
+
if line.include?('config.includes =')
|
17
|
+
line = line.sub('# ', '').sub(/=[^=\n]+$/, "= FileList['LICENSE.txt', 'VERSION']")
|
18
|
+
end
|
19
|
+
if line.include?('config.autodeploy_dir =')
|
20
|
+
line = line.sub('# ', '')
|
21
|
+
end
|
22
|
+
output + "\n" + line
|
23
|
+
end
|
24
|
+
File.write('config/warble.rb', new_config)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def jar
|
29
|
+
system('mkdir -p dist')
|
30
|
+
puts "Generating JAR with Warbler..."
|
31
|
+
system('warble')
|
32
|
+
end
|
33
|
+
|
34
|
+
def native
|
35
|
+
require 'facets/string/titlecase'
|
36
|
+
require 'facets/string/underscore'
|
37
|
+
project_name = File.basename(File.expand_path('.'))
|
38
|
+
version_file = File.expand_path('./VERSION')
|
39
|
+
version = (File.read(version_file).strip if File.exists?(version_file) && File.file?(version_file)) rescue nil
|
40
|
+
license_file = File.expand_path('./LICENSE.txt')
|
41
|
+
license = (File.read(license_file).strip if File.exists?(license_file) && File.file?(license_file)) rescue nil
|
42
|
+
human_name = project_name.underscore.titlecase
|
43
|
+
command = "javapackager -deploy -native -outdir packages -outfile \"#{project_name}\" -srcfiles \"dist/#{project_name}.jar\" -appclass JarMain -name \"#{human_name}\" -title \"#{human_name}\" -Bmac.CFBundleName=\"#{human_name}\" -Bmac.CFBundleIdentifier=\"org.#{project_name}.application.#{project_name}\" -Bmac.category=\"public.app-category.business\" "
|
44
|
+
command += " -BjvmOptions=-XstartOnFirstThread " if OS.mac?
|
45
|
+
command += " -BappVersion=#{version} -Bmac.CFBundleVersion=#{version} " if version
|
46
|
+
command += " -srcfiles LICENSE.txt -BlicenseFile=LICENSE.txt " if license
|
47
|
+
command += " #{javapackager_extra_args} " if javapackager_extra_args
|
48
|
+
command += " #{ENV['JAVAPACKAGER_EXTRA_ARGS']} " if ENV['JAVAPACKAGER_EXTRA_ARGS']
|
49
|
+
puts "Generating DMG/PKG/APP/JNLP with javapackager..."
|
50
|
+
puts command
|
51
|
+
system command
|
52
|
+
end
|
5
53
|
end
|
6
54
|
end
|
7
55
|
end
|
data/lib/glimmer/rake_task.rb
CHANGED
@@ -7,57 +7,26 @@ namespace :glimmer do
|
|
7
7
|
namespace :package do
|
8
8
|
desc 'Generate JAR config file'
|
9
9
|
task :config do
|
10
|
-
|
11
|
-
if !File.exists?('config/warble.rb')
|
12
|
-
puts 'Generating JAR configuration (config/warble.rb) to use with Warbler...'
|
13
|
-
system('mkdir -p config')
|
14
|
-
system('warble config')
|
15
|
-
new_config = File.read('config/warble.rb').split("\n").inject('') do |output, line|
|
16
|
-
if line.include?('config.dirs =')
|
17
|
-
line = line.sub('# ', '').sub(/=[^=\n]+$/, '= %w(app config db lib script bin docs fonts icons images sounds videos)')
|
18
|
-
end
|
19
|
-
if line.include?('config.includes =')
|
20
|
-
line = line.sub('# ', '').sub(/=[^=\n]+$/, "= FileList['LICENSE.txt', 'VERSION']")
|
21
|
-
end
|
22
|
-
if line.include?('config.autodeploy_dir =')
|
23
|
-
line = line.sub('# ', '')
|
24
|
-
end
|
25
|
-
output + "\n" + line
|
26
|
-
end
|
27
|
-
File.write('config/warble.rb', new_config)
|
28
|
-
end
|
10
|
+
Glimmer::Package.config
|
29
11
|
end
|
30
12
|
|
31
13
|
desc 'Generate JAR file'
|
32
|
-
task :jar
|
33
|
-
|
34
|
-
puts "Generating JAR with Warbler..."
|
35
|
-
system('warble')
|
14
|
+
task :jar do
|
15
|
+
Glimmer::Package.jar
|
36
16
|
end
|
37
17
|
|
38
|
-
desc 'Generate Native files (DMG/PKG/APP on the Mac)'
|
39
|
-
task :native
|
40
|
-
|
41
|
-
require 'facets/string/underscore'
|
42
|
-
project_name = File.basename(File.expand_path('.'))
|
43
|
-
version_file = File.expand_path('./VERSION')
|
44
|
-
version = (File.read(version_file).strip if File.exists?(version_file) && File.file?(version_file)) rescue nil
|
45
|
-
license_file = File.expand_path('./LICENSE.txt')
|
46
|
-
license = (File.read(license_file).strip if File.exists?(license_file) && File.file?(license_file)) rescue nil
|
47
|
-
human_name = project_name.underscore.titlecase
|
48
|
-
command = "javapackager -deploy -native -outdir packages -outfile \"#{project_name}\" -srcfiles \"dist/#{project_name}.jar\" -appclass JarMain -name \"#{human_name}\" -title \"#{human_name}\" -BjvmOptions=-XstartOnFirstThread -Bmac.CFBundleName=\"#{human_name}\" -Bmac.CFBundleIdentifier=\"org.#{project_name}.application.#{project_name}\" -Bmac.category=\"public.app-category.business\" "
|
49
|
-
command += " -BappVersion=#{version} -Bmac.CFBundleVersion=#{version} " if version
|
50
|
-
command += " -srcfiles LICENSE.txt -BlicenseFile=LICENSE.txt " if license
|
51
|
-
command += " #{Glimmer::Package.javapackager_extra_args} " if Glimmer::Package.javapackager_extra_args
|
52
|
-
command += " #{ENV['JAVAPACKAGER_EXTRA_ARGS']} " if ENV['JAVAPACKAGER_EXTRA_ARGS']
|
53
|
-
puts "Generating DMG/PKG/APP/JNLP with javapackager..."
|
54
|
-
puts command
|
55
|
-
system command
|
18
|
+
desc 'Generate Native files (DMG/PKG/APP on the Mac, EXE on Windows, RPM/DEB on Linux)'
|
19
|
+
task :native do
|
20
|
+
Glimmer::Package.native
|
56
21
|
end
|
57
22
|
end
|
58
23
|
|
59
24
|
desc 'Package app for distribution (generating config, jar, and native files)'
|
60
|
-
task :package
|
25
|
+
task :package do
|
26
|
+
Rake::Task['glimmer:package:config'].execute
|
27
|
+
Rake::Task['glimmer:package:jar'].execute
|
28
|
+
Rake::Task['glimmer:package:native'].execute
|
29
|
+
end
|
61
30
|
|
62
31
|
|
63
32
|
desc 'Scaffold a Glimmer application directory structure to begin building a new app'
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'glimmer/swt/swt_proxy'
|
2
|
+
require 'glimmer/swt/widget_proxy'
|
3
|
+
require 'glimmer/swt/display_proxy'
|
4
|
+
require 'glimmer/swt/shell_proxy'
|
5
|
+
|
6
|
+
module Glimmer
|
7
|
+
module SWT
|
8
|
+
# Proxy for org.eclipse.swt.widgets.Shell
|
9
|
+
#
|
10
|
+
# Follows the Proxy Design Pattern
|
11
|
+
class MessageBoxProxy
|
12
|
+
include_package 'org.eclipse.swt.widgets'
|
13
|
+
|
14
|
+
attr_reader :swt_widget
|
15
|
+
|
16
|
+
def initialize(parent, style)
|
17
|
+
parent = parent.swt_widget if parent.respond_to?(:swt_widget) && parent.swt_widget.is_a?(Shell)
|
18
|
+
@swt_widget = MessageBox.new(parent, style)
|
19
|
+
end
|
20
|
+
|
21
|
+
def open
|
22
|
+
@swt_widget.open
|
23
|
+
end
|
24
|
+
|
25
|
+
# TODO refactor the following methods to put in a JavaBean mixin or somethin (perhaps contribute to OSS project too)
|
26
|
+
|
27
|
+
def attribute_setter(attribute_name)
|
28
|
+
"set#{attribute_name.to_s.camelcase(:upper)}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def attribute_getter(attribute_name)
|
32
|
+
"get#{attribute_name.to_s.camelcase(:upper)}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def has_attribute?(attribute_name, *args)
|
36
|
+
@swt_widget.respond_to?(attribute_setter(attribute_name), args)
|
37
|
+
end
|
38
|
+
|
39
|
+
def set_attribute(attribute_name, *args)
|
40
|
+
@swt_widget.send(attribute_setter(attribute_name), *args) unless @swt_widget.send(attribute_getter(attribute_name)) == args.first
|
41
|
+
end
|
42
|
+
|
43
|
+
def get_attribute(attribute_name)
|
44
|
+
@swt_widget.send(attribute_getter(attribute_name))
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -102,24 +102,19 @@ module Glimmer
|
|
102
102
|
|
103
103
|
def pack_same_size
|
104
104
|
bounds = @swt_widget.getBounds
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
if OS.windows?
|
105
|
+
if OS.mac?
|
106
|
+
@swt_widget.pack
|
107
|
+
@swt_widget.setBounds(bounds)
|
108
|
+
elsif OS.windows? || OS::Underlying.windows?
|
110
109
|
minimum_size = @swt_widget.getMinimumSize
|
111
110
|
@swt_widget.setMinimumSize(bounds.width, bounds.height)
|
112
|
-
listener = on_control_resized {
|
113
|
-
@swt_widget.setSize(bounds.width, bounds.height)
|
114
|
-
@swt_widget.setLocation(bounds.x, bounds.y)
|
115
|
-
}
|
111
|
+
listener = on_control_resized { @swt_widget.setBounds(bounds) }
|
116
112
|
@swt_widget.pack
|
117
113
|
@swt_widget.removeControlListener(listener.swt_listener)
|
118
114
|
@swt_widget.setMinimumSize(minimum_size)
|
119
|
-
|
120
|
-
@swt_widget.
|
121
|
-
@swt_widget.
|
122
|
-
@swt_widget.setLocation(x, y)
|
115
|
+
elsif OS.linux?
|
116
|
+
@swt_widget.layout(true, true)
|
117
|
+
@swt_widget.setBounds(bounds)
|
123
118
|
end
|
124
119
|
end
|
125
120
|
|
@@ -0,0 +1,150 @@
|
|
1
|
+
require 'glimmer/swt/widget_proxy'
|
2
|
+
|
3
|
+
module Glimmer
|
4
|
+
module SWT
|
5
|
+
class TableProxy < Glimmer::SWT::WidgetProxy
|
6
|
+
include Glimmer
|
7
|
+
|
8
|
+
module TableListenerEvent
|
9
|
+
def table_item
|
10
|
+
table_item_and_column_index[:table_item]
|
11
|
+
end
|
12
|
+
|
13
|
+
def column_index
|
14
|
+
table_item_and_column_index[:column_index]
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def table_item_and_column_index
|
20
|
+
@table_item_and_column_index ||= find_table_item_and_column_index
|
21
|
+
end
|
22
|
+
|
23
|
+
def find_table_item_and_column_index
|
24
|
+
{}.tap do |result|
|
25
|
+
if respond_to?(:x) && respond_to?(:y)
|
26
|
+
result[:table_item] = widget.getItems.detect do |ti|
|
27
|
+
result[:column_index] = widget.getColumnCount.times.to_a.detect do |ci|
|
28
|
+
ti.getBounds(ci).contains(x, y)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
attr_reader :table_editor, :table_editor_text_proxy
|
37
|
+
attr_accessor :column_properties
|
38
|
+
|
39
|
+
def initialize(underscored_widget_name, parent, args)
|
40
|
+
super
|
41
|
+
@table_editor = TableEditor.new(swt_widget)
|
42
|
+
@table_editor.horizontalAlignment = SWTProxy[:left]
|
43
|
+
@table_editor.grabHorizontal = true
|
44
|
+
@table_editor.minimumHeight = 20
|
45
|
+
end
|
46
|
+
|
47
|
+
# Performs a search for table items matching block condition
|
48
|
+
# If no condition block is passed, returns all table items
|
49
|
+
# Returns a Java TableItem array to easily set as selection on org.eclipse.swt.Table if needed
|
50
|
+
def search(&condition)
|
51
|
+
swt_widget.getItems.select {|item| condition.nil? || condition.call(item)}.to_java(TableItem)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Returns all table items including descendants
|
55
|
+
def all_table_items
|
56
|
+
search
|
57
|
+
end
|
58
|
+
|
59
|
+
def widget_property_listener_installers
|
60
|
+
super.merge({
|
61
|
+
Java::OrgEclipseSwtWidgets::Table => {
|
62
|
+
selection: lambda do |observer|
|
63
|
+
on_widget_selected { |selection_event|
|
64
|
+
observer.call(@swt_widget.getSelection)
|
65
|
+
}
|
66
|
+
end
|
67
|
+
},
|
68
|
+
})
|
69
|
+
end
|
70
|
+
|
71
|
+
def edit_in_progress?
|
72
|
+
!!@edit_in_progress
|
73
|
+
end
|
74
|
+
|
75
|
+
def edit_selected_table_item(column_index, before_write: nil, after_write: nil, after_cancel: nil)
|
76
|
+
edit_table_item(swt_widget.getSelection.first, column_index, before_write: before_write, after_write: after_write, after_cancel: after_cancel)
|
77
|
+
end
|
78
|
+
|
79
|
+
def edit_table_item(table_item, column_index, before_write: nil, after_write: nil, after_cancel: nil)
|
80
|
+
return if table_item.nil?
|
81
|
+
content {
|
82
|
+
@table_editor_text_proxy = text {
|
83
|
+
focus true
|
84
|
+
text table_item.getText(column_index)
|
85
|
+
action_taken = false
|
86
|
+
cancel = lambda {
|
87
|
+
@table_editor_text_proxy.swt_widget.dispose
|
88
|
+
@table_editor_text_proxy = nil
|
89
|
+
after_cancel&.call
|
90
|
+
@edit_in_progress = false
|
91
|
+
}
|
92
|
+
action = lambda { |event|
|
93
|
+
if !action_taken && !@edit_in_progress
|
94
|
+
action_taken = true
|
95
|
+
@edit_in_progress = true
|
96
|
+
new_text = @table_editor_text_proxy.swt_widget.getText
|
97
|
+
if new_text == table_item.getText(column_index)
|
98
|
+
cancel.call
|
99
|
+
else
|
100
|
+
before_write&.call
|
101
|
+
table_item.setText(column_index, new_text)
|
102
|
+
model = table_item.getData
|
103
|
+
model.send("#{column_properties[column_index]}=", new_text) # makes table update itself, so must search for selected table item again
|
104
|
+
edited_table_item = search { |ti| ti.getData == model }.first
|
105
|
+
swt_widget.showItem(edited_table_item)
|
106
|
+
@table_editor_text_proxy.swt_widget.dispose
|
107
|
+
@table_editor_text_proxy = nil
|
108
|
+
after_write&.call(edited_table_item)
|
109
|
+
@edit_in_progress = false
|
110
|
+
end
|
111
|
+
end
|
112
|
+
}
|
113
|
+
on_focus_lost(&action)
|
114
|
+
on_key_pressed { |key_event|
|
115
|
+
if key_event.keyCode == swt(:cr)
|
116
|
+
action.call(key_event)
|
117
|
+
elsif key_event.keyCode == swt(:esc)
|
118
|
+
cancel.call
|
119
|
+
end
|
120
|
+
}
|
121
|
+
}
|
122
|
+
@table_editor_text_proxy.swt_widget.selectAll
|
123
|
+
}
|
124
|
+
@table_editor.setEditor(@table_editor_text_proxy.swt_widget, table_item, column_index)
|
125
|
+
end
|
126
|
+
|
127
|
+
def add_listener(underscored_listener_name, &block)
|
128
|
+
enhanced_block = lambda do |event|
|
129
|
+
event.extend(TableListenerEvent)
|
130
|
+
block.call(event)
|
131
|
+
end
|
132
|
+
super(underscored_listener_name, &enhanced_block)
|
133
|
+
end
|
134
|
+
|
135
|
+
private
|
136
|
+
|
137
|
+
def property_type_converters
|
138
|
+
super.merge({
|
139
|
+
selection: lambda do |value|
|
140
|
+
if value.is_a?(Array)
|
141
|
+
search {|ti| value.include?(ti.getData) }
|
142
|
+
else
|
143
|
+
search {|ti| ti.getData == value}
|
144
|
+
end
|
145
|
+
end,
|
146
|
+
})
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
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.8.
|
4
|
+
version: 0.8.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- AndyMaleh
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-06-
|
11
|
+
date: 2020-06-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -164,7 +164,10 @@ dependencies:
|
|
164
164
|
- - "~>"
|
165
165
|
- !ruby/object:Gem::Version
|
166
166
|
version: 0.8.1
|
167
|
-
description: Ruby Desktop Development GUI Library
|
167
|
+
description: "Ruby Desktop Development GUI Library (JRuby on SWT). \n\nChanges: \n\
|
168
|
+
- `message_box` DSL keyword\n- Table single/multi selection databinding\n- Table\
|
169
|
+
\ cell editing databinding\n- Enhance table listener events with table_item and\
|
170
|
+
\ column_index methods\n- Fix `Glimmer::SWT::ShellProxy#pack_same_size` for Linux\n"
|
168
171
|
email: andy.am@gmail.com
|
169
172
|
executables:
|
170
173
|
- glimmer
|
@@ -225,6 +228,7 @@ files:
|
|
225
228
|
- lib/glimmer/dsl/swt/list_selection_data_binding_expression.rb
|
226
229
|
- lib/glimmer/dsl/swt/menu_bar_expression.rb
|
227
230
|
- lib/glimmer/dsl/swt/menu_expression.rb
|
231
|
+
- lib/glimmer/dsl/swt/message_box_expression.rb
|
228
232
|
- lib/glimmer/dsl/swt/observe_expression.rb
|
229
233
|
- lib/glimmer/dsl/swt/property_expression.rb
|
230
234
|
- lib/glimmer/dsl/swt/rgb_expression.rb
|
@@ -259,10 +263,12 @@ files:
|
|
259
263
|
- lib/glimmer/swt/layout_data_proxy.rb
|
260
264
|
- lib/glimmer/swt/layout_proxy.rb
|
261
265
|
- lib/glimmer/swt/menu_proxy.rb
|
266
|
+
- lib/glimmer/swt/message_box_proxy.rb
|
262
267
|
- lib/glimmer/swt/packages.rb
|
263
268
|
- lib/glimmer/swt/shell_proxy.rb
|
264
269
|
- lib/glimmer/swt/swt_proxy.rb
|
265
270
|
- lib/glimmer/swt/tab_item_proxy.rb
|
271
|
+
- lib/glimmer/swt/table_proxy.rb
|
266
272
|
- lib/glimmer/swt/tree_proxy.rb
|
267
273
|
- lib/glimmer/swt/widget_listener_proxy.rb
|
268
274
|
- lib/glimmer/swt/widget_proxy.rb
|