glimmer 0.9.2 → 0.10.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2d387850f085c102bcaf51d9f9f1250cf02124372beed08612bc2dde2766f387
4
- data.tar.gz: 828032e8a3d6779e47d63c054cf15211ec8b989a58af47ba1aedfed36e696b67
3
+ metadata.gz: 4e5e05e1e5ce6544e9c0286a46f5436c82ff92e8659044b31794d3f4d9db40f2
4
+ data.tar.gz: 3ad9c659f81fed05328533f1af05713939d44297693af78d78799006009cad71
5
5
  SHA512:
6
- metadata.gz: 5e7d349b48f19af94bab354eceef736e6c58e9d4e608582fb12c1677c453dfff5ee02c74a968133e985239a18f0058f66b35a4199fc4c3ac63b29cb0d80a7f91
7
- data.tar.gz: 2d4f7f4600517ca0f6e9f08946b37f7aaff9740dc3f49b1844147d6635cd4cce053af200e1c58c0a5eac8523d4cce2f9601ead454665049919954498d697c32e
6
+ metadata.gz: 674f6f7ea6cf2908261b83ce3580b770bb39ac47c1069c2b26651c897d109863516349d7b09d94199c928b2efceb19719d41123453caa7fde187127bb0c3b16a
7
+ data.tar.gz: c5d22e44fa047b35f5aadb232f446cc074873dbb4b8638b2f83038208ae0e32535e0668cd19419994d76d1aac95e7a917b711cc8853d589ac3757e9ca90e350c
data/README.md CHANGED
@@ -1,9 +1,14 @@
1
- # <img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=105 /> Glimmer - Ruby Desktop Development GUI Library
1
+ # <img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 style="position: relative; top: 20px;" /> Glimmer (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
+ [![Coverage Status](https://coveralls.io/repos/github/AndyObtiva/glimmer/badge.svg?branch=master)](https://coveralls.io/github/AndyObtiva/glimmer?branch=master)
4
5
  [![Join the chat at https://gitter.im/AndyObtiva/glimmer](https://badges.gitter.im/AndyObtiva/glimmer.svg)](https://gitter.im/AndyObtiva/glimmer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
5
6
 
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.
7
+ **[Contributors Wanted! (Submit a Glimmer App Sample to Get Started)](#contributing)**
8
+
9
+ (The Original Glimmer Library Since 2007. Beware of Imitators!)
10
+
11
+ [**Glimmer**](https://rubygems.org/gems/glimmer) is a native-GUI cross-platform desktop development library written in [JRuby](https://www.jruby.org/), a highly portable faster version of [Ruby](https://www.ruby-lang.org/en/). [**Glimmer**](https://rubygems.org/gems/glimmer)'s main innovation is a declarative [Ruby DSL](#glimmer-dsl-syntax) that enables productive and efficient authoring of desktop application user-interfaces while relying on the robust [Eclipse SWT library](https://www.eclipse.org/swt/). [**Glimmer**](https://rubygems.org/gems/glimmer) additionally innovates by having built-in [data-binding](#data-binding) support, which greatly facilitates synchronizing the GUI with domain models. This 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. To get started quickly, [Glimmer](https://rubygems.org/gems/glimmer) offers [scaffolding](#scaffolding) options for [Apps](#in-production), [Gems](#custom-shell-gem), and [Custom Widgets](#custom-widgets). Last but not least, [Glimmer](https://rubygems.org/gems/glimmer) includes native-executable [packaging](#packaging--distribution) support, sorely lacking in competing libraries, thus enabling delivery of desktop apps written in [Ruby](https://www.ruby-lang.org/en/) as truly native DMG/PKG/APP files on the [Mac](https://www.apple.com/ca/macos) + [App Store](https://developer.apple.com/macos/distribution/) and MSI/EXE files on [Windows](https://www.microsoft.com/en-ca/windows). Given that [JRuby](https://www.jruby.org/) runs on the [JVM](https://java.com/en/download/faq/whatis_java.xml) (Java Virtual Machine), unlike competing libraries like TK, it does not require recompilation of [Ruby](https://www.ruby-lang.org/en/) to use native GUI libraries on every platform. [Glimmer](https://rubygems.org/gems/glimmer) runs native GUI out of the box on every platform thanks to the [JVM](https://java.com/en/download/faq/whatis_java.xml) and [Eclipse SWT library](https://www.eclipse.org/swt/).
7
12
 
8
13
  [<img src="https://covers.oreillystatic.com/images/9780596519650/lrg.jpg" width=105 /><br />
9
14
  Featured in<br />JRuby Cookbook](http://shop.oreilly.com/product/9780596519650.do)
@@ -12,13 +17,13 @@ Glimmer DSL gems:
12
17
  - [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt): Glimmer DSL for SWT (Desktop GUI)
13
18
  - [glimmer-dsl-opal](https://github.com/AndyObtiva/glimmer-dsl-opal): Glimmer DSL for Opal (Web GUI Adapter for Desktop Apps)
14
19
  - [glimmer-dsl-xml](https://github.com/AndyObtiva/glimmer-dsl-xml): Glimmer DSL for XML (& HTML)
15
- - [glimmer-dsl-css](https://github.com/AndyObtiva/glimmer-dsl-css): Glimmer DSL for CSS (Cascading Style Sheets)
20
+ - [glimmer-dsl-css](https://github.com/AndyObtiva/glimmer-dsl-css): Glimmer DSL for CSS
16
21
 
17
22
  ## Examples
18
23
 
19
24
  ### Hello, World!
20
25
 
21
- Glimmer code (from `samples/hello/hello_world.rb`):
26
+ Glimmer code (from [samples/hello/hello_world.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/hello/hello_world.rb)):
22
27
  ```ruby
23
28
  include Glimmer
24
29
 
@@ -41,28 +46,28 @@ Glimmer app:
41
46
 
42
47
  ### Tic Tac Toe
43
48
 
44
- Glimmer code (from `samples/elaborate/tic_tac_toe.rb`):
49
+ Glimmer code (from [samples/elaborate/tic_tac_toe.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/elaborate/tic_tac_toe.rb)):
45
50
 
46
51
  ```ruby
47
52
  # ...
48
- shell {
49
- text "Tic-Tac-Toe"
50
- composite {
51
- grid_layout 3, true
52
- (1..3).each { |row|
53
- (1..3).each { |column|
54
- button {
55
- layout_data :fill, :fill, true, true
56
- text bind(@tic_tac_toe_board[row, column], :sign)
57
- enabled bind(@tic_tac_toe_board[row, column], :empty)
58
- on_widget_selected {
59
- @tic_tac_toe_board.mark(row, column)
53
+ @shell = shell {
54
+ text "Tic-Tac-Toe"
55
+ composite {
56
+ grid_layout 3, true
57
+ (1..3).each { |row|
58
+ (1..3).each { |column|
59
+ button {
60
+ layout_data :fill, :fill, true, true
61
+ text bind(@tic_tac_toe_board[row, column], :sign)
62
+ enabled bind(@tic_tac_toe_board[row, column], :empty)
63
+ on_widget_selected {
64
+ @tic_tac_toe_board.mark(row, column)
65
+ }
66
+ }
60
67
  }
61
68
  }
62
69
  }
63
70
  }
64
- }
65
- }
66
71
  # ...
67
72
  ```
68
73
 
@@ -74,15 +79,103 @@ glimmer samples/elaborate/tic_tac_toe.rb
74
79
 
75
80
  Glimmer app:
76
81
 
77
- ![Tic Tac Toe](images/glimmer-tic-tac-toe.png)
82
+ ![Tic Tac Toe](images/glimmer-tic-tac-toe-in-progress.png)
78
83
 
79
- NOTE: Glimmer is in beta mode. Please help make better by [contributing](#contributing), adopting for small or low risk projects, and providing feedback.
84
+ ### Contact Manager
80
85
 
81
- 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.
86
+ Glimmer code (from [samples/elaborate/contact_manager.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/elaborate/contact_manager.rb)):
87
+
88
+ ```ruby
89
+ # ...
90
+ shell {
91
+ text "Contact Manager"
92
+ composite {
93
+ composite {
94
+ grid_layout 2, false
95
+ label {text "First &Name: "}
96
+ text {
97
+ text bind(@contact_manager_presenter, :first_name)
98
+ on_key_pressed {|key_event|
99
+ @contact_manager_presenter.find if key_event.keyCode == swt(:cr)
100
+ }
101
+ }
102
+ label {text "&Last Name: "}
103
+ text {
104
+ text bind(@contact_manager_presenter, :last_name)
105
+ on_key_pressed {|key_event|
106
+ @contact_manager_presenter.find if key_event.keyCode == swt(:cr)
107
+ }
108
+ }
109
+ label {text "&Email: "}
110
+ text {
111
+ text bind(@contact_manager_presenter, :email)
112
+ on_key_pressed {|key_event|
113
+ @contact_manager_presenter.find if key_event.keyCode == swt(:cr)
114
+ }
115
+ }
116
+ composite {
117
+ grid_layout 2, false
118
+ button {
119
+ text "&Find"
120
+ on_widget_selected {
121
+ @contact_manager_presenter.find
122
+ }
123
+ }
124
+ button {
125
+ text "&List All"
126
+ on_widget_selected {
127
+ @contact_manager_presenter.list
128
+ }
129
+ }
130
+ }
131
+ }
132
+
133
+ table(:multi) { |table_proxy|
134
+ layout_data {
135
+ horizontal_alignment :fill
136
+ vertical_alignment :fill
137
+ grab_excess_horizontal_space true
138
+ grab_excess_vertical_space true
139
+ height_hint 200
140
+ }
141
+ table_column {
142
+ text "First Name"
143
+ width 80
144
+ }
145
+ table_column {
146
+ text "Last Name"
147
+ width 80
148
+ }
149
+ table_column {
150
+ text "Email"
151
+ width 200
152
+ }
153
+ items bind(@contact_manager_presenter, :results),
154
+ column_properties(:first_name, :last_name, :email)
155
+ on_mouse_up { |event|
156
+ table_proxy.edit_table_item(event.table_item, event.column_index)
157
+ }
158
+ }
159
+ }
160
+ }.open
161
+ # ...
162
+ ```
163
+
164
+ Run:
165
+
166
+ ```
167
+ glimmer samples/elaborate/contact_manager.rb
168
+ ```
169
+
170
+ Glimmer App:
171
+
172
+ ![Contact Manager](images/glimmer-contact-manager.png)
173
+
174
+ NOTE: Glimmer is in beta mode. Please help make better by [contributing](#contributing), adopting for small or low risk projects, and providing feedback.
82
175
 
83
176
  ## Table of contents
84
177
 
85
- - [Glimmer - Ruby Desktop Development GUI Library](#glimmer---ruby-desktop-development-gui-library)
178
+ - [Glimmer (Ruby Desktop Development GUI Library)](#-glimmer-ruby-desktop-development-gui-library)
86
179
  - [Examples](#examples)
87
180
  - [Hello, World!](#hello-world)
88
181
  - [Tic Tac Toe](#tic-tac-toe)
@@ -101,6 +194,13 @@ Ruby is a dynamically-typed object-oriented language, which provides great produ
101
194
  - [Custom Widget](#custom-widget)
102
195
  - [Custom Shell Gem](#custom-shell-gem)
103
196
  - [Custom Widget Gem](#custom-widget-gem)
197
+ - [Gem Listing](#gem-listing)
198
+ - [Listing Custom Shell Gems](#listing-custom-shell-gems)
199
+ - [Listing Custom Widget Gems](#listing-custom-widget-gems)
200
+ - [Listing DSL Gems](#listing-dsl-gems)
201
+ - [Packaging](#packaging)
202
+ - [Raw JRuby Command](#raw-jruby-command)
203
+ - [Mac Support](#mac-support)
104
204
  - [Girb (Glimmer irb) Command](#girb-glimmer-irb-command)
105
205
  - [Glimmer DSL Syntax](#glimmer-dsl-syntax)
106
206
  - [Widgets](#widgets)
@@ -108,6 +208,7 @@ Ruby is a dynamically-typed object-oriented language, which provides great produ
108
208
  - [SWT Proxies](#swt-proxies)
109
209
  - [Dialog](#dialog)
110
210
  - [Menus](#menus)
211
+ - [ScrolledComposite](#scrolledcomposite)
111
212
  - [Widget Styles](#widget-styles)
112
213
  - [Explicit SWT Style Bit](#explicit-swt-style-bit)
113
214
  - [Negative SWT Style Bits](#negative-swt-style-bits)
@@ -128,29 +229,49 @@ Ruby is a dynamically-typed object-oriented language, which provides great produ
128
229
  - [Observing Models](#observing-models)
129
230
  - [Custom Widgets](#custom-widgets)
130
231
  - [Simple Example](#simple-example)
131
- - [Hook Example](#hook-example)
232
+ - [Lifecycle Hook Example](#lifecycle-hook-example)
233
+ - [Custom Widget API](#custom-widget-api)
132
234
  - [Content/Options Example](#contentoptions-example)
235
+ - [Custom Widget Lifecycle Hooks](#custom-widget-lifecycle-hooks)
133
236
  - [Gotcha](#gotcha)
237
+ - [Final Notes](#final-notes)
134
238
  - [Custom Shells](#custom-shells)
239
+ - [Drag and Drop](#drag-and-drop)
135
240
  - [Miscellaneous](#miscellaneous)
136
241
  - [Multi-DSL Support](#multi-dsl-support)
137
242
  - [Application Menu Items (About/Preferences)](#application-menu-items-aboutpreferences)
138
243
  - [App Name and Version](#app-name-and-version)
139
244
  - [Video Widget](#video-widget)
140
245
  - [Browser Widget](#browser-widget)
246
+ - [Glimmer Configuration](#glimmer-configuration)
247
+ - [logger](#logger)
248
+ - [import_swt_packages](#importswtpackages)
249
+ - [loop_max_count](#loopmaxcount)
141
250
  - [Glimmer Style Guide](#glimmer-style-guide)
251
+ - [SWT Reference](#swt-reference)
142
252
  - [Samples](#samples)
143
253
  - [Hello Samples](#hello-samples)
254
+ - [Hello, World! Sample](#hello-world-sample)
255
+ - [Hello, Tab!](#hello-tab)
256
+ - [Hello, Combo!](#hello-combo)
257
+ - [Hello, List Single Selection!](#hello-list-single-selection)
258
+ - [Hello, List Multi Selection!](#hello-list-multi-selection)
259
+ - [Hello, Computed!](#hello-computed)
260
+ - [Hello, Message Box!](#hello-message-box)
261
+ - [Hello, Browser!](#hello-browser)
262
+ - [Hello, Drag and Drop!](#hello-drag-and-drop)
263
+ - [Hello, Menu Bar!](#hello-menu-bar)
264
+ - [Hello, Pop Up Context Menu!](#hello-pop-up-context-menu)
144
265
  - [Elaborate Samples](#elaborate-samples)
266
+ - [Login](#login)
267
+ - [Tic Tac Toe Sample](#tic-tac-toe-sample)
268
+ - [Contact Manager](#contact-manager-sample)
145
269
  - [External Samples](#external-samples)
146
270
  - [Glimmer Calculator](#glimmer-calculator)
147
271
  - [Gladiator](#gladiator)
148
272
  - [In Production](#in-production)
149
- - [SWT Reference](#swt-reference)
150
- - [SWT Packages](#swt-packages)
151
- - [Logging](#logging)
152
- - [Raw JRuby Command](#raw-jruby-command)
153
- - [Mac Support](#mac-support)
273
+ - [Math Bowling](#math-bowling)
274
+ - [Are We There Yet?](#are-we-there-yet)
154
275
  - [Packaging & Distribution](#packaging--distribution)
155
276
  - [Packaging Defaults](#packaging-defaults)
156
277
  - [Packaging Configuration](#packaging-configuration)
@@ -161,11 +282,12 @@ Ruby is a dynamically-typed object-oriented language, which provides great produ
161
282
  - [Resources](#resources)
162
283
  - [Help](#help)
163
284
  - [Issues](#issues)
164
- - [IRC Channel](#irc-channel)
285
+ - [Chat](#chat)
165
286
  - [Feature Suggestions](#feature-suggestions)
166
287
  - [Change Log](#change-log)
167
288
  - [Contributing](#contributing)
168
289
  - [Contributors](#contributors)
290
+ - [Hire Me](#hire-me)
169
291
  - [License](#license)
170
292
 
171
293
  ## Background
@@ -192,14 +314,14 @@ https://www.eclipse.org/swt/faq.php
192
314
  ## Pre-requisites
193
315
 
194
316
  - SWT 4.15 (comes included in Glimmer gem)
195
- - JRuby 9.2.11.1 (supporting Ruby 2.5.x syntax) (find at [https://www.jruby.org/download](https://www.jruby.org/download))
196
- - JDK 8 - 10 (find at [https://www.oracle.com/java/technologies/javase-downloads.html](https://www.oracle.com/java/technologies/javase-downloads.html))
317
+ - JRuby 9.2.12.0 (supporting Ruby 2.5.x syntax) (find at [https://www.jruby.org/download](https://www.jruby.org/download))
318
+ - JDK 8 (find at [https://www.oracle.com/java/technologies/javase-downloads.html](https://www.oracle.com/java/technologies/javase-downloads.html))
197
319
  - (Optional) RVM is needed for [Scaffolding](#scaffolding) only (find at [https://rvm.io/](https://rvm.io/))
198
320
 
199
321
  On **Mac** and **Linux**, an easy way to obtain JRuby is through [RVM](http://rvm.io) by running:
200
322
 
201
323
  ```bash
202
- rvm install jruby-9.2.11.1
324
+ rvm install jruby-9.2.12.0
203
325
  ```
204
326
 
205
327
  Glimmer might still work on lower versions of Java, JRuby and SWT, but there are no guarantees, so it is best to stick to the pre-requisites outlined above.
@@ -208,22 +330,36 @@ Glimmer might still work on lower versions of Java, JRuby and SWT, but there are
208
330
 
209
331
  Please follow these instructions to make the `glimmer` command available on your system via the [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem.
210
332
 
211
- ### Option 1: Direct Install
333
+ If you intend to learn the basics of Glimmer but are not ready to build a Glimmer app yet, pick Option 1 ([Direct Install](#option-1-direct-install)).
334
+
335
+ If you intend to build a Glimmer app from scratch on the Mac, pick Option 1 ([Direct Install](#option-1-direct-install)) to leverage [Glimmer Scaffolding](#scaffolding) (only available on the Mac).
336
+
337
+ Otherwise, Option 2 ([Bundler](#option-2-bundler)) is recommended for building Glimmer apps on other platforms (Windows and Linux).
338
+
339
+ ### Option 1: Direct Install
340
+ (Use for [Scaffolding](#scaffolding) on the Mac)
212
341
 
213
342
  Run this command to install directly:
214
343
  ```
215
- jgem install glimmer-dsl-swt -v 0.1.2
344
+ jgem install glimmer-dsl-swt -v 0.4.1
216
345
  ```
217
346
 
218
347
  `jgem` is JRuby's version of `gem` command.
219
348
  RVM allows running `gem` as an alias.
220
349
  Otherwise, you may also run `jruby -S gem install ...`
221
350
 
222
- ### Option 2: Bundler
351
+ If you are new to Glimmer and would like to continue learning the basics, you may continue to the [Glimmer Command](https://github.com/AndyObtiva/glimmer#glimmer-command) section.
352
+
353
+ Otherwise, if you are ready to build a Glimmer app on the Mac, you can jump to the [Glimmer Scaffolding](https://github.com/AndyObtiva/glimmer#scaffolding) section next.
354
+
355
+ Note: if you're using activerecord or activesupport, keep in mind that Glimmer unhooks ActiveSupport::Dependencies as it does not rely on it.
356
+
357
+ ### Option 2: Bundler
358
+ (Use for Manual App Creation)
223
359
 
224
360
  Add the following to `Gemfile`:
225
361
  ```
226
- gem 'glimmer-dsl-swt', '~> 0.1.2'
362
+ gem 'glimmer-dsl-swt', '~> 0.4.1'
227
363
  ```
228
364
 
229
365
  And, then run:
@@ -231,10 +367,16 @@ And, then run:
231
367
  jruby -S bundle install
232
368
  ```
233
369
 
370
+ Note: if you're using activerecord or activesupport, keep in mind that Glimmer unhooks ActiveSupport::Dependencies as it does not rely on it.
371
+
234
372
  You may learn more about other Glimmer related gems ([`glimmer-dsl-opal`](https://github.com/AndyObtiva/glimmer-dsl-opal), [`glimmer-dsl-xml`](https://github.com/AndyObtiva/glimmer-dsl-xml), and [`glimmer-dsl-css`](https://github.com/AndyObtiva/glimmer-dsl-css)) at [Multi-DSL Support](#multi-dsl-support)
235
373
 
236
374
  ## Glimmer Command
237
375
 
376
+ The `glimmer` command allows you to run, scaffold, package, and list Glimmer applications/gems.
377
+
378
+ If you are new to Glimmer, you may read the Basic Usage section and skip the rest until you have gone through [Girb (Glimmer irb) Command](#girb-glimmer-irb-command), [Glimmer DSL Syntax](#glimmer-dsl-syntax), and [Samples](#samples).
379
+
238
380
  ### Basic Usage
239
381
 
240
382
  ```
@@ -271,7 +413,11 @@ Either a single task or one or more applications may be specified.
271
413
  When a task is specified, it runs via rake. Some tasks take arguments in square brackets.
272
414
 
273
415
  Available tasks are below (you may also lookup by adding `require 'glimmer/rake_task'` in Rakefile and running rake -T):
416
+ glimmer list:custom_shell_gems[query] # List Glimmer custom shell gems available at rubygems.org (query is optional)
417
+ glimmer list:custom_widget_gems[query] # List Glimmer custom widget gems available at rubygems.org (query is optional)
418
+ glimmer list:dsl_gems[query] # List Glimmer DSL gems available at rubygems.org (query is optional)
274
419
  glimmer package # Package app for distribution (generating config, jar, and native files)
420
+ glimmer package:clean # Clean by removing "dist" and "packages" directories
275
421
  glimmer package:config # Generate JAR config file
276
422
  glimmer package:jar # Generate JAR file
277
423
  glimmer package:native # Generate Native files (DMG/PKG/APP on the Mac)
@@ -369,6 +515,10 @@ Eventually, it will launch an advanced "Hello, World!" app window having the tit
369
515
 
370
516
  ![Glimmer Scaffold App](images/glimmer-scaffolding-app.png)
371
517
 
518
+ On the Mac, it also comes with a boilerplate Preferences dialog.
519
+
520
+ ![Glimmer Scaffold App Preferences](images/glimmer-scaffolding-app-preferences.png)
521
+
372
522
  #### Custom Shell
373
523
 
374
524
  To scaffold a Glimmer custom shell (full window view) for an existing Glimmer app, run the following command:
@@ -424,11 +574,133 @@ The Ruby gem name will follow the convention "glimmer-cw-customwidgetname-namesp
424
574
 
425
575
  Only official Glimmer gems created by the Glimmer project committers will have no namespace (e.g. [glimmer-cw-video](https://rubygems.org/gems/glimmer-cw-video) Ruby gem)
426
576
 
427
- Example: [https://github.com/AndyObtiva/glimmer-cw-video](https://github.com/AndyObtiva/glimmer-cw-video)
577
+ Examples:
578
+
579
+ - [glimmer-cw-video](https://github.com/AndyObtiva/glimmer-cw-video): Video Widget
580
+ - [glimmer-cw-cdatetime-nebula](https://github.com/AndyObtiva/glimmer-cw-cdatetime-nebula): Nebula CDateTime Widget
581
+
582
+ ### Gem Listing
583
+
584
+ The `glimmer` command comes with tasks for listing Glimmer related gems to make it easy to find Glimmer Custom Shells, Custom Widgets, and DSLs published by others in the Glimmer community on [rubygems.org](http://www.rubygems.org).
585
+
586
+ #### Listing Custom Shell Gems
587
+
588
+ The following command lists available Glimmer [Custom Shell Gems](#custom-shell-gem) (prefixed with "glimmer-cs-" by scaffolding convention) created by the the Glimmer community and published on [rubygems.org](http://www.rubygems.org):
589
+
590
+ ```
591
+ glimmer list:custom_shell_gems[query] # List Glimmer custom shell gems available at rubygems.org (query is optional)
592
+ ```
593
+
594
+ Example:
595
+
596
+ ```
597
+ glimmer list:custom_shell_gems
598
+ ```
599
+
600
+ Output:
601
+
602
+ ```
603
+
604
+ Glimmer Custom Shell Gems at rubygems.org:
605
+
606
+ Name Gem Version Author Description
607
+
608
+ Calculator glimmer-cs-calculator 1.0.1 Andy Maleh Calculator - Glimmer Custom Shell
609
+ Gladiator glimmer-cs-gladiator 0.2.0 Andy Maleh Gladiator (Glimmer Editor) - Glimmer Custom Shell
610
+
611
+ ```
612
+
613
+ #### Listing Custom Widget Gems
614
+
615
+ The following command lists available Glimmer [Custom Widget Gems](#custom-widget-gem) (prefixed with "glimmer-cw-" by scaffolding convention) created by the the Glimmer community and published on [rubygems.org](http://www.rubygems.org):
616
+
617
+ ```
618
+ glimmer list:custom_widget_gems[query] # List Glimmer custom widget gems available at rubygems.org (query is optional)
619
+ ```
620
+
621
+ Example:
622
+
623
+ Check if there is a custom video widget for Glimmer.
624
+
625
+ ```
626
+ glimmer list:custom_widget_gems[video]
627
+ ```
628
+
629
+ Output:
630
+
631
+ ```
632
+
633
+ Glimmer Custom Widget Gems matching [video] at rubygems.org:
634
+
635
+ Name Gem Version Author Description
636
+
637
+ Video glimmer-cw-video 0.1.1 Andy Maleh Glimmer Custom Widget - Video
638
+
639
+ ```
640
+
641
+ #### Listing DSL Gems
642
+
643
+ The following command lists available Glimmer [DSL Gems](#multi-dsl-support) (prefixed with "glimmer-dsl-" by convention) created by the the Glimmer community and published on [rubygems.org](http://www.rubygems.org):
644
+
645
+ ```
646
+ glimmer list:dsl_gems[query] # List Glimmer DSL gems available at rubygems.org (query is optional)
647
+ ```
648
+
649
+ Example:
650
+
651
+ ```
652
+ glimmer list:dsl_gems
653
+ ```
654
+
655
+ Output:
656
+
657
+ ```
658
+
659
+ Glimmer DSL Gems at rubygems.org:
660
+
661
+ Name Gem Version Author Description
662
+
663
+ Css glimmer-dsl-css 0.1.0 AndyMaleh Glimmer DSL for CSS
664
+ Opal glimmer-dsl-opal 0.0.9 AndyMaleh Glimmer DSL for Opal
665
+ Swt glimmer-dsl-swt 0.4.1 AndyMaleh Glimmer DSL for SWT
666
+ Xml glimmer-dsl-xml 0.1.0 AndyMaleh Glimmer DSL for XML
667
+
668
+ ```
669
+
670
+ ### Packaging
671
+
672
+ Glimmer packaging tasks are detailed under [Packaging & Distribution](#packaging--distribution).
673
+
674
+ ### Raw JRuby Command
675
+
676
+ If there is a need to run Glimmer directly via the `jruby` command, you
677
+ may run the following:
678
+
679
+ ```
680
+ jruby -J-classpath "path_to/swt.jar" -r glimmer -S application.rb
681
+ ```
682
+
683
+ The `-J-classpath` option specifies the `swt.jar` file path, which can be a
684
+ manually downloaded version of SWT, or otherwise the one included in the gem. You can lookup the one included in the gem by running `jgem which glimmer` to find the gem path and then look through the `vendor` directory.
685
+
686
+ The `-r` option preloads (requires) the `glimmer` library in Ruby.
687
+
688
+ The `-S` option specifies a script to run.
689
+
690
+ #### Mac Support
691
+
692
+ The Mac is well supported with the `glimmer` command. The advice below is not needed if you are using it.
693
+
694
+ However, if there is a reason to use the raw `jruby` command directly instead of the `glimmer` command, you need to pass an extra option (`-J-XstartOnFirstThread`) to JRuby on the Mac (Glimmer automatically passes it for you when using the `glimmer` command).
695
+
696
+ Example:
697
+ ```
698
+ jruby -J-XstartOnFirstThread -J-classpath "path_to/swt.jar" -r glimmer -S application.rb
699
+ ```
428
700
 
429
701
  ## Girb (Glimmer irb) Command
430
702
 
431
- With Glimmer installed, you may want to run `girb` instead of standard `irb` to have SWT preloaded and the Glimmer library required and included for quick Glimmer coding/testing.
703
+ With `glimmer-dsl-swt` installed, you may want to run `girb` instead of standard `irb` to have SWT preloaded and the Glimmer library required and included for quick Glimmer coding/testing.
432
704
 
433
705
  ```
434
706
  girb
@@ -448,13 +720,13 @@ Keep in mind that all samples live under [https://github.com/AndyObtiva/glimmer-
448
720
 
449
721
  Glimmer DSL syntax consists of static keywords and dynamic keywords to build and bind user-interface objects.
450
722
 
451
- Static keywords are pre-identified keywords in the Glimmer DSL, such as `shell`, `rgb`, and `bind`.
723
+ Static keywords are pre-identified keywords in the Glimmer DSL, such as `shell`, `message_box`, `async_exec`, and `bind`.
452
724
 
453
- Dynamic keywords are dynamically figured out from available SWT widgets, custom widgets, and properties. Examples are: `label`, `combo`, and `text`.
725
+ Dynamic keywords are dynamically figured out from available SWT widgets, custom widgets, and properties. Examples are: `label`, `combo`, and `list`.
454
726
 
455
- The only reason to distinguish between both types of Glimmer DSL keywords is to realize that importing new Java SWT custom widget libraries and Ruby custom widgets automatically expands Glimmer's available DSL syntax via new dynamic keywords.
727
+ The only reason to distinguish between the two types of Glimmer DSL keywords is to realize that importing new Glimmer [custom widgets](#custom-widgets) and Java SWT custom widget libraries automatically expands Glimmer's DSL vocabulary via new dynamic keywords.
456
728
 
457
- For example, if a project adds this custom SWT library:
729
+ For example, if a project adds this custom Java SWT library:
458
730
 
459
731
  https://www.eclipse.org/nebula/widgets/cdatetime/cdatetime.php?page=operation
460
732
 
@@ -547,22 +819,22 @@ Check out the [samples](samples) directory for more examples.
547
819
 
548
820
  Example from [hello_tab.rb](samples/hello/hello_tab.rb) sample (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
549
821
 
550
- ![Hello Tab 1](images/glimmer-hello-tab1.png)
822
+ ![Hello Tab English](images/glimmer-hello-tab-english.png)
551
823
 
552
- ![Hello Tab 2](images/glimmer-hello-tab2.png)
824
+ ![Hello Tab French](images/glimmer-hello-tab-french.png)
553
825
 
554
826
  ```ruby
555
827
  shell {
556
- text "SWT"
828
+ text "Hello, Tab!"
557
829
  tab_folder {
558
830
  tab_item {
559
- text "Tab 1"
831
+ text "English"
560
832
  label {
561
833
  text "Hello, World!"
562
834
  }
563
835
  }
564
836
  tab_item {
565
- text "Tab 2"
837
+ text "French"
566
838
  label {
567
839
  text "Bonjour Univers!"
568
840
  }
@@ -582,7 +854,7 @@ automatically uses the display created earlier without having to explicitly hook
582
854
  ```ruby
583
855
  @display = display {
584
856
  cursor_location 300, 300
585
- on_event_keydown {
857
+ on_swt_keydown {
586
858
  # ...
587
859
  }
588
860
  # ...
@@ -634,27 +906,34 @@ Example (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
634
906
  @shell.open
635
907
  ```
636
908
 
637
- ##### `#swt_widget`
909
+ ##### `message_box`
638
910
 
639
- Glimmer widget objects come with an instance method `#swt_widget` that returns the actual SWT `Widget` object wrapped by the Glimmer widget object. It is useful in cases you'd like to do some custom SWT programming outside of Glimmer.
911
+ The Glimmer DSL `message_box` keyword is similar to `shell`, but renders a modal dialog with a title `text` property and main body `message` property. It may also be opened via the `#open` method.
640
912
 
641
913
  Example (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
642
914
 
643
915
  ```ruby
916
+ include Glimmer
917
+
644
918
  @shell = shell {
919
+ text 'Hello, Message Box!'
645
920
  button {
646
- text "Press Me"
921
+ text 'Please Click To Win a Surprise'
647
922
  on_widget_selected {
648
- message_box = MessageBox.new(@shell.swt_widget) # passing SWT Shell widget
649
- message_box.setText("Surprise")
650
- message_box.setMessage("You have won $1,000,000!")
651
- message_box.open
923
+ message_box(@shell) {
924
+ text 'Surprise'
925
+ message "Congratulations!\n\nYou have won $1,000,000!"
926
+ }.open
652
927
  }
653
928
  }
654
929
  }
655
930
  @shell.open
656
931
  ```
657
932
 
933
+ ##### `#swt_widget`
934
+
935
+ Glimmer widget objects come with an instance method `#swt_widget` that returns the actual SWT `Widget` object wrapped by the Glimmer widget object. It is useful in cases you'd like to do some custom SWT programming outside of Glimmer.
936
+
658
937
  ##### Shell widget proxy methods
659
938
 
660
939
  Shell widget proxy has extra methods specific to SWT Shell:
@@ -682,7 +961,7 @@ Glimmer DSL provides support for SWT Menu and MenuItem widgets.
682
961
 
683
962
  There are 2 main types of menus in SWT:
684
963
  - Menu Bar (shows up on top)
685
- - Pop Up Menu (shows up when right-clicking a widget)
964
+ - Pop Up Context Menu (shows up when right-clicking a widget)
686
965
 
687
966
  Underneath both types, there can be a 3rd menu type called Drop Down.
688
967
 
@@ -690,39 +969,63 @@ Glimmer provides special support for Drop Down menus as it automatically instant
690
969
 
691
970
  The ampersand symbol indicates the keyboard shortcut key for the menu item (e.g. '&Help' can be triggered on Windows by hitting ALT+H)
692
971
 
693
- Example [Menu Bar] (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
972
+ Example of a Menu Bar (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
694
973
 
695
974
  ```ruby
696
- shell {
975
+ shell { |shell_proxy|
976
+ text 'Hello, Menu Bar!'
977
+ grid_layout
978
+ label(:center) {
979
+ font height: 16
980
+ text 'Check Out The File Menu and History Menu in The Menu Bar Above!'
981
+ }
697
982
  menu_bar {
698
983
  menu {
699
- text "&File"
984
+ text '&File'
700
985
  menu_item {
701
- text "E&xit"
986
+ text 'E&xit'
702
987
  }
703
988
  menu_item(0) {
704
- text "&New"
989
+ text '&New'
990
+ on_widget_selected {
991
+ message_box(shell_proxy) {
992
+ text 'New File'
993
+ message 'New File Contents'
994
+ }.open
995
+ }
705
996
  }
706
997
  menu(1) {
707
- text "&Options"
998
+ text '&Options'
708
999
  menu_item(:radio) {
709
- text "Option 1"
1000
+ text 'Option 1'
710
1001
  }
711
1002
  menu_item(:separator)
712
1003
  menu_item(:check) {
713
- text "Option 3"
1004
+ text 'Option 3'
714
1005
  }
715
1006
  }
716
1007
  }
717
1008
  menu {
718
- text "&History"
1009
+ text '&History'
719
1010
  menu {
720
- text "&Recent"
1011
+ text '&Recent'
721
1012
  menu_item {
722
- text "File 1"
1013
+ text 'File 1'
1014
+ on_widget_selected {
1015
+ message_box(shell_proxy) {
1016
+ text 'File 1'
1017
+ message 'File 1 Contents'
1018
+ }.open
1019
+ }
723
1020
  }
724
1021
  menu_item {
725
- text "File 2"
1022
+ text 'File 2'
1023
+ on_widget_selected {
1024
+ message_box(shell_proxy) {
1025
+ text 'File 2'
1026
+ message 'File 2 Contents'
1027
+ }.open
1028
+ }
726
1029
  }
727
1030
  }
728
1031
  }
@@ -730,22 +1033,37 @@ shell {
730
1033
  }.open
731
1034
  ```
732
1035
 
733
- Example [Pop Up Menu] (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
1036
+ Example of a Pop Up Context Menu (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
734
1037
 
735
1038
  ```ruby
736
- shell {
1039
+ shell { |shell_proxy|
1040
+ text 'Hello, Pop Up Context Menu!'
1041
+ grid_layout
737
1042
  label {
738
- text 'Right-Click Me'
1043
+ font height: 16
1044
+ text 'Right-Click To Pop Up a Context Menu'
739
1045
  menu {
740
1046
  menu {
741
1047
  text '&History'
742
1048
  menu {
743
- text "&Recent"
1049
+ text '&Recent'
744
1050
  menu_item {
745
- text "File 1"
1051
+ text 'File 1'
1052
+ on_widget_selected {
1053
+ message_box(shell_proxy) {
1054
+ text 'File 1'
1055
+ message 'File 1 Contents'
1056
+ }.open
1057
+ }
746
1058
  }
747
1059
  menu_item {
748
- text "File 2"
1060
+ text 'File 2'
1061
+ on_widget_selected {
1062
+ message_box(shell_proxy) {
1063
+ text 'File 2'
1064
+ message 'File 2 Contents'
1065
+ }.open
1066
+ }
749
1067
  }
750
1068
  }
751
1069
  }
@@ -754,6 +1072,13 @@ shell {
754
1072
  }.open
755
1073
  ```
756
1074
 
1075
+ #### ScrolledComposite
1076
+
1077
+ Glimmer provides smart defaults for the `scrolled_composite` widget by:
1078
+ - Automatically setting the nested widget as its content (meaning use can just like a plain old `composite` to add scrolling)
1079
+ - Automatically setting the :h_scroll and :v_scroll SWT styles (can be set manually if only one of either :h_scroll or :v_scroll is desired )
1080
+ - Automatically setting the expand horizontal and expand vertical SWT properties to `true`
1081
+
757
1082
  ### Widget Styles
758
1083
 
759
1084
  SWT widgets receive `SWT` styles in their constructor as per this guide:
@@ -999,9 +1324,12 @@ composite {
999
1324
  ```
1000
1325
 
1001
1326
  Here is a more sophisticated example taken from [hello_computed.rb](samples/hello/hello_computed.rb) sample:
1327
+
1328
+ ![Hello Computed](images/glimmer-hello-computed.png)
1329
+
1002
1330
  ```ruby
1003
1331
  shell {
1004
- text "Hello Computed"
1332
+ text 'Hello, Computed!'
1005
1333
  composite {
1006
1334
  grid_layout {
1007
1335
  num_columns 2
@@ -1009,44 +1337,44 @@ shell {
1009
1337
  horizontal_spacing 20
1010
1338
  vertical_spacing 10
1011
1339
  }
1012
- label {text "First &Name: "}
1340
+ label {text 'First &Name: '}
1013
1341
  text {
1014
1342
  text bind(@contact, :first_name)
1015
1343
  layout_data {
1016
- horizontalAlignment :fill
1017
- grabExcessHorizontalSpace true
1344
+ horizontal_alignment :fill
1345
+ grab_excess_horizontal_space true
1018
1346
  }
1019
1347
  }
1020
- label {text "&Last Name: "}
1348
+ label {text '&Last Name: '}
1021
1349
  text {
1022
1350
  text bind(@contact, :last_name)
1023
1351
  layout_data {
1024
- horizontalAlignment :fill
1025
- grabExcessHorizontalSpace true
1352
+ horizontal_alignment :fill
1353
+ grab_excess_horizontal_space true
1026
1354
  }
1027
1355
  }
1028
- label {text "&Year of Birth: "}
1356
+ label {text '&Year of Birth: '}
1029
1357
  text {
1030
1358
  text bind(@contact, :year_of_birth)
1031
1359
  layout_data {
1032
- horizontalAlignment :fill
1033
- grabExcessHorizontalSpace true
1360
+ horizontal_alignment :fill
1361
+ grab_excess_horizontal_space true
1034
1362
  }
1035
1363
  }
1036
- label {text "Name: "}
1364
+ label {text 'Name: '}
1037
1365
  label {
1038
1366
  text bind(@contact, :name, computed_by: [:first_name, :last_name])
1039
1367
  layout_data {
1040
- horizontalAlignment :fill
1041
- grabExcessHorizontalSpace true
1368
+ horizontal_alignment :fill
1369
+ grab_excess_horizontal_space true
1042
1370
  }
1043
1371
  }
1044
- label {text "Age: "}
1372
+ label {text 'Age: '}
1045
1373
  label {
1046
1374
  text bind(@contact, :age, on_write: :to_i, computed_by: [:year_of_birth])
1047
1375
  layout_data {
1048
- horizontalAlignment :fill
1049
- grabExcessHorizontalSpace true
1376
+ horizontal_alignment :fill
1377
+ grab_excess_horizontal_space true
1050
1378
  }
1051
1379
  }
1052
1380
  }
@@ -1189,6 +1517,10 @@ Example from [samples/hello/hello_combo.rb](samples/hello_combo.rb) sample (you
1189
1517
 
1190
1518
  #### Combo
1191
1519
 
1520
+ The `combo` widget provides a dropdown of options. By default, it also allows typing in a new option. To disable that behavior, you may use with the `:read_only` SWT style.
1521
+
1522
+ When data-binding a `combo` widget, Glimmer can automatically deduce available options from data-bound model by convention: `{attribute_name}_options` method.
1523
+
1192
1524
  ![Hello Combo](images/glimmer-hello-combo.png)
1193
1525
 
1194
1526
  ![Hello Combo](images/glimmer-hello-combo-expanded.png)
@@ -1230,7 +1562,7 @@ end
1230
1562
  HelloCombo.new.launch
1231
1563
  ```
1232
1564
 
1233
- `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.
1565
+ `combo` widget is data-bound to the country of a person. Note that it expects the `person` object to have the `:country` attribute and `:country_options` attribute containing all available countries (aka options). Glimmer reads these attributes by convention.
1234
1566
 
1235
1567
  #### List
1236
1568
 
@@ -1344,6 +1676,9 @@ shell {
1344
1676
  }
1345
1677
  items bind(group, :people), column_properties(:name, :age, :adult)
1346
1678
  selection bind(group, :selected_person)
1679
+ on_mouse_up { |event|
1680
+ @table.edit_table_item(event.table_item, event.column_index)
1681
+ }
1347
1682
  }
1348
1683
  }
1349
1684
  ```
@@ -1351,6 +1686,7 @@ shell {
1351
1686
  The code above includes two data-bindings:
1352
1687
  - 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.
1353
1688
  - 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)
1689
+ - The `on_mouse_up` event handler invokes `@table.edit_table_item(event.table_item, event.column_index)` to start edit mode on the clicked table item cell, and then saves or cancel depending on whether the user hits ENTER or ESC once done editing (or focus-out after either making a change or not making any changes.)
1354
1690
 
1355
1691
  Additionally, Table `items` data-binding automatically stores each node model unto the SWT TableItem object via `setData` method. This enables things like searchability.
1356
1692
 
@@ -1370,6 +1706,67 @@ This automatically leverages the SWT TableEditor custom class behind the scenes,
1370
1706
  passed table item text into something else.
1371
1707
  It automatically persists the change to `items` data-bound model on ENTER/FOCUS-OUT or cancels on ESC/NO-CHANGE.
1372
1708
 
1709
+ ##### Table Sorting
1710
+
1711
+ Glimmer automatically adds sorting support to the SWT `Table` widget.
1712
+
1713
+ Check out the [Contact Manager](#contact-manager) sample for an example.
1714
+ You may click on any column and it will sort by ascending order first and descending if you click again.
1715
+
1716
+ Glimmer automatic table sorting supports `String`, `Integer`, and `Float` columns out of the box as well as any column data that is comparable.
1717
+
1718
+ In cases where data is nil, depending on the data-type, it is automatically converted to `Float` with `to_f`, `Integer` with `to_i`, or `String` with `to_s`.
1719
+
1720
+ Should you have a special data type that could not be compared automatically, Glimmer offers the following 3 alternatives for custom sorting:
1721
+ - `sort_property`: this may be set to an alternative property to the one data-bound to the table column. For example, a table column called 'adult', which returns `true` or `false` may be sorted with `sort_property :dob` instead. This also support multi-property (aka multi-column) sorting (e.g. `sort_property :dob, :name`).
1722
+ - `sort_by(&block)`: this works just like Ruby `Enumerable` `sort_by`. The block receives the table column data as argument.
1723
+ - `sort(&comparator)`: this works just like Ruby `Enumerable` `sort`. The comparator block receives two objects from the table column data.
1724
+
1725
+ You may also set `additional_sort_properties` on the parent `table` widget to have secondary sorting applied. For example, if you set `additional_sort_properties :name, :project_name`, then whenever you sort by `:name`, it additionally sorts by `:project_name` afterwards, and vice versa. This only works for columns that either have no custom sort set or have a `sort_property` with one property only (but no sort or sort_by block)
1726
+
1727
+ Example:
1728
+
1729
+ ```ruby
1730
+ # ...
1731
+ table {
1732
+ table_column {
1733
+ text 'Task'
1734
+ width 120
1735
+ }
1736
+ table_column {
1737
+ text 'Project'
1738
+ width 120
1739
+ }
1740
+ table_column {
1741
+ text 'Duration (hours)'
1742
+ width 120
1743
+ sort_property :duration_in_hours
1744
+ }
1745
+ table_column {
1746
+ text 'Priority'
1747
+ width 120
1748
+ sort_by { |value| ['High', 'Medium', 'Low'].index(value) }
1749
+ }
1750
+ table_column {
1751
+ text 'Start Date'
1752
+ width 120
1753
+ sort { |d1, d2| d1.to_date <=> d2.to_date }
1754
+ }
1755
+ additional_sort_properties :project_name, :duration_in_hours, :name
1756
+ items bind(Task, :list), column_properties(:name, :project_name, :duration, :priority, :start_date)
1757
+ # ...
1758
+ }
1759
+ # ...
1760
+ ```
1761
+
1762
+ Here is an explanation of the example above:
1763
+ - Task and Project table columns are data-bound to the `:name` and `:project_name` properties and sorted through them automatically
1764
+ - Task Duration table column is data-bound to the `:duration` property, but sorted via the `:duration_in_hours` property instead
1765
+ - Task Priority table column has a custom sort_by block
1766
+ - Task Start Date table column has a custom sort comparator block
1767
+ - Additional (secondary) sort properties are applied when sorting by Task, Project, or Duration in the order specified
1768
+
1769
+
1373
1770
  #### Tree
1374
1771
 
1375
1772
  The SWT Tree widget visualizes a tree data-structure, such as an employment or composition hierarchy.
@@ -1417,10 +1814,10 @@ Glimmer comes with `Observer` module, which is used internally for data-binding,
1417
1814
 
1418
1815
  Glimmer supports observing widgets with two main types of events:
1419
1816
  1. `on_{swt-listener-method-name}`: where {swt-listener-method-name} is replaced with the lowercase underscored event method name on an SWT listener class (e.g. `on_verify_text` for `org.eclipse.swt.events.VerifyListener#verifyText`).
1420
- 2. `on_event_{swt-event-constant}`: where {swt-event-constant} is replaced with an `org.eclipse.swt.SWT` event constant (e.g. `on_event_show` for `SWT.Show` to observe when widget becomes visible)
1817
+ 2. `on_swt_{swt-event-constant}`: where {swt-event-constant} is replaced with an [`org.eclipse.swt.SWT`](https://help.eclipse.org/2020-06/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/SWT.html) event constant (e.g. `on_swt_show` for `SWT.Show` to observe when widget becomes visible)
1421
1818
 
1422
1819
  Additionally, there are two more types of events:
1423
- - SWT `display` supports global listeners called filters that run on any widget. They are hooked via `on_event_{swt-event-constant}`
1820
+ - SWT `display` supports global listeners called filters that run on any widget. They are hooked via `on_swt_{swt-event-constant}`
1424
1821
  - SWT `display` supports Mac application menu item observers (`on_about` and `on_preferences`), which you can read about under [Miscellaneous](#miscellaneous).
1425
1822
 
1426
1823
  Number 1 is more commonly used in SWT applications, so make it your starting point. Number 2 covers events not found in number 1, so look into it if you don't find an SWT listener you need in number 1.
@@ -1465,21 +1862,21 @@ Note that every Tic Tac Toe grid cell has its `text` and `enabled` properties da
1465
1862
 
1466
1863
  Next however, each of these Tic Tac Toe grid cells, which are clickable buttons, have an `on_widget_selected` observer, which once triggered, marks the cell on the `TicTacToe::Board` to make a move.
1467
1864
 
1468
- **Regarding number 2**, you can figure out all available events by looking at the `org.eclipse.swt.SWT` API:
1865
+ **Regarding number 2**, you can figure out all available events by looking at the [`org.eclipse.swt.SWT`](https://help.eclipse.org/2020-06/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/SWT.html) API:
1469
1866
 
1470
1867
  https://help.eclipse.org/2019-12/nftopic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/SWT.html
1471
1868
 
1472
1869
  Example (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
1473
1870
 
1474
- `SWT.Show` - hooks a listener for showing a widget (using `on_event_show` in Glimmer)
1475
- `SWT.Hide` - hooks a listener for hiding a widget (using `on_event_hide` in Glimmer)
1871
+ `SWT.Show` - hooks a listener for showing a widget (using `on_swt_show` in Glimmer)
1872
+ `SWT.Hide` - hooks a listener for hiding a widget (using `on_swt_hide` in Glimmer)
1476
1873
 
1477
1874
  ```ruby
1478
1875
  shell {
1479
1876
  @button1 = button {
1480
1877
  text "Show 2nd Button"
1481
1878
  visible true
1482
- on_event_show {
1879
+ on_swt_show {
1483
1880
  @button2.swt_widget.setVisible(false)
1484
1881
  }
1485
1882
  on_widget_selected {
@@ -1489,7 +1886,7 @@ shell {
1489
1886
  @button2 = button {
1490
1887
  text "Show 1st Button"
1491
1888
  visible false
1492
- on_event_show {
1889
+ on_swt_show {
1493
1890
  @button1.swt_widget.setVisible(false)
1494
1891
  }
1495
1892
  on_widget_selected {
@@ -1499,7 +1896,7 @@ shell {
1499
1896
  }.open
1500
1897
  ```
1501
1898
 
1502
- **Gotcha:** SWT.Resize event needs to be hooked using **`on_event_Resize`** because `org.eclipse.swt.SWT` has 2 constants for resize: `RESIZE` and `Resize`, so it cannot infer the right one automatically from the underscored version `on_event_resize`
1899
+ **Gotcha:** SWT.Resize event needs to be hooked using **`on_swt_Resize`** because [`org.eclipse.swt.SWT`](https://help.eclipse.org/2020-06/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/SWT.html) has 2 constants for resize: `RESIZE` and `Resize`, so it cannot infer the right one automatically from the underscored version `on_swt_resize`
1503
1900
 
1504
1901
  ##### Alternative Syntax
1505
1902
 
@@ -1542,7 +1939,7 @@ class TicTacToe
1542
1939
  end
1543
1940
  ```
1544
1941
 
1545
- Observers can be a good mechanism for displaying dialog messages in Glimmer (using SWT's `MessageBox`).
1942
+ Observers can be a good mechanism for displaying dialog messages in Glimmer (using SWT's [`MessageBox`](https://help.eclipse.org/2020-06/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/widgets/MessageBox.html) class).
1546
1943
 
1547
1944
  Look at [`samples/elaborate/tictactoe/tic_tac_toe.rb`](samples/tictactoe/tic_tac_toe.rb) for more details starting with the code included below.
1548
1945
 
@@ -1568,10 +1965,10 @@ class TicTacToe
1568
1965
  end
1569
1966
 
1570
1967
  def display_game_over_message(message)
1571
- message_box = MessageBox.new(@shell.swt_widget)
1572
- message_box.setText("Game Over")
1573
- message_box.setMessage(message)
1574
- message_box.open
1968
+ message_box(@shell) {
1969
+ text 'Game Over'
1970
+ message message_text
1971
+ }.open
1575
1972
  @tic_tac_toe_board.reset
1576
1973
  end
1577
1974
  # ...
@@ -1612,7 +2009,7 @@ shell {
1612
2009
 
1613
2010
  As you can see, `RedLabel` became Glimmer DSL keyword: `red_label`
1614
2011
 
1615
- #### Hook Example
2012
+ #### Lifecycle Hook Example
1616
2013
 
1617
2014
  (you may copy/paste in [`girb`](#girb-glimmer-irb-command))
1618
2015
 
@@ -1647,10 +2044,12 @@ shell {
1647
2044
  }.open
1648
2045
  ```
1649
2046
 
1650
- Notice how `Red::Composite` became `red__composite` with double-underscore, which is how Glimmer Custom Widgets signify namespaces by convention. Additionally, `before_body` hook was utilized to set a `@color` variable and use inside the `body`.
2047
+ Notice how `Red::Composite` became `red__composite` with double-underscore, which is how Glimmer Custom Widgets signify namespaces by convention. Additionally, the `before_body` lifecycle hook was utilized to set a `@color` variable and use inside the `body`.
1651
2048
 
1652
2049
  Keep in mind that namespaces are not needed to be specified if the Custom Widget class has a unique name, not clashing with a basic SWT widget or another custom widget name.
1653
2050
 
2051
+ #### Custom Widget API
2052
+
1654
2053
  Custom Widgets have the following attributes available to call from inside the `#body` method:
1655
2054
  - `#parent`: Glimmer object parenting custom widget
1656
2055
  - `#swt_style`: SWT style integer. Can be useful if you want to allow consumers to customize a widget inside the custom widget body
@@ -1705,7 +2104,9 @@ shell {
1705
2104
 
1706
2105
  Notice how `:no_focus` was the `swt_style` value, followed by the `options` hash `{orientation: :horizontal, bg_color: :white}`, and finally the `content` block containing the label with `'SANDWICH CONTENT'`
1707
2106
 
1708
- Last but not least, these are the available hooks:
2107
+ #### Custom Widget Lifecycle Hooks
2108
+
2109
+ Last but not least, these are the available lifecycle hooks:
1709
2110
  - `before_body`: takes a block that executes in the custom widget instance scope before calling `body`. Useful for initializing variables to later use in `body`
1710
2111
  - `after_body`: takes a block that executes in the custom widget instance scope after calling `body`. Useful for setting up observers on widgets built in `body` (set in instance variables) and linking to other shells.
1711
2112
 
@@ -1739,6 +2140,11 @@ body {
1739
2140
 
1740
2141
  The `text` method invoked in the custom widget body will call the one you defined above it. To avoid this gotcha, simply name the text property above something else, like `custom_text`.
1741
2142
 
2143
+ #### Final Notes
2144
+
2145
+ This [Eclipse guide](https://www.eclipse.org/articles/Article-Writing%20Your%20Own%20Widget/Writing%20Your%20Own%20Widget.htm) for how to write custom SWT widgets is also applicable to Glimmer Custom Widgets written in Ruby. I recommend reading it:
2146
+ [https://www.eclipse.org/articles/Article-Writing%20Your%20Own%20Widget/Writing%20Your%20Own%20Widget.htm](https://www.eclipse.org/articles/Article-Writing%20Your%20Own%20Widget/Writing%20Your%20Own%20Widget.htm)
2147
+
1742
2148
  ### Custom Shells
1743
2149
 
1744
2150
  Custom shells are a kind of custom widgets that have shells only as the body root. They can be self-contained applications that may be opened and hidden/closed independently of the main app.
@@ -1784,7 +2190,7 @@ shell { |app_shell|
1784
2190
  @current_step_number = 1
1785
2191
  @wizard_steps = 5.times.map { |n|
1786
2192
  wizard_step(number: n+1, step_count: 5) {
1787
- on_event_hide {
2193
+ on_swt_hide {
1788
2194
  if @current_step_number < 5
1789
2195
  @current_step_number += 1
1790
2196
  app_shell.hide
@@ -1804,6 +2210,62 @@ shell { |app_shell|
1804
2210
  }.open
1805
2211
  ```
1806
2212
 
2213
+ ### Drag and Drop
2214
+
2215
+ Glimmer offers Drag and Drop support, thanks to [SWT](https://www.eclipse.org/swt/) and Glimmer's lightweight [DSL syntax](#glimmer-dsl-syntax).
2216
+
2217
+ You may learn more about SWT Drag and Drop support over here: [https://www.eclipse.org/articles/Article-SWT-DND/DND-in-SWT.html](https://www.eclipse.org/articles/Article-SWT-DND/DND-in-SWT.html)
2218
+
2219
+ To get started, simply follow these steps:
2220
+ 1. On the drag source widget, add `on_drag_set_data` [DragSourceListener](https://help.eclipse.org/2020-03/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/dnd/DragSourceListener.html) event handler block at minimum (you may also add `on_drag_start` and `on_drag_finished` if needed)
2221
+ 1. Set `event.data` to transfer via drag and drop inside the `on_drag_set_data` event handler block (defaults to `transfer` type of `:text`, as in a Ruby String)
2222
+ 1. On the drop target widget, add `on_drop` [DropTargetListener](https://help.eclipse.org/2020-03/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/dnd/DropTargetListener.html) event handler block at minimum (you may also add `on_drag_enter` [must set [`event.detail`](https://help.eclipse.org/2020-06/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/dnd/DropTargetEvent.html#detail) if added], `on_drag_over`, `on_drag_leave`, `on_drag_operation_changed` and `on_drop_accept` if needed)
2223
+ 1. Read `event.data` and consume it (e.g. change widget text) inside the `on_drop` event handler block.
2224
+
2225
+ Example (taken from [samples/hello/hello_drag_and_drop.rb](#hello-drag-and-drop) / you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
2226
+
2227
+ ```ruby
2228
+ class Location
2229
+ attr_accessor :country
2230
+
2231
+ def country_options
2232
+ %w[USA Canada Mexico Columbia UK Australia Germany Italy Spain]
2233
+ end
2234
+ end
2235
+
2236
+ @location = Location.new
2237
+
2238
+ include Glimmer
2239
+
2240
+ shell {
2241
+ text 'Hello, Drag and Drop!'
2242
+ list {
2243
+ selection bind(@location, :country)
2244
+ on_drag_set_data { |event|
2245
+ list = event.widget.getControl
2246
+ event.data = list.getSelection.first
2247
+ }
2248
+ }
2249
+ label(:center) {
2250
+ text 'Drag a country here!'
2251
+ font height: 20
2252
+ on_drop { |event|
2253
+ event.widget.getControl.setText(event.data)
2254
+ }
2255
+ }
2256
+ }.open
2257
+ ```
2258
+
2259
+ ![Hello Drag and Drop](images/glimmer-hello-drag-and-drop.gif)
2260
+
2261
+ Optional steps:
2262
+ - Set a `transfer` property (defaults to `:text`). Values may be: :text (default), :html :image, :rtf, :url, and :file, or an array of multiple values. The `transfer` property will automatically convert your option into a [Transfer](https://help.eclipse.org/2020-03/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/dnd/Transfer.html) object as per the SWT API.
2263
+ - Specify `drag_source_style` operation (may be: :drop_copy (default), :drop_link, :drop_move, :drop_none, or an array of multiple operations)
2264
+ - Specify `drag_source_effect` (Check [DragSourceEffect](https://help.eclipse.org/2020-06/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/dnd/DragSourceEffect.html) SWT API for details)
2265
+ - Specify `drop_target_style` operation (may be: :drop_copy (default), :drop_link, :drop_move, :drop_none, or an array of multiple operations)
2266
+ - Specify `drop_target_effect` (Check [DropTargetEffect](https://help.eclipse.org/2020-06/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/dnd/DropTargetEffect.html) SWT API for details)
2267
+ - Set drag operation in `event.detail` (e.g. DND::DROP_COPY) inside `on_drag_enter`
2268
+
1807
2269
  ### Miscellaneous
1808
2270
 
1809
2271
  #### Multi-DSL Support
@@ -1959,10 +2421,10 @@ class Example
1959
2421
  def initialize
1960
2422
  display {
1961
2423
  on_about {
1962
- message_box = MessageBox.new(@shell_proxy.swt_widget)
1963
- message_box.setText("About")
1964
- message_box.setMessage("About Application")
1965
- message_box.open
2424
+ message_box(@shell_proxy) {
2425
+ text 'About'
2426
+ message 'About Application'
2427
+ }.open
1966
2428
  }
1967
2429
  on_preferences {
1968
2430
  preferences_dialog = dialog {
@@ -2028,7 +2490,7 @@ Also, you may invoke `Display.setAppVersion('1.0.0')` if needed for OS app versi
2028
2490
 
2029
2491
  #### Video Widget
2030
2492
 
2031
- ![Video Widget](images/glimmer-video-widget.png)
2493
+ [![Video Widget](images/glimmer-video-widget.png)](https://github.com/AndyObtiva/glimmer-cw-video)
2032
2494
 
2033
2495
  Glimmer supports a [video custom widget](https://github.com/AndyObtiva/glimmer-cw-video) not in SWT.
2034
2496
 
@@ -2036,7 +2498,9 @@ You may obtain via `glimmer-cw-video` gem.
2036
2498
 
2037
2499
  #### Browser Widget
2038
2500
 
2039
- Glimmer supports SWT Browser widget, which can load URLs or render HTML. It can even be instrumented with JavaScript when needed (though highly discouraged in Glimmer except for rare cases when leveraging a pre-existing web codebase in a desktop app).
2501
+ ![Hello Browser](images/glimmer-hello-browser.png)
2502
+
2503
+ Glimmer supports the SWT Browser widget, which can load URLs or render HTML. It can even be instrumented with JavaScript when needed (though highly discouraged since it defeats the purpose of using Ruby except in very rare cases like leveraging a pre-existing web codebase in a desktop app).
2040
2504
 
2041
2505
  Example loading a URL (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
2042
2506
 
@@ -2072,6 +2536,123 @@ shell {
2072
2536
 
2073
2537
  This relies on Glimmer's [Multi-DSL Support](#multi-dsl-support) for building the HTML text using [Glimmer XML DSL](https://github.com/AndyObtiva/glimmer-dsl-xml).
2074
2538
 
2539
+ ## Glimmer Configuration
2540
+
2541
+ Glimmer configuration may be done via the `Glimmer::Config` module.
2542
+
2543
+ ### logger
2544
+
2545
+ Glimmer supports logging via a standard `STDOUT` Ruby `Logger` configured in the `Glimmer::Config.logger` config option.
2546
+ It is set to level Logger::ERROR by default.
2547
+ Log level may be adjusted via `Glimmer::Config.logger.level` just like any other Ruby Logger.
2548
+ It may be replaced with a custom logger via `Glimmer::Config.logger = custom_logger`
2549
+ All logging is done lazily via blocks (e.g. `logger.debug {message}`) to avoid affecting app performance with logging when below the configured logging level threshold.
2550
+
2551
+ Example:
2552
+
2553
+ ```ruby
2554
+ Glimmer::Config.logger.level = :debug
2555
+ ```
2556
+ This results in more verbose debug loggging to `STDOUT`, which is very helpful in troubleshooting Glimmer DSL syntax when needed.
2557
+
2558
+ Example log:
2559
+ ```
2560
+ D, [2017-07-21T19:23:12.587870 #35707] DEBUG -- : method: shell and args: []
2561
+ D, [2017-07-21T19:23:12.594405 #35707] DEBUG -- : ShellCommandHandler will handle command: shell with arguments []
2562
+ D, [2017-07-21T19:23:12.844775 #35707] DEBUG -- : method: composite and args: []
2563
+ D, [2017-07-21T19:23:12.845388 #35707] DEBUG -- : parent is a widget: true
2564
+ D, [2017-07-21T19:23:12.845833 #35707] DEBUG -- : on listener?: false
2565
+ D, [2017-07-21T19:23:12.864395 #35707] DEBUG -- : WidgetCommandHandler will handle command: composite with arguments []
2566
+ D, [2017-07-21T19:23:12.864893 #35707] DEBUG -- : widget styles are: []
2567
+ D, [2017-07-21T19:23:12.874296 #35707] DEBUG -- : method: list and args: [:multi]
2568
+ D, [2017-07-21T19:23:12.874969 #35707] DEBUG -- : parent is a widget: true
2569
+ D, [2017-07-21T19:23:12.875452 #35707] DEBUG -- : on listener?: false
2570
+ D, [2017-07-21T19:23:12.878434 #35707] DEBUG -- : WidgetCommandHandler will handle command: list with arguments [:multi]
2571
+ D, [2017-07-21T19:23:12.878798 #35707] DEBUG -- : widget styles are: [:multi]
2572
+ ```
2573
+
2574
+ ### import_swt_packages
2575
+
2576
+ Glimmer automatically imports all SWT Java packages upon adding `include Glimmer`, `include Glimmer::UI::CustomWidget`, or `include Glimmer::UI::CustomShell` to a class or module. It relies on JRuby's `include_package` for lazy-importing upon first reference of a Java class.
2577
+
2578
+ As a result, you may call SWT Java classes from Glimmer Ruby code without mentioning Java package references explicitly.
2579
+
2580
+ For example, `org.eclipse.swt.graphics.Color` can be referenced as just `Color`
2581
+
2582
+ The Java packages imported come from the [`Glimmer::Config.import_swt_packages`](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/lib/ext/glimmer/config.rb) config option, which defaults to `Glimmer::Config::DEFAULT_IMPORT_SWT_PACKAGES`, importing the following Java packages:
2583
+ ```
2584
+ org.eclipse.swt.*
2585
+ org.eclipse.swt.widgets.*
2586
+ org.eclipse.swt.layout.*
2587
+ org.eclipse.swt.graphics.*
2588
+ org.eclipse.swt.browser.*
2589
+ org.eclipse.swt.custom.*
2590
+ org.eclipse.swt.dnd.*
2591
+ ```
2592
+
2593
+ If you need to import additional Java packages as extra Glimmer widgets, you may add more packages to [`Glimmer::Config.import_swt_packages`](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/lib/ext/glimmer/config.rb) by using the `+=` operator (or alternatively limit to certain packages via `=` operator).
2594
+
2595
+ Example:
2596
+
2597
+ ```ruby
2598
+ Glimmer::Config.import_swt_packages += [
2599
+ 'org.eclipse.nebula.widgets.ganttchart'
2600
+ ]
2601
+ ```
2602
+
2603
+ Another alternative is to simply add a `java_import` call to your code (e.g. `java_import 'org.eclipse.nebula.widgets.ganttchart.GanttChart'`). Glimmer will automatically take advantage of it (e.g. when invoking `gantt_chart` keyword)
2604
+
2605
+ Nonetheless, you can disable automatic Java package import if needed via this Glimmer configuration option:
2606
+
2607
+ ```ruby
2608
+ Glimmer::Config.import_swt_packages = false
2609
+ ```
2610
+
2611
+ Once disabled, to import SWT Java packages manually, you may simply:
2612
+
2613
+ 1. `include Glimmer::SWT::Packages`: lazily imports all SWT Java packages to your class, lazy-loading SWT Java class constants on first reference.
2614
+
2615
+ 2. `java_import swt_package_class_string`: immediately imports a specific Java class where `swt_package_class_string` is the Java full package reference of a Java class (e.g. `java_import 'org.eclipse.swt.SWT'`)
2616
+
2617
+ Note: Glimmer relies on [`nested_imported_jruby_include_package`](https://github.com/AndyObtiva/nested_inherited_jruby_include_package), which automatically brings packages to nested-modules/nested-classes and sub-modules/sub-classes.
2618
+
2619
+ You can learn more about importing Java packages into Ruby code at this JRuby WIKI page:
2620
+
2621
+ https://github.com/jruby/jruby/wiki/CallingJavaFromJRuby
2622
+
2623
+ ### loop_max_count
2624
+
2625
+ Glimmer has infinite loop detection support.
2626
+ It can detect when an infinite loop is about to occur in method_missing and stops it.
2627
+ It detects potential infinite loops when the same keyword and args repeat more than 100 times, which is unusual in a GUI app.
2628
+
2629
+ The max limit can be changed via the `Glimmer::Config::loop_max_count=(count)` config option.
2630
+
2631
+ Infinite loop detection may be disabled altogether if needed by setting `Glimmer::Config::loop_max_count` to `-1`
2632
+
2633
+ ### excluded_keyword_checkers
2634
+
2635
+ Glimmer permits consumers to exclude keywords from DSL processing by its engine via the `excluded_keyword_checkers` config option.
2636
+
2637
+ To do so, add a proc to it that returns a boolean indicating if a keyword is excluded or not.
2638
+
2639
+ Note that this proc runs within the context of the Glimmer object (as in the object mixing in the Glimmer module), so checker can can pretend to run there with its `self` object assumption.
2640
+
2641
+ Example of keywords excluded by [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt):
2642
+
2643
+ ```ruby
2644
+ Glimmer::Config.excluded_keyword_checkers << lambda do |method_symbol, *args|
2645
+ method = method_symbol.to_s
2646
+ result = false
2647
+ result ||= method.start_with?('on_swt_') && is_a?(Glimmer::UI::CustomWidget) && respond_to?(method)
2648
+ result ||= method == 'dispose' && is_a?(Glimmer::UI::CustomWidget) && respond_to?(method)
2649
+ result ||= ['drag_source_proxy', 'drop_target_proxy'].include?(method) && is_a?(Glimmer::UI::CustomWidget)
2650
+ result ||= method == 'post_initialize_child'
2651
+ result ||= method.end_with?('=')
2652
+ result ||= ['finish_edit!', 'search', 'all_tree_items', 'depth_first_search'].include?(method) && is_a?(Glimmer::UI::CustomWidget) && body_root.respond_to?(method)
2653
+ end
2654
+ ```
2655
+
2075
2656
  ## Glimmer Style Guide
2076
2657
 
2077
2658
  - Widgets are declared with underscored lowercase versions of their SWT names minus the SWT package name.
@@ -2087,11 +2668,43 @@ This relies on Glimmer's [Multi-DSL Support](#multi-dsl-support) for building th
2087
2668
  - Custom widget body, before_body, and after_body blocks open their blocks and close them with curly braces.
2088
2669
  - Custom widgets receive additional arguments to SWT style called options. These are passed as the last argument inside the parentheses, a hash of option names pointing to values.
2089
2670
 
2671
+ ## SWT Reference
2672
+
2673
+ https://www.eclipse.org/swt/docs.php
2674
+
2675
+ Here is the SWT API:
2676
+
2677
+ https://help.eclipse.org/2019-12/nftopic/org.eclipse.platform.doc.isv/reference/api/index.html
2678
+
2679
+ Here is a visual list of SWT widgets:
2680
+
2681
+ https://www.eclipse.org/swt/widgets/
2682
+
2683
+ Here is a textual list of SWT widgets:
2684
+
2685
+ https://help.eclipse.org/2019-12/topic/org.eclipse.platform.doc.isv/guide/swt_widgets_controls.htm?cp=2_0_7_0_0
2686
+
2687
+ Here is a list of SWT style bits as used in widget declaration:
2688
+
2689
+ https://wiki.eclipse.org/SWT_Widget_Style_Bits
2690
+
2691
+ Here is a SWT style bit constant reference:
2692
+
2693
+ https://help.eclipse.org/2019-12/nftopic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/SWT.html
2694
+
2695
+ Here is an SWT Drag and Drop guide:
2696
+
2697
+ https://www.eclipse.org/articles/Article-SWT-DND/DND-in-SWT.html
2698
+
2699
+ Here is an SWT Custom Widget guide:
2700
+
2701
+ https://www.eclipse.org/articles/Article-Writing%20Your%20Own%20Widget/Writing%20Your%20Own%20Widget.htm
2702
+
2090
2703
  ## Samples
2091
2704
 
2092
- Check the [samples](samples) directory for examples on how to write Glimmer applications. To run a sample, make sure to install the `glimmer` gem first and then use the `glimmer` command to run it (alternatively, you may clone the repo, follow [CONTRIBUTING.md](CONTRIBUTING.md) instructions, and run samples locally with development glimmer command: `bin/glimmer`).
2705
+ Check the [samples](samples) directory in [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt) for examples on how to write Glimmer applications. To run a sample, make sure to install the `glimmer` gem first and then use the `glimmer` command to run it (alternatively, you may clone the repo, follow [CONTRIBUTING.md](CONTRIBUTING.md) instructions, and run samples locally with development glimmer command: `bin/glimmer`).
2093
2706
 
2094
- If you cloned the project and followed [CONTRIBUTING.md](CONTRIBUTING.md) instructions, you may run all samples at once via `samples/launch` command:
2707
+ If you cloned the project and followed [CONTRIBUTING.md](CONTRIBUTING.md) instructions, you may run all samples in [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt) at once via `samples/launch` command:
2095
2708
 
2096
2709
  ```
2097
2710
  samples/launch
@@ -2099,168 +2712,306 @@ samples/launch
2099
2712
 
2100
2713
  ### Hello Samples
2101
2714
 
2102
- For "Hello, World!" type samples, check the following:
2715
+ For hello-type simple samples, check the following.
2716
+
2717
+ #### Hello, World! Sample
2718
+
2719
+ Code:
2720
+
2721
+ [samples/hello/hello_world.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/hello/hello_world.rb)
2722
+
2723
+ Run:
2103
2724
 
2104
2725
  ```
2105
2726
  glimmer samples/hello/hello_world.rb
2106
- glimmer samples/hello/hello_browser.rb # demonstrates browser widget
2107
- glimmer samples/hello/hello_tab.rb # demonstrates tabs
2108
- glimmer samples/hello/hello_combo.rb # demonstrates combo data-binding
2109
- glimmer samples/hello/hello_list_single_selection.rb # demonstrates list single-selection data-binding
2110
- glimmer samples/hello/hello_list_multi_selection.rb # demonstrates list multi-selection data-binding
2111
- glimmer samples/hello/hello_computed.rb # demonstrates computed data-binding
2112
2727
  ```
2113
2728
 
2114
- ### Elaborate Samples
2729
+ ![Hello World](images/glimmer-hello-world.png)
2115
2730
 
2116
- For more elaborate samples, check the following:
2731
+ #### Hello, Tab!
2732
+
2733
+ Code:
2734
+
2735
+ [samples/hello/hello_tab.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/hello/hello_tab.rb)
2736
+
2737
+ Run:
2117
2738
 
2118
2739
  ```
2119
- glimmer samples/elaborate/login.rb # demonstrates basic data-binding
2120
- glimmer samples/elaborate/contact_manager.rb # demonstrates table data-binding
2121
- glimmer samples/elaborate/tic_tac_toe.rb # demonstrates a full MVC application
2740
+ glimmer samples/hello/hello_tab.rb
2122
2741
  ```
2123
2742
 
2124
- ### External Samples
2743
+ ![Hello Tab English](images/glimmer-hello-tab-english.png)
2744
+ ![Hello Tab French](images/glimmer-hello-tab-french.png)
2125
2745
 
2126
- #### Glimmer Calculator
2746
+ #### Hello, Combo!
2127
2747
 
2128
- [<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)
2748
+ This sample demonstrates combo data-binding.
2129
2749
 
2130
- [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).
2750
+ Code:
2131
2751
 
2132
- #### Gladiator
2752
+ [samples/hello/hello_combo.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/hello/hello_combo.rb)
2133
2753
 
2134
- [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer-cs-gladiator/v0.1.5/images/glimmer-gladiator.png" />](https://github.com/AndyObtiva/glimmer-cs-gladiator)
2754
+ Run:
2135
2755
 
2136
- [Gladiator](https://github.com/AndyObtiva/glimmer-cs-gladiator) (short for Glimmer Editor) is a Glimmer sample project under on-going development.
2137
- You may check it out to learn how to build a Glimmer Custom Shell gem.
2756
+ ```
2757
+ glimmer samples/hello/hello_combo.rb
2758
+ ```
2138
2759
 
2139
- ## In Production
2760
+ ![Hello Combo](images/glimmer-hello-combo.png)
2761
+ ![Hello Combo Expanded](images/glimmer-hello-combo-expanded.png)
2140
2762
 
2141
- The following production apps have been built with Glimmer:
2763
+ #### Hello, List Single Selection!
2142
2764
 
2143
- [<img alt="Math Bowling Logo" src="https://raw.githubusercontent.com/AndyObtiva/MathBowling/master/images/math-bowling-logo.png" width="40" />Math Bowling](https://github.com/AndyObtiva/MathBowling): an educational math game for elementary level kids
2765
+ This sample demonstrates list single-selection data-binding.
2144
2766
 
2145
- ## SWT Reference
2767
+ Code:
2146
2768
 
2147
- https://www.eclipse.org/swt/docs.php
2769
+ [samples/hello/hello_list_single_selection.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/hello/hello_list_single_selection.rb)
2148
2770
 
2149
- Here is the SWT API:
2771
+ Run:
2150
2772
 
2151
- https://help.eclipse.org/2019-12/nftopic/org.eclipse.platform.doc.isv/reference/api/index.html
2773
+ ```
2774
+ glimmer samples/hello/hello_list_single_selection.rb
2775
+ ```
2152
2776
 
2153
- Here is a visual list of SWT widgets:
2777
+ ![Hello List Single Selection](images/glimmer-hello-list-single-selection.png)
2154
2778
 
2155
- https://www.eclipse.org/swt/widgets/
2779
+ #### Hello, List Multi Selection!
2156
2780
 
2157
- Here is a textual list of SWT widgets:
2781
+ This sample demonstrates list multi-selection data-binding.
2158
2782
 
2159
- https://help.eclipse.org/2019-12/topic/org.eclipse.platform.doc.isv/guide/swt_widgets_controls.htm?cp=2_0_7_0_0
2783
+ Code:
2160
2784
 
2161
- Here is a list of SWT style bits as used in widget declaration:
2785
+ [samples/hello/hello_list_multi_selection.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/hello/hello_list_multi_selection.rb)
2162
2786
 
2163
- https://wiki.eclipse.org/SWT_Widget_Style_Bits
2787
+ Run:
2164
2788
 
2165
- Here is a SWT style bit constant reference:
2789
+ ```
2790
+ glimmer samples/hello/hello_list_multi_selection.rb
2791
+ ```
2166
2792
 
2167
- https://help.eclipse.org/2019-12/nftopic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/SWT.html
2793
+ ![Hello List Multi Selection](images/glimmer-hello-list-multi-selection.png)
2794
+
2795
+ #### Hello, Computed!
2796
+
2797
+ This sample demonstrates computed data-binding.
2168
2798
 
2169
- ## SWT Packages
2799
+ Code:
2170
2800
 
2171
- Glimmer automatically imports all SWT Java packages upon adding `include Glimmer` to a class or module.
2801
+ [samples/hello/hello_computed.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/hello/hello_computed.rb)
2802
+
2803
+ Run:
2172
2804
 
2173
- Here are the Java packages imported:
2174
2805
  ```
2175
- org.eclipse.swt.*
2176
- org.eclipse.swt.widgets.*
2177
- org.eclipse.swt.layout.*
2178
- org.eclipse.swt.graphics.*
2179
- org.eclipse.swt.browser.*
2180
- org.eclipse.swt.custom.*
2806
+ glimmer samples/hello/hello_computed.rb
2181
2807
  ```
2182
2808
 
2183
- This allows you to call SWT Java classes from Ruby without mentioning Java package references.
2809
+ ![Hello Browser](images/glimmer-hello-computed.png)
2184
2810
 
2185
- For example, after imports, `org.eclipse.swt.graphics.Color` can be referenced by just `Color`
2811
+ #### Hello, Message Box!
2186
2812
 
2187
- Nonetheless, you can disable automatic import if needed via this Glimmer configuration option:
2813
+ This sample demonstrates a `message_box` dialog.
2814
+
2815
+ Code:
2816
+
2817
+ [samples/hello/hello_message_box.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/hello/hello_message_box.rb)
2818
+
2819
+ Run:
2188
2820
 
2189
- ```ruby
2190
- Glimmer::Config.import_swt_packages = false
2821
+ ```
2822
+ glimmer samples/hello/hello_message_box.rb
2191
2823
  ```
2192
2824
 
2193
- To import SWT Java packages manually instead, you have 2 options:
2825
+ ![Hello Message Box](images/glimmer-hello-message-box.png)
2826
+ ![Hello Message Box Dialog](images/glimmer-hello-message-box-dialog.png)
2194
2827
 
2195
- 1. `include Glimmer::SwtPackages`: lazily imports all SWT Java packages to your class, lazy-loading SWT Java class constants on first reference.
2828
+ #### Hello, Browser!
2196
2829
 
2197
- 2. `java_import swt_package_class_string`: immediately imports a specific Java class where `swt_package_class_string` is the Java full package reference of a Java class (e.g. `java_import 'org.eclipse.swt.SWT'`)
2830
+ This sample demonstrates the `browser` widget.
2198
2831
 
2199
- Note: Glimmer relies on [`nested_imported_jruby_include_package`](https://github.com/AndyObtiva/nested_inherited_jruby_include_package), which automatically brings packages to nested-modules/nested-classes and sub-modules/sub-classes.
2832
+ Code:
2200
2833
 
2201
- You can learn more about importing Java packages into Ruby code at this JRuby WIKI page:
2834
+ [samples/hello/hello_browser.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/hello/hello_browser.rb)
2202
2835
 
2203
- https://github.com/jruby/jruby/wiki/CallingJavaFromJRuby
2836
+ Run:
2204
2837
 
2205
- ## Logging
2838
+ ```
2839
+ glimmer samples/hello/hello_browser.rb
2840
+ ```
2841
+
2842
+ ![Hello Browser](images/glimmer-hello-browser.png)
2843
+
2844
+ #### Hello, Drag and Drop!
2845
+
2846
+ This sample demonstrates drag and drop in Glimmer.
2847
+
2848
+ Code:
2849
+
2850
+ [samples/hello/hello_drag_and_drop.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/hello/hello_drag_and_drop.rb)
2851
+
2852
+ Run:
2206
2853
 
2207
- Glimmer comes with a Ruby Logger accessible via `Glimmer::Config.logger`
2208
- Its level of logging defaults to `Logger::WARN`
2209
- It may be configured to show a different level of logging as follows:
2210
- ```ruby
2211
- Glimmer::Config.enable_logging
2212
- Glimmer::Config.logger.level = Logger::DEBUG
2213
2854
  ```
2214
- This results in more verbose debugging log to `STDOUT`, which is helpful in troubleshooting Glimmer DSL syntax when needed.
2855
+ glimmer samples/hello/hello_drag_and_drop.rb
2856
+ ```
2857
+
2858
+ ![Hello Drag and Drop](images/glimmer-hello-drag-and-drop.gif)
2859
+
2860
+ #### Hello, Menu Bar!
2861
+
2862
+ This sample demonstrates menus in Glimmer.
2863
+
2864
+ Code:
2865
+
2866
+ [samples/hello/hello_menu_bar.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/hello/hello_menu_bar.rb)
2867
+
2868
+ Run:
2215
2869
 
2216
- Example log:
2217
2870
  ```
2218
- D, [2017-07-21T19:23:12.587870 #35707] DEBUG -- : method: shell and args: []
2219
- D, [2017-07-21T19:23:12.594405 #35707] DEBUG -- : ShellCommandHandler will handle command: shell with arguments []
2220
- D, [2017-07-21T19:23:12.844775 #35707] DEBUG -- : method: composite and args: []
2221
- D, [2017-07-21T19:23:12.845388 #35707] DEBUG -- : parent is a widget: true
2222
- D, [2017-07-21T19:23:12.845833 #35707] DEBUG -- : on listener?: false
2223
- D, [2017-07-21T19:23:12.864395 #35707] DEBUG -- : WidgetCommandHandler will handle command: composite with arguments []
2224
- D, [2017-07-21T19:23:12.864893 #35707] DEBUG -- : widget styles are: []
2225
- D, [2017-07-21T19:23:12.874296 #35707] DEBUG -- : method: list and args: [:multi]
2226
- D, [2017-07-21T19:23:12.874969 #35707] DEBUG -- : parent is a widget: true
2227
- D, [2017-07-21T19:23:12.875452 #35707] DEBUG -- : on listener?: false
2228
- D, [2017-07-21T19:23:12.878434 #35707] DEBUG -- : WidgetCommandHandler will handle command: list with arguments [:multi]
2229
- D, [2017-07-21T19:23:12.878798 #35707] DEBUG -- : widget styles are: [:multi]
2871
+ glimmer samples/hello/hello_menu_bar.rb
2230
2872
  ```
2231
2873
 
2232
- ## Raw JRuby Command
2874
+ ![Hello Menu Bar](images/glimmer-hello-menu-bar.png)
2875
+ ![Hello Menu Bar File Menu](images/glimmer-hello-menu-bar-file-menu.png)
2876
+ ![Hello Menu Bar History Menu](images/glimmer-hello-menu-bar-history-menu.png)
2233
2877
 
2234
- If there is a need to run Glimmer directly via the `jruby` command, you
2235
- may run the following:
2878
+ #### Hello, Pop Up Context Menu!
2879
+
2880
+ This sample demonstrates pop up context menus in Glimmer.
2881
+
2882
+ Code:
2883
+
2884
+ [samples/hello/hello_pop_up_context_menu.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/hello/hello_pop_up_context_menu.rb)
2885
+
2886
+ Run:
2236
2887
 
2237
2888
  ```
2238
- jruby -J-classpath "path_to/swt.jar" -r glimmer -S application.rb
2889
+ glimmer samples/hello/hello_pop_up_context_menu.rb
2239
2890
  ```
2240
2891
 
2241
- The `-J-classpath` option specifies the `swt.jar` file path, which can be a
2242
- manually downloaded version of SWT, or otherwise the one included in the gem. You can lookup the one included in the gem by running `jgem which glimmer` to find the gem path and then look through the `vendor` directory.
2892
+ ![Hello Pop Up Context Menu](images/glimmer-hello-pop-up-context-menu.png)
2893
+ ![Hello Pop Up Context Menu Popped Up](images/glimmer-hello-pop-up-context-menu-popped-up.png)
2243
2894
 
2244
- The `-r` option preloads (requires) the `glimmer` library in Ruby.
2895
+ ### Elaborate Samples
2245
2896
 
2246
- The `-S` option specifies a script to run.
2897
+ For more elaborate samples, check the following:
2247
2898
 
2248
- ### Mac Support
2899
+ #### Login
2249
2900
 
2250
- Mac is well supported with the `glimmer` command. However, if there is a reason to use the raw jruby command, you need to pass an extra option (`-J-XstartOnFirstThread`) to JRuby on the Mac.
2901
+ This sample demonstrates basic data-binding, password and text fields, and field enablement data-binding.
2902
+
2903
+ Code:
2904
+
2905
+ [samples/elaborate/login.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/elaborate/login.rb)
2906
+
2907
+ Run:
2251
2908
 
2252
- Example:
2253
2909
  ```
2254
- jruby -J-XstartOnFirstThread -J-classpath "path_to/swt.jar" -r glimmer -S application.rb
2910
+ glimmer samples/elaborate/login.rb
2255
2911
  ```
2256
2912
 
2913
+ ![Login](images/glimmer-login.png)
2914
+ ![Login Filled In](images/glimmer-login-filled-in.png)
2915
+ ![Login Logged In](images/glimmer-login-logged-in.png)
2916
+
2917
+ #### Tic Tac Toe Sample
2918
+
2919
+ This sample demonstrates a full MVC application, including GUI layout, text and enablement data-binding, and test-driven development (has [specs](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/spec/samples/elaborate/tic_tac_toe/board_spec.rb)).
2920
+
2921
+ Code:
2922
+
2923
+ [samples/elaborate/tic_tac_toe.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/elaborate/tic_tac_toe.rb)
2924
+
2925
+ Run:
2926
+
2927
+ ```
2928
+ glimmer samples/elaborate/tic_tac_toe.rb
2929
+ ```
2930
+
2931
+ ![Tic Tac Toe](images/glimmer-tic-tac-toe.png)
2932
+ ![Tic Tac Toe In Progress](images/glimmer-tic-tac-toe-in-progress.png)
2933
+ ![Tic Tac Toe Game Over](images/glimmer-tic-tac-toe-game-over.png)
2934
+
2935
+ #### Contact Manager Sample
2936
+
2937
+ This sample demonstrates table data-binding, sorting, filtering, GUI layout, MVP pattern, and test-driven development (has [specs](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/spec/samples/elaborate/contact_manager/contact_manager_presenter_spec.rb)).
2938
+
2939
+ Code:
2940
+
2941
+ [samples/elaborate/contact_manager.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/elaborate/contact_manager.rb)
2942
+
2943
+ Run:
2944
+
2945
+ ```
2946
+ glimmer samples/elaborate/contact_manager.rb
2947
+ ```
2948
+
2949
+ Contact Manager
2950
+
2951
+ ![Contact Manager](images/glimmer-contact-manager.png)
2952
+
2953
+ Contact Manager - Find
2954
+
2955
+ ![Contact Manager](images/glimmer-contact-manager-find.png)
2956
+
2957
+ Contact Manager - Edit Started
2958
+
2959
+ ![Contact Manager](images/glimmer-contact-manager-edit-started.png)
2960
+
2961
+ Contact Manager - Edit In Progress
2962
+
2963
+ ![Contact Manager](images/glimmer-contact-manager-edit-in-progress.png)
2964
+
2965
+ Contact Manager - Edit Done
2966
+
2967
+ ![Contact Manager](images/glimmer-contact-manager-edit-done.png)
2968
+
2969
+ ### External Samples
2970
+
2971
+ #### Glimmer Calculator
2972
+
2973
+ [<img alt="Glimmer Calculator Icon" src="https://raw.githubusercontent.com/AndyObtiva/glimmer-cs-calculator/master/glimmer-cs-calculator-icon.png" height=40 /> 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).
2974
+
2975
+ [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer-cs-calculator/master/glimmer-cs-calculator-screenshot.png" />](https://github.com/AndyObtiva/glimmer-cs-calculator)
2976
+
2977
+ #### Gladiator
2978
+
2979
+ [<img src='https://raw.githubusercontent.com/AndyObtiva/glimmer-cs-gladiator/master/images/glimmer-cs-gladiator-logo.svg' height=40 /> Gladiator](https://github.com/AndyObtiva/glimmer-cs-gladiator) (short for Glimmer Editor) is a Glimmer sample project under on-going development.
2980
+ You may check it out to learn how to build a Glimmer Custom Shell gem.
2981
+
2982
+ [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer-cs-gladiator/master/images/glimmer-gladiator.png" />](https://github.com/AndyObtiva/glimmer-cs-gladiator)
2983
+
2984
+ Gladiator is a good demonstration of:
2985
+ - MVP Pattern
2986
+ - Tree data-binding
2987
+ - List data-binding
2988
+ - Text selection data-binding
2989
+ - Tabs
2990
+ - Context menus
2991
+ - Custom Shell
2992
+ - Custom widget
2993
+
2994
+ ## In Production
2995
+
2996
+ The following production apps have been built with Glimmer.
2997
+
2998
+ ### Math Bowling
2999
+
3000
+ [<img alt="Math Bowling Logo" src="https://raw.githubusercontent.com/AndyObtiva/MathBowling/master/images/math-bowling-logo.png" width="40" />Math Bowling](https://github.com/AndyObtiva/MathBowling): an educational math game for elementary level kids
3001
+
3002
+ ### Are We There Yet?
3003
+
3004
+ [<img alt="Are We There Yet Logo" src="https://raw.githubusercontent.com/AndyObtiva/are-we-there-yet/master/are-we-there-yet-logo.svg" width="40" />Are We There Yet?](https://github.com/AndyObtiva/are-we-there-yet): A tool that helps you learn when your small projects will finish
3005
+
3006
+ If you have a Glimmer app you would like referenced here, please mention in a Pull Request.
3007
+
2257
3008
  ## Packaging & Distribution
2258
3009
 
2259
3010
  Glimmer apps may be packaged and distributed on the Mac, Windows, and Linux via these tools:
2260
3011
  - Warbler (https://github.com/jruby/warbler): Enables bundling a Glimmer app into a JAR file
2261
3012
  - javapackager (https://docs.oracle.com/javase/8/docs/technotes/tools/unix/javapackager.html): Enables packaging a JAR file as a DMG file on Mac, EXE on Windows, and multiple Linux supported formats on Linux.
2262
3013
 
2263
- Glimmer simplifies the process of Mac packaging via the `glimmer package` command. It works out of the box for any application generated by [Glimmer Scaffolding](https://github.com/AndyObtiva/glimmer/blob/master/README.md#scaffolding):
3014
+ Glimmer simplifies the process of Mac packaging via the `glimmer package` command. It works out of the box for any application generated by [Glimmer Scaffolding](#scaffolding):
2264
3015
 
2265
3016
  ```
2266
3017
  glimmer package
@@ -2423,14 +3174,30 @@ If you need live help, try to [![Join the chat at https://gitter.im/AndyObtiva/g
2423
3174
 
2424
3175
  These features have been suggested. You might see them in a future version of Glimmer. You are welcome to contribute more feature suggestions.
2425
3176
 
2426
- [TODO.md](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/TODO.md)
3177
+ [glimmer-dsl-swt/TODO.md](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/TODO.md)
3178
+
3179
+ Glimmer DSL Engine specific tasks are at:
3180
+
3181
+ [TODO.md](TODO.md)
2427
3182
 
2428
3183
  ## Change Log
2429
3184
 
3185
+ [glimmer-dsl-swt/CHANGELOG.md](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/CHANGELOG.md)
3186
+
2430
3187
  [CHANGELOG.md](CHANGELOG.md)
2431
3188
 
2432
3189
  ## Contributing
2433
3190
 
3191
+ **Contributors Wanted!**
3192
+
3193
+ If you would like to contribute to Glimmer, please study up on Glimmer and [SWT](#swt-reference), run all Glimmer [samples](#samples), and build a small sample app (perhaps from [this TODO list](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/TODO.md#samples)) to add to [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt) Hello or Elaborate samples via a Pull Request. Once done, contact me on [Chat](#chat).
3194
+
3195
+ You may apply for contributing to any of these Glimmer DSL gems whether you prefer to focus on the desktop or web:
3196
+ - [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt): Glimmer DSL for SWT (Desktop GUI)
3197
+ - [glimmer-dsl-opal](https://github.com/AndyObtiva/glimmer-dsl-opal): Glimmer DSL for Opal (Web GUI Adapter for Desktop Apps)
3198
+ - [glimmer-dsl-xml](https://github.com/AndyObtiva/glimmer-dsl-xml): Glimmer DSL for XML (& HTML)
3199
+ - [glimmer-dsl-css](https://github.com/AndyObtiva/glimmer-dsl-css): Glimmer DSL for CSS (Cascading Style Sheets)
3200
+
2434
3201
  [CONTRIBUTING.md](CONTRIBUTING.md)
2435
3202
 
2436
3203
  ## Contributors
@@ -2440,7 +3207,17 @@ These features have been suggested. You might see them in a future version of Gl
2440
3207
 
2441
3208
  [Click here to view contributor commits.](https://github.com/AndyObtiva/glimmer/graphs/contributors)
2442
3209
 
3210
+ ## Hire Me
3211
+
3212
+ If your company would like to invest fulltime in further development of the Glimmer open-source project, [hire me](https://www.linkedin.com/in/andymaleh/).
3213
+
2443
3214
  ## License
2444
3215
 
2445
- Copyright (c) 2007-2020 Andy Maleh.
2446
- See LICENSE.txt for further details.
3216
+ [MIT](https://opensource.org/licenses/MIT)
3217
+
3218
+ Copyright (c) 2007-2020 - Andy Maleh.
3219
+ See [LICENSE.txt](LICENSE.txt) for further details.
3220
+
3221
+ --
3222
+
3223
+ Glimmer logo was made by <a href="https://www.flaticon.com/authors/freepik" title="Freepik">Freepik</a> from <a href="https://www.flaticon.com/" title="Flaticon"> www.flaticon.com</a>