glimmer 0.8.1 → 0.8.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![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
|
-
[![Test Coverage](https://api.codeclimate.com/v1/badges/38fbc278022862794414/test_coverage)](https://codeclimate.com/github/AndyObtiva/glimmer/test_coverage)
|
5
4
|
[![Maintainability](https://api.codeclimate.com/v1/badges/38fbc278022862794414/maintainability)](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
|
![Tic Tac Toe](images/glimmer-tic-tac-toe.png)
|
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
|