glimmer 0.9.3 → 0.10.2

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: 6255c2aed0be3512fb9e8e1892232ee9f8ad35efb308ea2dc814f5ff86e69265
4
- data.tar.gz: 1c6a024b3ddfed3e296644ec54ce57f38816feb2656a05f2c6daf557cde22b16
3
+ metadata.gz: f5296edf57183b7bffa288342e5c3c4ab14713dbd70af643bf8117f608314d2a
4
+ data.tar.gz: 5a9285de28140f0f7a94ed80ec9c6c597ae163a5fdce4f4ad8a060f5ad341775
5
5
  SHA512:
6
- metadata.gz: f39bf5895a97510fe0e40b463b0e77224b7ff09bd695686cf1f38fecdf0e01c1ff86a23ab25a4dbcc3b297906b905be1ad6eb5e8e9fb3fe8e985b39fbda0f80e
7
- data.tar.gz: 44068213c246dacc1763868175aba950a9bf78dc803dcb4b0269d3dd9b1ad76c9efd373cb35977b60d7bfcfbe03e8bd07b46ac32595cb89a796e6c9444ff6b0e
6
+ metadata.gz: ef36cf024e59cc0111d8f3a283c6d89134eea01390574962ef0b36ef89c75d482d6912b83fd1bfc609f40f262f72156df9ab8d8481ac41118bb799b1a718e473
7
+ data.tar.gz: 65c0d12d30f2ea846766d98bb91aa0b3ae86eaac11697532d6b3ed55a139816d0be797a94584297c40c949f8cff436dfa15cbc0176cbb652207bab452c148071
data/README.md CHANGED
@@ -1,13 +1,17 @@
1
- # <img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 /> 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;" />](https://rubygems.org/gems/glimmer) 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)
5
+ [![Maintainability](https://api.codeclimate.com/v1/badges/38fbc278022862794414/maintainability)](https://codeclimate.com/github/AndyObtiva/glimmer/maintainability)
4
6
  [![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
7
 
6
- **[Contributors Wanted!](#contributing)**
8
+ **[Contributors Wanted! (Submit a Glimmer App Sample to Get Started)](#contributing)**
7
9
 
8
10
  (The Original Glimmer Library Since 2007. Beware of Imitators!)
9
11
 
10
- 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.
12
+ [**Glimmer**](https://rubygems.org/gems/glimmer) is a native-GUI cross-platform desktop development library written in [JRuby](https://www.jruby.org/), an OS-threaded 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, thus achieving true decoupling of object oriented components and enabling developers to solve business problems (test-first) without worrying about GUI concerns. 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). [Glimmer](https://rubygems.org/gems/glimmer) also includes native-executable [packaging](#packaging--distribution) support, sorely lacking in other libraries, thus enabling the 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). Unlike libraries like TK, [Glimmer](https://rubygems.org/gems/glimmer) does not require recompilation of [Ruby](https://www.ruby-lang.org/en/). [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), [JRuby](https://www.jruby.org/), and the [Eclipse SWT library](https://www.eclipse.org/swt/).
13
+
14
+ NOTE: Glimmer is in beta mode. Please help make better by [contributing](#contributing), adopting for small or low risk projects, and providing feedback. While a lot of hard work has gone into it, it is by no means polished, and definitely has bugs waiting to be reported. The more feedback and issues you report the better.
11
15
 
12
16
  [<img src="https://covers.oreillystatic.com/images/9780596519650/lrg.jpg" width=105 /><br />
13
17
  Featured in<br />JRuby Cookbook](http://shop.oreilly.com/product/9780596519650.do)
@@ -16,13 +20,13 @@ Glimmer DSL gems:
16
20
  - [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt): Glimmer DSL for SWT (Desktop GUI)
17
21
  - [glimmer-dsl-opal](https://github.com/AndyObtiva/glimmer-dsl-opal): Glimmer DSL for Opal (Web GUI Adapter for Desktop Apps)
18
22
  - [glimmer-dsl-xml](https://github.com/AndyObtiva/glimmer-dsl-xml): Glimmer DSL for XML (& HTML)
19
- - [glimmer-dsl-css](https://github.com/AndyObtiva/glimmer-dsl-css): Glimmer DSL for CSS (Cascading Style Sheets)
23
+ - [glimmer-dsl-css](https://github.com/AndyObtiva/glimmer-dsl-css): Glimmer DSL for CSS
20
24
 
21
25
  ## Examples
22
26
 
23
27
  ### Hello, World!
24
28
 
25
- Glimmer code (from `samples/hello/hello_world.rb`):
29
+ Glimmer code (from [samples/hello/hello_world.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/hello/hello_world.rb)):
26
30
  ```ruby
27
31
  include Glimmer
28
32
 
@@ -45,28 +49,28 @@ Glimmer app:
45
49
 
46
50
  ### Tic Tac Toe
47
51
 
48
- Glimmer code (from `samples/elaborate/tic_tac_toe.rb`):
52
+ Glimmer code (from [samples/elaborate/tic_tac_toe.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/elaborate/tic_tac_toe.rb)):
49
53
 
50
54
  ```ruby
51
55
  # ...
52
- shell {
53
- text "Tic-Tac-Toe"
54
- composite {
55
- grid_layout 3, true
56
- (1..3).each { |row|
57
- (1..3).each { |column|
58
- button {
59
- layout_data :fill, :fill, true, true
60
- text bind(@tic_tac_toe_board[row, column], :sign)
61
- enabled bind(@tic_tac_toe_board[row, column], :empty)
62
- on_widget_selected {
63
- @tic_tac_toe_board.mark(row, column)
56
+ @shell = shell {
57
+ text "Tic-Tac-Toe"
58
+ composite {
59
+ grid_layout 3, true
60
+ (1..3).each { |row|
61
+ (1..3).each { |column|
62
+ button {
63
+ layout_data :fill, :fill, true, true
64
+ text bind(@tic_tac_toe_board[row, column], :sign)
65
+ enabled bind(@tic_tac_toe_board[row, column], :empty)
66
+ on_widget_selected {
67
+ @tic_tac_toe_board.mark(row, column)
68
+ }
69
+ }
64
70
  }
65
71
  }
66
72
  }
67
73
  }
68
- }
69
- }
70
74
  # ...
71
75
  ```
72
76
 
@@ -80,11 +84,99 @@ Glimmer app:
80
84
 
81
85
  ![Tic Tac Toe](images/glimmer-tic-tac-toe-in-progress.png)
82
86
 
83
- NOTE: Glimmer is in beta mode. Please help make better by [contributing](#contributing), adopting for small or low risk projects, and providing feedback.
87
+ ### Contact Manager
88
+
89
+ Glimmer code (from [samples/elaborate/contact_manager.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/elaborate/contact_manager.rb)):
90
+
91
+ ```ruby
92
+ # ...
93
+ shell {
94
+ text "Contact Manager"
95
+ composite {
96
+ composite {
97
+ grid_layout 2, false
98
+ label {text "First &Name: "}
99
+ text {
100
+ text bind(@contact_manager_presenter, :first_name)
101
+ on_key_pressed {|key_event|
102
+ @contact_manager_presenter.find if key_event.keyCode == swt(:cr)
103
+ }
104
+ }
105
+ label {text "&Last Name: "}
106
+ text {
107
+ text bind(@contact_manager_presenter, :last_name)
108
+ on_key_pressed {|key_event|
109
+ @contact_manager_presenter.find if key_event.keyCode == swt(:cr)
110
+ }
111
+ }
112
+ label {text "&Email: "}
113
+ text {
114
+ text bind(@contact_manager_presenter, :email)
115
+ on_key_pressed {|key_event|
116
+ @contact_manager_presenter.find if key_event.keyCode == swt(:cr)
117
+ }
118
+ }
119
+ composite {
120
+ grid_layout 2, false
121
+ button {
122
+ text "&Find"
123
+ on_widget_selected {
124
+ @contact_manager_presenter.find
125
+ }
126
+ }
127
+ button {
128
+ text "&List All"
129
+ on_widget_selected {
130
+ @contact_manager_presenter.list
131
+ }
132
+ }
133
+ }
134
+ }
135
+
136
+ table(:multi) { |table_proxy|
137
+ layout_data {
138
+ horizontal_alignment :fill
139
+ vertical_alignment :fill
140
+ grab_excess_horizontal_space true
141
+ grab_excess_vertical_space true
142
+ height_hint 200
143
+ }
144
+ table_column {
145
+ text "First Name"
146
+ width 80
147
+ }
148
+ table_column {
149
+ text "Last Name"
150
+ width 80
151
+ }
152
+ table_column {
153
+ text "Email"
154
+ width 200
155
+ }
156
+ items bind(@contact_manager_presenter, :results),
157
+ column_properties(:first_name, :last_name, :email)
158
+ on_mouse_up { |event|
159
+ table_proxy.edit_table_item(event.table_item, event.column_index)
160
+ }
161
+ }
162
+ }
163
+ }.open
164
+ # ...
165
+ ```
166
+
167
+ Run:
168
+
169
+ ```
170
+ glimmer samples/elaborate/contact_manager.rb
171
+ ```
172
+
173
+ Glimmer App:
174
+
175
+ ![Contact Manager](images/glimmer-contact-manager.png)
84
176
 
85
177
  ## Table of contents
86
178
 
87
- - [Glimmer - Ruby Desktop Development GUI Library](#-glimmer---ruby-desktop-development-gui-library)
179
+ - [Glimmer (Ruby Desktop Development GUI Library)](#-glimmer-ruby-desktop-development-gui-library)
88
180
  - [Examples](#examples)
89
181
  - [Hello, World!](#hello-world)
90
182
  - [Tic Tac Toe](#tic-tac-toe)
@@ -103,13 +195,21 @@ NOTE: Glimmer is in beta mode. Please help make better by [contributing](#contri
103
195
  - [Custom Widget](#custom-widget)
104
196
  - [Custom Shell Gem](#custom-shell-gem)
105
197
  - [Custom Widget Gem](#custom-widget-gem)
198
+ - [Gem Listing](#gem-listing)
199
+ - [Listing Custom Shell Gems](#listing-custom-shell-gems)
200
+ - [Listing Custom Widget Gems](#listing-custom-widget-gems)
201
+ - [Listing DSL Gems](#listing-dsl-gems)
202
+ - [Packaging](#packaging)
203
+ - [Raw JRuby Command](#raw-jruby-command)
204
+ - [Mac Support](#mac-support)
106
205
  - [Girb (Glimmer irb) Command](#girb-glimmer-irb-command)
107
- - [Glimmer DSL Syntax](#glimmer-dsl-syntax)
206
+ - [Glimmer GUI DSL Syntax](#glimmer-gui-dsl-syntax)
108
207
  - [Widgets](#widgets)
109
208
  - [Display](#display)
110
209
  - [SWT Proxies](#swt-proxies)
111
210
  - [Dialog](#dialog)
112
211
  - [Menus](#menus)
212
+ - [ScrolledComposite](#scrolledcomposite)
113
213
  - [Widget Styles](#widget-styles)
114
214
  - [Explicit SWT Style Bit](#explicit-swt-style-bit)
115
215
  - [Negative SWT Style Bits](#negative-swt-style-bits)
@@ -135,26 +235,45 @@ NOTE: Glimmer is in beta mode. Please help make better by [contributing](#contri
135
235
  - [Content/Options Example](#contentoptions-example)
136
236
  - [Custom Widget Lifecycle Hooks](#custom-widget-lifecycle-hooks)
137
237
  - [Gotcha](#gotcha)
238
+ - [Final Notes](#final-notes)
138
239
  - [Custom Shells](#custom-shells)
240
+ - [Drag and Drop](#drag-and-drop)
139
241
  - [Miscellaneous](#miscellaneous)
140
242
  - [Multi-DSL Support](#multi-dsl-support)
141
243
  - [Application Menu Items (About/Preferences)](#application-menu-items-aboutpreferences)
142
244
  - [App Name and Version](#app-name-and-version)
143
245
  - [Video Widget](#video-widget)
144
246
  - [Browser Widget](#browser-widget)
247
+ - [Glimmer Configuration](#glimmer-configuration)
248
+ - [logger](#logger)
249
+ - [import_swt_packages](#importswtpackages)
250
+ - [loop_max_count](#loopmaxcount)
145
251
  - [Glimmer Style Guide](#glimmer-style-guide)
252
+ - [SWT Reference](#swt-reference)
146
253
  - [Samples](#samples)
147
254
  - [Hello Samples](#hello-samples)
255
+ - [Hello, World! Sample](#hello-world-sample)
256
+ - [Hello, Tab!](#hello-tab)
257
+ - [Hello, Combo!](#hello-combo)
258
+ - [Hello, List Single Selection!](#hello-list-single-selection)
259
+ - [Hello, List Multi Selection!](#hello-list-multi-selection)
260
+ - [Hello, Computed!](#hello-computed)
261
+ - [Hello, Message Box!](#hello-message-box)
262
+ - [Hello, Browser!](#hello-browser)
263
+ - [Hello, Drag and Drop!](#hello-drag-and-drop)
264
+ - [Hello, Menu Bar!](#hello-menu-bar)
265
+ - [Hello, Pop Up Context Menu!](#hello-pop-up-context-menu)
148
266
  - [Elaborate Samples](#elaborate-samples)
267
+ - [Login](#login)
268
+ - [Tic Tac Toe Sample](#tic-tac-toe-sample)
269
+ - [Contact Manager](#contact-manager-sample)
149
270
  - [External Samples](#external-samples)
150
271
  - [Glimmer Calculator](#glimmer-calculator)
151
272
  - [Gladiator](#gladiator)
152
273
  - [In Production](#in-production)
153
- - [SWT Reference](#swt-reference)
154
- - [SWT Packages](#swt-packages)
155
- - [Logging](#logging)
156
- - [Raw JRuby Command](#raw-jruby-command)
157
- - [Mac Support](#mac-support)
274
+ - [Math Bowling](#math-bowling)
275
+ - [Are We There Yet?](#are-we-there-yet)
276
+ - [Garderie Rainbow Daily Agenda](#garderie-rainbow-daily-agenda)
158
277
  - [Packaging & Distribution](#packaging--distribution)
159
278
  - [Packaging Defaults](#packaging-defaults)
160
279
  - [Packaging Configuration](#packaging-configuration)
@@ -162,6 +281,7 @@ NOTE: Glimmer is in beta mode. Please help make better by [contributing](#contri
162
281
  - [Mac Application Distribution](#mac-application-distribution)
163
282
  - [Self Signed Certificate](#self-signed-certificate)
164
283
  - [Gotchas](#gotchas)
284
+ - [App Updates](#app-updates)
165
285
  - [Resources](#resources)
166
286
  - [Help](#help)
167
287
  - [Issues](#issues)
@@ -170,6 +290,7 @@ NOTE: Glimmer is in beta mode. Please help make better by [contributing](#contri
170
290
  - [Change Log](#change-log)
171
291
  - [Contributing](#contributing)
172
292
  - [Contributors](#contributors)
293
+ - [Hire Me](#hire-me)
173
294
  - [License](#license)
174
295
 
175
296
  ## Background
@@ -195,39 +316,52 @@ https://www.eclipse.org/swt/faq.php
195
316
 
196
317
  ## Pre-requisites
197
318
 
198
- - SWT 4.15 (comes included in Glimmer gem)
199
- - JRuby 9.2.11.1 (supporting Ruby 2.5.x syntax) (find at [https://www.jruby.org/download](https://www.jruby.org/download))
200
- - JDK 8 - 10 (find at [https://www.oracle.com/java/technologies/javase-downloads.html](https://www.oracle.com/java/technologies/javase-downloads.html))
201
- - (Optional) RVM is needed for [Scaffolding](#scaffolding) only (find at [https://rvm.io/](https://rvm.io/))
319
+ - SWT 4.16 (comes included in Glimmer gem)
320
+ - JRuby 9.2.13.0 (supporting Ruby 2.5.x syntax) (get via [RVM](http://rvm.io) on Mac and Linux or find at [https://www.jruby.org/download](https://www.jruby.org/download) for Windows)
321
+ - JDK 8 (find at https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html)
202
322
 
203
- On **Mac** and **Linux**, an easy way to obtain JRuby is through [RVM](http://rvm.io) by running:
323
+ To obtain JRuby through [RVM](http://rvm.io), you may run:
204
324
 
205
325
  ```bash
206
- rvm install jruby-9.2.11.1
326
+ rvm install jruby-9.2.13.0
207
327
  ```
208
328
 
209
- 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.
329
+ Glimmer might still work on other versions of Java, JRuby and SWT, but there are no guarantees, so it is best to stick to the pre-requisites outlined above.
210
330
 
211
331
  ## Setup
212
332
 
213
333
  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.
214
334
 
215
- ### Option 1: Direct Install
335
+ 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)).
336
+
337
+ If you intend to build a Glimmer app from scratch with [scaffolding](#scaffolding), pick Option 1 ([Direct Install](#option-1-direct-install)) as well.
338
+
339
+ Otherwise, Option 2 ([Bundler](#option-2-bundler)) can be followed in rare cases where you want to build an app without [scaffolding](#scaffolding).
340
+
341
+ ### Option 1: Direct Install
342
+ (Use for [Scaffolding](#scaffolding))
216
343
 
217
344
  Run this command to install directly:
218
345
  ```
219
- jgem install glimmer-dsl-swt -v 0.1.3
346
+ jgem install glimmer-dsl-swt -v 0.6.1
220
347
  ```
221
348
 
222
349
  `jgem` is JRuby's version of `gem` command.
223
350
  RVM allows running `gem` as an alias.
224
351
  Otherwise, you may also run `jruby -S gem install ...`
225
352
 
226
- ### Option 2: Bundler
353
+ 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.
354
+
355
+ 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.
356
+
357
+ Note: if you're using activerecord or activesupport, keep in mind that Glimmer unhooks ActiveSupport::Dependencies as it does not rely on it.
358
+
359
+ ### Option 2: Bundler
360
+ (Use for Manual App Creation)
227
361
 
228
362
  Add the following to `Gemfile`:
229
363
  ```
230
- gem 'glimmer-dsl-swt', '~> 0.1.3'
364
+ gem 'glimmer-dsl-swt', '~> 0.6.1'
231
365
  ```
232
366
 
233
367
  And, then run:
@@ -235,10 +369,16 @@ And, then run:
235
369
  jruby -S bundle install
236
370
  ```
237
371
 
372
+ Note: if you're using activerecord or activesupport, keep in mind that Glimmer unhooks ActiveSupport::Dependencies as it does not rely on it.
373
+
238
374
  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)
239
375
 
240
376
  ## Glimmer Command
241
377
 
378
+ The `glimmer` command allows you to run, scaffold, package, and list Glimmer applications/gems.
379
+
380
+ 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 GUI DSL Syntax](#glimmer-gui-dsl-syntax), and [Samples](#samples).
381
+
242
382
  ### Basic Usage
243
383
 
244
384
  ```
@@ -275,15 +415,20 @@ Either a single task or one or more applications may be specified.
275
415
  When a task is specified, it runs via rake. Some tasks take arguments in square brackets.
276
416
 
277
417
  Available tasks are below (you may also lookup by adding `require 'glimmer/rake_task'` in Rakefile and running rake -T):
278
- glimmer package # Package app for distribution (generating config, jar, and native files)
279
- glimmer package:config # Generate JAR config file
280
- glimmer package:jar # Generate JAR file
281
- glimmer package:native # Generate Native files (DMG/PKG/APP on the Mac)
282
- glimmer scaffold[app_name] # Scaffold a Glimmer application directory structure to begin building a new app
283
- glimmer scaffold:custom_shell[custom_shell_name,namespace] # Scaffold a Glimmer::UI::CustomShell subclass (represents a full window view) under app/views (namespace is optional)
284
- glimmer scaffold:custom_shell_gem[custom_shell_name,namespace] # Scaffold a Glimmer::UI::CustomShell subclass (represents a full window view) under its own Ruby gem + app project (namespace is required)
285
- glimmer scaffold:custom_widget[custom_widget_name,namespace] # Scaffold a Glimmer::UI::CustomWidget subclass (represents a part of a view) under app/views (namespace is optional)
286
- glimmer scaffold:custom_widget_gem[custom_widget_name,namespace] # Scaffold a Glimmer::UI::CustomWidget subclass (represents a part of a view) under its own Ruby gem project (namespace is required)
418
+ glimmer list:gems:customshell[query] # List Glimmer custom shell gems available at rubygems.org (query is optional) [alt: list:gems:cs]
419
+ glimmer list:gems:customwidget[query] # List Glimmer custom widget gems available at rubygems.org (query is optional) [alt: list:gems:cw]
420
+ glimmer list:gems:dsl[query] # List Glimmer DSL gems available at rubygems.org (query is optional)
421
+ glimmer package[type] # Package app for distribution (generating config, jar, and native files) (type is optional)
422
+ glimmer package:clean # Clean by removing "dist" and "packages" directories
423
+ glimmer package:config # Generate JAR config file
424
+ glimmer package:jar # Generate JAR file
425
+ glimmer package:lock_jars # Lock JARs
426
+ glimmer package:native[type] # Generate Native files (DMG/PKG/APP on the Mac, MSI/EXE/IMAGE on Windows, RPM/DEB on Linux) (type is optional)
427
+ glimmer scaffold[app_name] # Scaffold Glimmer application directory structure to build a new app
428
+ glimmer scaffold:customshell[name,namespace] # Scaffold Glimmer::UI::CustomShell subclass (full window view) under app/views (namespace is optional) [alt: scaffold:cs]
429
+ glimmer scaffold:customwidget[name,namespace] # Scaffold Glimmer::UI::CustomWidget subclass (part of a view) under app/views (namespace is optional) [alt: scaffold:cw]
430
+ glimmer scaffold:gem:customshell[name,namespace] # Scaffold Glimmer::UI::CustomShell subclass (full window view) under its own Ruby gem + app project (namespace is required) [alt: scaffold:gem:cs]
431
+ glimmer scaffold:gem:customwidget[name,namespace] # Scaffold Glimmer::UI::CustomWidget subclass (part of a view) under its own Ruby gem project (namespace is required) [alt: scaffold:gem:cw]
287
432
 
288
433
  When applications are specified, they are run using JRuby,
289
434
  automatically preloading the glimmer Ruby gem and SWT jar dependency.
@@ -325,7 +470,7 @@ getting you to a running and delivered state of an advanced "Hello, World!" Glim
325
470
  This should greatly facilitate building a new Glimmer app by helping you be productive and focus on app details while
326
471
  letting Glimmer scaffolding take care of initial app file structure concerns, such as adding:
327
472
  - Main application class that includes Glimmer
328
- - Main application view that houses main window content, about dialog, and preferences dialog
473
+ - Main application view that houses main window content, menu, about dialog, and preferences dialog
329
474
  - View and Model directories
330
475
  - Rakefile including Glimmer tasks
331
476
  - Version
@@ -333,7 +478,7 @@ letting Glimmer scaffolding take care of initial app file structure concerns, su
333
478
  - Icon
334
479
  - Bin file for starting application
335
480
 
336
- NOTE: Scaffolding requires RVM and currently supports Mac packaging only at the moment.
481
+ NOTE: Scaffolding supports Mac and Windows packaging at the moment.
337
482
 
338
483
  #### App
339
484
 
@@ -369,16 +514,35 @@ Created CarMaker/bin/car_maker
369
514
  ...
370
515
  ```
371
516
 
372
- Eventually, it will launch an advanced "Hello, World!" app window having the title of your application and a Mac icon.
517
+ Eventually, it will launch an advanced "Hello, World!" app window having the title of your application.
373
518
 
374
519
  ![Glimmer Scaffold App](images/glimmer-scaffolding-app.png)
375
520
 
521
+ It also comes with a boilerplate Preferences dialog.
522
+
523
+ ![Glimmer Scaffold App Preferences](images/glimmer-scaffolding-app-preferences.png)
524
+
525
+ Here is a Windows scaffolded app called Greeter:
526
+
527
+ ![Glimmer Scaffold App Windows](images/glimmer-scaffolding-app-windows.png)
528
+
529
+ Here is the Windows version of the boilerplate Preferences dialog.
530
+
531
+ ![Glimmer Scaffold App Windows Preferences](images/glimmer-scaffolding-app-windows-preferences.png)
532
+
533
+
376
534
  #### Custom Shell
377
535
 
378
536
  To scaffold a Glimmer custom shell (full window view) for an existing Glimmer app, run the following command:
379
537
 
380
538
  ```
381
- glimmer scaffold:custom_shell[custom_shell_name]
539
+ glimmer scaffold:customshell[name]
540
+ ```
541
+
542
+ Or the following alternative abbreviation:
543
+
544
+ ```
545
+ glimmer scaffold:cs[name]
382
546
  ```
383
547
 
384
548
  #### Custom Widget
@@ -386,13 +550,19 @@ glimmer scaffold:custom_shell[custom_shell_name]
386
550
  To scaffold a Glimmer custom widget (part of a view) for an existing Glimmer app, run the following command:
387
551
 
388
552
  ```
389
- glimmer scaffold:custom_widget[custom_widget_name]
553
+ glimmer scaffold:customwidget[name]
554
+ ```
555
+
556
+ Or the following alternative abbreviation:
557
+
558
+ ```
559
+ glimmer scaffold:cw[name]
390
560
  ```
391
561
 
392
562
  #### Custom Shell Gem
393
563
 
394
564
  Custom shell gems are self-contained Glimmer apps as well as reusable custom shells.
395
- They have everything scaffolded Glimmer apps come with in addition to gem content like a Jeweler Rakefile that can build gemspec and release gems.
565
+ They have everything scaffolded Glimmer apps come with in addition to gem content like a [jeweler](https://github.com/technicalpickles/jeweler) Rakefile that can build gemspec and release gems.
396
566
  Unlike scaffolded Glimmer apps, custom shell gem content lives under the `lib` directory (not `app`).
397
567
  They can be packaged as both a native executable (e.g. Mac DMG/PKG/APP) and a Ruby gem.
398
568
  Of course, you can just build a Ruby gem and disregard native executable packaging if you do not need it.
@@ -400,7 +570,13 @@ Of course, you can just build a Ruby gem and disregard native executable packagi
400
570
  To scaffold a Glimmer custom shell gem (full window view distributed as a Ruby gem), run the following command:
401
571
 
402
572
  ```
403
- glimmer scaffold:custom_shell_gem[custom_shell_name, namespace]
573
+ glimmer scaffold:gem:customshell[name,namespace]
574
+ ```
575
+
576
+ Or the following alternative abbreviation:
577
+
578
+ ```
579
+ glimmer scaffold:gem:cs[name,namespace]
404
580
  ```
405
581
 
406
582
  It is important to specify a namespace to avoid having your gem clash with existing gems.
@@ -419,16 +595,157 @@ Examples:
419
595
  To scaffold a Glimmer custom widget gem (part of a view distributed as a Ruby gem), run the following command:
420
596
 
421
597
  ```
422
- glimmer scaffold:custom_widget_gem[custom_widget_name, namespace]
598
+ glimmer scaffold:gem:customwidget[name,namespace]
599
+ ```
600
+
601
+ Or the following alternative abbreviation:
602
+
603
+ ```
604
+ glimmer scaffold:gem:cw[name,namespace]
423
605
  ```
424
606
 
607
+
425
608
  It is important to specify a namespace to avoid having your gem clash with existing gems.
426
609
 
427
610
  The Ruby gem name will follow the convention "glimmer-cw-customwidgetname-namespace" (the 'cw' is for Custom Widget)
428
611
 
429
612
  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)
430
613
 
431
- Example: [https://github.com/AndyObtiva/glimmer-cw-video](https://github.com/AndyObtiva/glimmer-cw-video)
614
+ Examples:
615
+
616
+ - [glimmer-cw-video](https://github.com/AndyObtiva/glimmer-cw-video): Video Widget
617
+ - [glimmer-cw-cdatetime-nebula](https://github.com/AndyObtiva/glimmer-cw-cdatetime-nebula): Nebula CDateTime Widget
618
+
619
+ ### Gem Listing
620
+
621
+ 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).
622
+
623
+ #### Listing Custom Shell Gems
624
+
625
+ 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):
626
+
627
+ ```
628
+ glimmer list:gems:customshell[query]
629
+ ```
630
+
631
+ Or the following alternative abbreviation:
632
+
633
+ ```
634
+ glimmer list:gems:cs[query]
635
+ ```
636
+
637
+ Example:
638
+
639
+ ```
640
+ glimmer list:gems:cs
641
+ ```
642
+
643
+ Output:
644
+
645
+ ```
646
+
647
+ Glimmer Custom Shell Gems at rubygems.org:
648
+
649
+ Name Gem Version Author Description
650
+
651
+ Calculator glimmer-cs-calculator 1.0.1 Andy Maleh Calculator - Glimmer Custom Shell
652
+ Gladiator glimmer-cs-gladiator 0.2.3 Andy Maleh Gladiator (Glimmer Editor) - Glimmer Custom Shell
653
+
654
+ ```
655
+
656
+ #### Listing Custom Widget Gems
657
+
658
+ 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):
659
+
660
+ ```
661
+ glimmer list:gems:customwidget[query]
662
+ ```
663
+
664
+ Or the following alternative abbreviation:
665
+
666
+ ```
667
+ glimmer list:gems:cw[query]
668
+ ```
669
+
670
+ Example:
671
+
672
+ Check if there is a custom video widget for Glimmer.
673
+
674
+ ```
675
+ glimmer list:gems:cw[video]
676
+ ```
677
+
678
+ Output:
679
+
680
+ ```
681
+
682
+ Glimmer Custom Widget Gems matching [video] at rubygems.org:
683
+
684
+ Name Gem Version Author Description
685
+
686
+ Video glimmer-cw-video 0.1.3 Andy Maleh Glimmer Custom Widget - Video
687
+
688
+ ```
689
+
690
+ #### Listing DSL Gems
691
+
692
+ 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):
693
+
694
+ ```
695
+ glimmer list:gems:dsl[query]
696
+ ```
697
+
698
+ Example:
699
+
700
+ ```
701
+ glimmer list:gems:dsl
702
+ ```
703
+
704
+ Output:
705
+
706
+ ```
707
+
708
+ Glimmer DSL Gems at rubygems.org:
709
+
710
+ Name Gem Version Author Description
711
+
712
+ Css glimmer-dsl-css 0.2.0 AndyMaleh Glimmer DSL for CSS
713
+ Opal glimmer-dsl-opal 0.1.0 AndyMaleh Glimmer DSL for Opal
714
+ Swt glimmer-dsl-swt 0.6.1 AndyMaleh Glimmer DSL for SWT
715
+ Xml glimmer-dsl-xml 0.2.0 AndyMaleh Glimmer DSL for XML
716
+
717
+ ```
718
+
719
+ ### Packaging
720
+
721
+ Glimmer packaging tasks are detailed under [Packaging & Distribution](#packaging--distribution).
722
+
723
+ ### Raw JRuby Command
724
+
725
+ If there is a need to run Glimmer directly via the `jruby` command, you
726
+ may run the following:
727
+
728
+ ```
729
+ jruby -J-classpath "path_to/swt.jar" -r glimmer -S application.rb
730
+ ```
731
+
732
+ The `-J-classpath` option specifies the `swt.jar` file path, which can be a
733
+ 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.
734
+
735
+ The `-r` option preloads (requires) the `glimmer` library in Ruby.
736
+
737
+ The `-S` option specifies a script to run.
738
+
739
+ #### Mac Support
740
+
741
+ The Mac is well supported with the `glimmer` command. The advice below is not needed if you are using it.
742
+
743
+ 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).
744
+
745
+ Example:
746
+ ```
747
+ jruby -J-XstartOnFirstThread -J-classpath "path_to/swt.jar" -r glimmer -S application.rb
748
+ ```
432
749
 
433
750
  ## Girb (Glimmer irb) Command
434
751
 
@@ -448,17 +765,28 @@ Watch out for hands-on examples in this README indicated by "you may copy/paste
448
765
 
449
766
  Keep in mind that all samples live under [https://github.com/AndyObtiva/glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt)
450
767
 
451
- ## Glimmer DSL Syntax
768
+ ## Glimmer GUI DSL Syntax
452
769
 
453
- Glimmer DSL syntax consists of static keywords and dynamic keywords to build and bind user-interface objects.
770
+ Glimmer is mainly a GUI DSL with a lightweight visual syntax that makes it easy to visualize the nesting of widgets in the GUI hierarchy tree.
454
771
 
455
- Static keywords are pre-identified keywords in the Glimmer DSL, such as `shell`, `rgb`, and `bind`.
772
+ The GUI DSL intentionally avoids overly verbose syntax, requiring as little declarative code as possible to describe what GUI to render, how to style it, and what properties to data-bind to the Models.
456
773
 
457
- Dynamic keywords are dynamically figured out from available SWT widgets, custom widgets, and properties. Examples are: `label`, `combo`, and `text`.
774
+ As such, it breaks off from Ruby's convention of using `do end` for multi-line blocks, opting instead for the lightweight and visual `{ }` curly brace blocks everywhere inside the GUI DSL. More details about Glimmer's syntax conventions may be found in the [Glimmer Style Guide](#glimmer-style-guide)
458
775
 
459
- 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.
776
+ Glimmer DSL syntax consists mainly of:
777
+ - keywords (e.g. `table` for a table widget)
778
+ - style/args (e.g. :multi as in `table(:multi)` for a multi-line selection table widget)
779
+ - content (e.g. `{ table_column { text 'Name'} }` as in `table(:multi) { table_column { text 'name'} }` for a multi-line selection table widget with a table column having header text property `'Name'` as content)
460
780
 
461
- For example, if a project adds this custom SWT library:
781
+ Glimmer keywords may be static or dynamic.
782
+
783
+ Static keywords are pre-identified keywords in the Glimmer DSL, such as `shell`, `display`, `message_box`, `async_exec`, `sync_exec`, and `bind`.
784
+
785
+ Dynamic keywords are dynamically figured out from currently imported (aka required/loaded) SWT widgets, custom widgets, and widget properties. Examples are: `label`, `combo`, and `list` for widgets and `enabled`, `text`, and `selection` for properties.
786
+
787
+ 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.
788
+
789
+ For example, if a project adds this custom Java SWT library:
462
790
 
463
791
  https://www.eclipse.org/nebula/widgets/cdatetime/cdatetime.php?page=operation
464
792
 
@@ -474,9 +802,9 @@ https://www.eclipse.org/swt/widgets/
474
802
 
475
803
  This screenshot taken from the link above should give a glimpse of how SWT widgets look and feel:
476
804
 
477
- ![SWT Widgets](images/glimmer-swt-widgets.png)
805
+ [![SWT Widgets](images/glimmer-swt-widgets.png)](https://www.eclipse.org/swt/widgets/)
478
806
 
479
- In Glimmer DSL, widgets are declared with lowercase underscored names mirroring their SWT names minus the package name:
807
+ In Glimmer DSL, widgets are declared with lowercase underscored names mirroring their SWT names minus the package name. For example, here are some Glimmer widgets and their SWT counterparts:
480
808
 
481
809
  - `shell` instantiates `org.eclipse.swt.widgets.Shell`
482
810
  - `text` instantiates `org.eclipse.swt.widgets.Text`
@@ -492,8 +820,8 @@ In Glimmer DSL, widgets are declared with lowercase underscored names mirroring
492
820
  - `list` instantiates `org.eclipse.swt.widgets.List`
493
821
 
494
822
  Every **widget** is sufficiently declared by name, but may optionally be accompanied with:
495
- - SWT **style** ***argument*** wrapped by parenthesis according to [Glimmer Style Guide](#glimmer-style-guide) (see [next section](#widget-styles) for details).
496
- - Ruby block containing **properties** (widget attributes) and **content** (nested widgets)
823
+ - SWT **style**/***arguments*** wrapped by parenthesis according to [Glimmer Style Guide](#glimmer-style-guide) (see [next section](#widget-styles) for details).
824
+ - Ruby block containing **content**, which may be **properties** (e.g. `enabled false`) or nested **widgets** (e.g. `table_column` nested inside `table`)
497
825
 
498
826
  For example, if we were to revisit `samples/hello/hello_world.rb` above (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
499
827
 
@@ -575,6 +903,8 @@ shell {
575
903
  }.open
576
904
  ```
577
905
 
906
+ If you are new to Glimmer, you have learned enough to start running some [samples](#samples). Go ahead and run all Glimmer [samples](#samples), and come back to read the rest in any order you like since this material is more organized like a reference.
907
+
578
908
  #### Display
579
909
 
580
910
  SWT Display is a singleton in Glimmer. It is used in SWT to represent your display device, allowing you to manage GUI globally
@@ -586,7 +916,7 @@ automatically uses the display created earlier without having to explicitly hook
586
916
  ```ruby
587
917
  @display = display {
588
918
  cursor_location 300, 300
589
- on_event_keydown {
919
+ on_swt_keydown {
590
920
  # ...
591
921
  }
592
922
  # ...
@@ -638,27 +968,49 @@ Example (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
638
968
  @shell.open
639
969
  ```
640
970
 
641
- ##### `#swt_widget`
971
+ ##### `message_box`
642
972
 
643
- 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.
973
+ 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.
644
974
 
645
975
  Example (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
646
976
 
647
977
  ```ruby
978
+ include Glimmer
979
+
648
980
  @shell = shell {
981
+ text 'Hello, Message Box!'
649
982
  button {
650
- text "Press Me"
983
+ text 'Please Click To Win a Surprise'
651
984
  on_widget_selected {
652
- message_box = MessageBox.new(@shell.swt_widget) # passing SWT Shell widget
653
- message_box.setText("Surprise")
654
- message_box.setMessage("You have won $1,000,000!")
655
- message_box.open
985
+ message_box(@shell) {
986
+ text 'Surprise'
987
+ message "Congratulations!\n\nYou have won $1,000,000!"
988
+ }.open
656
989
  }
657
990
  }
658
991
  }
659
992
  @shell.open
660
993
  ```
661
994
 
995
+ ![Hello Message Box Dialog](images/glimmer-hello-message-box-dialog.png)
996
+
997
+ It is also possible to use `message_box` even before instantiating the first `shell` ([Glimmer](https://rubygems.org/gems/glimmer) builds a throwaway `shell` parent automatically for it):
998
+
999
+ Example (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
1000
+
1001
+ ```ruby
1002
+ include Glimmer
1003
+
1004
+ message_box {
1005
+ text 'Greeting'
1006
+ message "Hello, World!"
1007
+ }.open
1008
+ ```
1009
+
1010
+ ##### `#swt_widget`
1011
+
1012
+ 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.
1013
+
662
1014
  ##### Shell widget proxy methods
663
1015
 
664
1016
  Shell widget proxy has extra methods specific to SWT Shell:
@@ -674,6 +1026,24 @@ Shell widget proxy has extra methods specific to SWT Shell:
674
1026
  - `#pack`: Packs contained widgets using SWT's `Shell#pack` method
675
1027
  - `#pack_same_size`: Packs contained widgets without changing shell's size when widget sizes change
676
1028
 
1029
+ ##### Shell Icon
1030
+
1031
+ To set the shell icon, simply set the `image` property under the `shell` widget. This shows up in the operating system toolbar and app-switcher (e.g. CMD+TAB) (and application window top-left corner in Windows)
1032
+
1033
+ Example:
1034
+
1035
+ ```ruby
1036
+ shell {
1037
+ # ...
1038
+ image 'path/to/image.png'
1039
+ # ...
1040
+ }
1041
+ ```
1042
+
1043
+ ###### Shell Icon Tip for Packaging on Windows
1044
+
1045
+ When setting shell icon for a [packaged](#packaging--distribution) app, which has a JAR file at its core, you can reference the `ico` file that ships with the app by going one level up (e.g. `'../AppName.ico'`)
1046
+
677
1047
  #### Dialog
678
1048
 
679
1049
  Dialog is a variation on Shell. It is basically a shell that is modal (blocks what's behind it) and belongs to another shell. It only has a close button.
@@ -686,7 +1056,7 @@ Glimmer DSL provides support for SWT Menu and MenuItem widgets.
686
1056
 
687
1057
  There are 2 main types of menus in SWT:
688
1058
  - Menu Bar (shows up on top)
689
- - Pop Up Menu (shows up when right-clicking a widget)
1059
+ - Pop Up Context Menu (shows up when right-clicking a widget)
690
1060
 
691
1061
  Underneath both types, there can be a 3rd menu type called Drop Down.
692
1062
 
@@ -694,39 +1064,63 @@ Glimmer provides special support for Drop Down menus as it automatically instant
694
1064
 
695
1065
  The ampersand symbol indicates the keyboard shortcut key for the menu item (e.g. '&Help' can be triggered on Windows by hitting ALT+H)
696
1066
 
697
- Example [Menu Bar] (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
1067
+ Example of a Menu Bar (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
698
1068
 
699
1069
  ```ruby
700
- shell {
1070
+ shell { |shell_proxy|
1071
+ text 'Hello, Menu Bar!'
1072
+ grid_layout
1073
+ label(:center) {
1074
+ font height: 16
1075
+ text 'Check Out The File Menu and History Menu in The Menu Bar Above!'
1076
+ }
701
1077
  menu_bar {
702
1078
  menu {
703
- text "&File"
1079
+ text '&File'
704
1080
  menu_item {
705
- text "E&xit"
1081
+ text 'E&xit'
706
1082
  }
707
1083
  menu_item(0) {
708
- text "&New"
1084
+ text '&New'
1085
+ on_widget_selected {
1086
+ message_box(shell_proxy) {
1087
+ text 'New File'
1088
+ message 'New File Contents'
1089
+ }.open
1090
+ }
709
1091
  }
710
1092
  menu(1) {
711
- text "&Options"
1093
+ text '&Options'
712
1094
  menu_item(:radio) {
713
- text "Option 1"
1095
+ text 'Option 1'
714
1096
  }
715
1097
  menu_item(:separator)
716
1098
  menu_item(:check) {
717
- text "Option 3"
1099
+ text 'Option 3'
718
1100
  }
719
1101
  }
720
1102
  }
721
1103
  menu {
722
- text "&History"
1104
+ text '&History'
723
1105
  menu {
724
- text "&Recent"
1106
+ text '&Recent'
725
1107
  menu_item {
726
- text "File 1"
1108
+ text 'File 1'
1109
+ on_widget_selected {
1110
+ message_box(shell_proxy) {
1111
+ text 'File 1'
1112
+ message 'File 1 Contents'
1113
+ }.open
1114
+ }
727
1115
  }
728
1116
  menu_item {
729
- text "File 2"
1117
+ text 'File 2'
1118
+ on_widget_selected {
1119
+ message_box(shell_proxy) {
1120
+ text 'File 2'
1121
+ message 'File 2 Contents'
1122
+ }.open
1123
+ }
730
1124
  }
731
1125
  }
732
1126
  }
@@ -734,22 +1128,37 @@ shell {
734
1128
  }.open
735
1129
  ```
736
1130
 
737
- Example [Pop Up Menu] (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
1131
+ Example of a Pop Up Context Menu (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
738
1132
 
739
1133
  ```ruby
740
- shell {
1134
+ shell { |shell_proxy|
1135
+ text 'Hello, Pop Up Context Menu!'
1136
+ grid_layout
741
1137
  label {
742
- text 'Right-Click Me'
1138
+ font height: 16
1139
+ text 'Right-Click To Pop Up a Context Menu'
743
1140
  menu {
744
1141
  menu {
745
1142
  text '&History'
746
1143
  menu {
747
- text "&Recent"
1144
+ text '&Recent'
748
1145
  menu_item {
749
- text "File 1"
1146
+ text 'File 1'
1147
+ on_widget_selected {
1148
+ message_box(shell_proxy) {
1149
+ text 'File 1'
1150
+ message 'File 1 Contents'
1151
+ }.open
1152
+ }
750
1153
  }
751
1154
  menu_item {
752
- text "File 2"
1155
+ text 'File 2'
1156
+ on_widget_selected {
1157
+ message_box(shell_proxy) {
1158
+ text 'File 2'
1159
+ message 'File 2 Contents'
1160
+ }.open
1161
+ }
753
1162
  }
754
1163
  }
755
1164
  }
@@ -758,6 +1167,13 @@ shell {
758
1167
  }.open
759
1168
  ```
760
1169
 
1170
+ #### ScrolledComposite
1171
+
1172
+ Glimmer provides smart defaults for the `scrolled_composite` widget by:
1173
+ - Automatically setting the nested widget as its content (meaning use can just like a plain old `composite` to add scrolling)
1174
+ - 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 )
1175
+ - Automatically setting the expand horizontal and expand vertical SWT properties to `true`
1176
+
761
1177
  ### Widget Styles
762
1178
 
763
1179
  SWT widgets receive `SWT` styles in their constructor as per this guide:
@@ -803,7 +1219,7 @@ text(:center, :border) { # Multiple SWT styles separated by comma
803
1219
  Glimmer ships with SWT style **smart defaults** so you wouldn't have to set them yourself most of the time (albeit you can always override them):
804
1220
 
805
1221
  - `text(:border)`
806
- - `table(:border)`
1222
+ - `table(:border, :virtual, :full_selection)`
807
1223
  - `tree(:border, :virtual, :v_scroll, :h_scroll)`
808
1224
  - `spinner(:border)`
809
1225
  - `list(:border, :v_scroll)`
@@ -879,7 +1295,7 @@ button {
879
1295
 
880
1296
  In the above example, the `text` widget `enabled` property was data-bound to `#empty` method on `@tic_tac_toe_board.box(row, column)` (learn more about data-binding below)
881
1297
 
882
- #### Colors
1298
+ #### Color
883
1299
 
884
1300
  Colors make up a subset of widget properties. SWT accepts color objects created with RGB (Red Green Blue) or RGBA (Red Green Blue Alpha). Glimmer supports constructing color objects using the `rgb` and `rgba` DSL keywords.
885
1301
 
@@ -928,7 +1344,7 @@ Example:
928
1344
  color(:black).swt_color # returns SWT Color object
929
1345
  ```
930
1346
 
931
- #### Fonts
1347
+ #### Font
932
1348
 
933
1349
  Fonts are represented in Glimmer as a hash of name, height, and style keys.
934
1350
 
@@ -957,7 +1373,34 @@ label {
957
1373
  # ...
958
1374
  ```
959
1375
 
960
- ### Layouts
1376
+ You may simply use the standalone `font` keyword without nesting in a parent if there is a need to build a Font object to use in manual SWT programming outside of widget font property setting.
1377
+
1378
+ Example:
1379
+
1380
+ ```ruby
1381
+ @font = font(name: 'Arial', height: 36, style: :normal)
1382
+ ```
1383
+
1384
+ ### Cursor
1385
+
1386
+ SWT widget `cursor` property represents the mouse cursor you see on the screen when you hover over that widget.
1387
+
1388
+ The `Display` class provides a way to obtain standard system cursors matching of the SWT style constants starting with prefix `CURSOR_` (e.g. `SWT::CURSOR_HELP` shows a question mark mouse cursor)
1389
+
1390
+ Glimmer provides an easier way to obtain and set `cursor` property on a widget by simply mentioning the SWT style constant as an abbreviated symbol excluding the "CURSOR_" suffix.
1391
+
1392
+ Example:
1393
+
1394
+ ```ruby
1395
+ shell {
1396
+ minimum_size 128, 128
1397
+ cursor :appstarting
1398
+ }
1399
+ ```
1400
+
1401
+ This sets the shell `cursor` to that of `SWT::CURSOR_APPSTARTING`
1402
+
1403
+ ### Layout
961
1404
 
962
1405
  Glimmer lays widgets out visually using SWT layouts, which can only be set on composite widget and subclasses.
963
1406
 
@@ -1008,7 +1451,7 @@ Here is a more sophisticated example taken from [hello_computed.rb](samples/hell
1008
1451
 
1009
1452
  ```ruby
1010
1453
  shell {
1011
- text "Hello Computed"
1454
+ text 'Hello, Computed!'
1012
1455
  composite {
1013
1456
  grid_layout {
1014
1457
  num_columns 2
@@ -1016,44 +1459,44 @@ shell {
1016
1459
  horizontal_spacing 20
1017
1460
  vertical_spacing 10
1018
1461
  }
1019
- label {text "First &Name: "}
1462
+ label {text 'First &Name: '}
1020
1463
  text {
1021
1464
  text bind(@contact, :first_name)
1022
1465
  layout_data {
1023
- horizontalAlignment :fill
1024
- grabExcessHorizontalSpace true
1466
+ horizontal_alignment :fill
1467
+ grab_excess_horizontal_space true
1025
1468
  }
1026
1469
  }
1027
- label {text "&Last Name: "}
1470
+ label {text '&Last Name: '}
1028
1471
  text {
1029
1472
  text bind(@contact, :last_name)
1030
1473
  layout_data {
1031
- horizontalAlignment :fill
1032
- grabExcessHorizontalSpace true
1474
+ horizontal_alignment :fill
1475
+ grab_excess_horizontal_space true
1033
1476
  }
1034
1477
  }
1035
- label {text "&Year of Birth: "}
1478
+ label {text '&Year of Birth: '}
1036
1479
  text {
1037
1480
  text bind(@contact, :year_of_birth)
1038
1481
  layout_data {
1039
- horizontalAlignment :fill
1040
- grabExcessHorizontalSpace true
1482
+ horizontal_alignment :fill
1483
+ grab_excess_horizontal_space true
1041
1484
  }
1042
1485
  }
1043
- label {text "Name: "}
1486
+ label {text 'Name: '}
1044
1487
  label {
1045
1488
  text bind(@contact, :name, computed_by: [:first_name, :last_name])
1046
1489
  layout_data {
1047
- horizontalAlignment :fill
1048
- grabExcessHorizontalSpace true
1490
+ horizontal_alignment :fill
1491
+ grab_excess_horizontal_space true
1049
1492
  }
1050
1493
  }
1051
- label {text "Age: "}
1494
+ label {text 'Age: '}
1052
1495
  label {
1053
1496
  text bind(@contact, :age, on_write: :to_i, computed_by: [:year_of_birth])
1054
1497
  layout_data {
1055
- horizontalAlignment :fill
1056
- grabExcessHorizontalSpace true
1498
+ horizontal_alignment :fill
1499
+ grab_excess_horizontal_space true
1057
1500
  }
1058
1501
  }
1059
1502
  }
@@ -1196,6 +1639,10 @@ Example from [samples/hello/hello_combo.rb](samples/hello_combo.rb) sample (you
1196
1639
 
1197
1640
  #### Combo
1198
1641
 
1642
+ 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.
1643
+
1644
+ When data-binding a `combo` widget, Glimmer can automatically deduce available options from data-bound model by convention: `{attribute_name}_options` method.
1645
+
1199
1646
  ![Hello Combo](images/glimmer-hello-combo.png)
1200
1647
 
1201
1648
  ![Hello Combo](images/glimmer-hello-combo-expanded.png)
@@ -1237,7 +1684,7 @@ end
1237
1684
  HelloCombo.new.launch
1238
1685
  ```
1239
1686
 
1240
- `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.
1687
+ `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.
1241
1688
 
1242
1689
  #### List
1243
1690
 
@@ -1351,6 +1798,9 @@ shell {
1351
1798
  }
1352
1799
  items bind(group, :people), column_properties(:name, :age, :adult)
1353
1800
  selection bind(group, :selected_person)
1801
+ on_mouse_up { |event|
1802
+ @table.edit_table_item(event.table_item, event.column_index)
1803
+ }
1354
1804
  }
1355
1805
  }
1356
1806
  ```
@@ -1358,6 +1808,7 @@ shell {
1358
1808
  The code above includes two data-bindings:
1359
1809
  - 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.
1360
1810
  - 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)
1811
+ - 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.)
1361
1812
 
1362
1813
  Additionally, Table `items` data-binding automatically stores each node model unto the SWT TableItem object via `setData` method. This enables things like searchability.
1363
1814
 
@@ -1377,38 +1828,99 @@ This automatically leverages the SWT TableEditor custom class behind the scenes,
1377
1828
  passed table item text into something else.
1378
1829
  It automatically persists the change to `items` data-bound model on ENTER/FOCUS-OUT or cancels on ESC/NO-CHANGE.
1379
1830
 
1380
- #### Tree
1381
-
1382
- The SWT Tree widget visualizes a tree data-structure, such as an employment or composition hierarchy.
1383
-
1384
- To data-bind a Tree, you need the root model, the children querying method, and the text display attribute on each child.
1831
+ ##### Table Sorting
1385
1832
 
1386
- This involves using the `bind` keyword mentioned above in addition to a special `tree_properties` keyword that takes the children and text attribute methods.
1833
+ Glimmer automatically adds sorting support to the SWT `Table` widget.
1387
1834
 
1388
- Example:
1835
+ Check out the [Contact Manager](#contact-manager) sample for an example.
1836
+ You may click on any column and it will sort by ascending order first and descending if you click again.
1389
1837
 
1390
- ```ruby
1391
- shell {
1392
- @tree = tree {
1393
- items bind(company, :owner), tree_properties(children: :coworkers, text: :name)
1394
- selection bind(company, :selected_coworker)
1395
- }
1396
- }
1397
- ```
1838
+ Glimmer automatic table sorting supports `String`, `Integer`, and `Float` columns out of the box as well as any column data that is comparable.
1398
1839
 
1399
- The code above includes two data-bindings:
1400
- - Tree `items`, which first bind to the root node (company.owner), and then dig down via `coworkers` `children` method, using the `name` `text` attribute for displaying each tree item.
1401
- - Tree `selection`, which binds the single tree item selected by the user to the attribute denoted by the `bind` keyword
1840
+ 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`.
1402
1841
 
1403
- Additionally, Tree `items` data-binding automatically stores each node model unto the SWT TreeItem object via `setData` method. This enables things like searchability.
1842
+ Should you have a special data type that could not be compared automatically, Glimmer offers the following 3 alternatives for custom sorting:
1843
+ - `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`).
1844
+ - `sort_by(&block)`: this works just like Ruby `Enumerable` `sort_by`. The block receives the table column data as argument.
1845
+ - `sort(&comparator)`: this works just like Ruby `Enumerable` `sort`. The comparator block receives two objects from the table column data.
1404
1846
 
1405
- The tree widget in Glimmer is represented by a subclass of `WidgetProxy` called `TreeProxy`.
1406
- TreeProxy includes a `depth_first_search` method that takes a block to look for a tree item.
1847
+ 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)
1407
1848
 
1408
1849
  Example:
1409
1850
 
1410
1851
  ```ruby
1411
- found_array = @tree.depth_first_search { |tree_item| tree_item.getData == company.owner }
1852
+ # ...
1853
+ table {
1854
+ table_column {
1855
+ text 'Task'
1856
+ width 120
1857
+ }
1858
+ table_column {
1859
+ text 'Project'
1860
+ width 120
1861
+ }
1862
+ table_column {
1863
+ text 'Duration (hours)'
1864
+ width 120
1865
+ sort_property :duration_in_hours
1866
+ }
1867
+ table_column {
1868
+ text 'Priority'
1869
+ width 120
1870
+ sort_by { |value| ['High', 'Medium', 'Low'].index(value) }
1871
+ }
1872
+ table_column {
1873
+ text 'Start Date'
1874
+ width 120
1875
+ sort { |d1, d2| d1.to_date <=> d2.to_date }
1876
+ }
1877
+ additional_sort_properties :project_name, :duration_in_hours, :name
1878
+ items bind(Task, :list), column_properties(:name, :project_name, :duration, :priority, :start_date)
1879
+ # ...
1880
+ }
1881
+ # ...
1882
+ ```
1883
+
1884
+ Here is an explanation of the example above:
1885
+ - Task and Project table columns are data-bound to the `:name` and `:project_name` properties and sorted through them automatically
1886
+ - Task Duration table column is data-bound to the `:duration` property, but sorted via the `:duration_in_hours` property instead
1887
+ - Task Priority table column has a custom sort_by block
1888
+ - Task Start Date table column has a custom sort comparator block
1889
+ - Additional (secondary) sort properties are applied when sorting by Task, Project, or Duration in the order specified
1890
+
1891
+
1892
+ #### Tree
1893
+
1894
+ The SWT Tree widget visualizes a tree data-structure, such as an employment or composition hierarchy.
1895
+
1896
+ To data-bind a Tree, you need the root model, the children querying method, and the text display attribute on each child.
1897
+
1898
+ This involves using the `bind` keyword mentioned above in addition to a special `tree_properties` keyword that takes the children and text attribute methods.
1899
+
1900
+ Example:
1901
+
1902
+ ```ruby
1903
+ shell {
1904
+ @tree = tree {
1905
+ items bind(company, :owner), tree_properties(children: :coworkers, text: :name)
1906
+ selection bind(company, :selected_coworker)
1907
+ }
1908
+ }
1909
+ ```
1910
+
1911
+ The code above includes two data-bindings:
1912
+ - Tree `items`, which first bind to the root node (company.owner), and then dig down via `coworkers` `children` method, using the `name` `text` attribute for displaying each tree item.
1913
+ - Tree `selection`, which binds the single tree item selected by the user to the attribute denoted by the `bind` keyword
1914
+
1915
+ Additionally, Tree `items` data-binding automatically stores each node model unto the SWT TreeItem object via `setData` method. This enables things like searchability.
1916
+
1917
+ The tree widget in Glimmer is represented by a subclass of `WidgetProxy` called `TreeProxy`.
1918
+ TreeProxy includes a `depth_first_search` method that takes a block to look for a tree item.
1919
+
1920
+ Example:
1921
+
1922
+ ```ruby
1923
+ found_array = @tree.depth_first_search { |tree_item| tree_item.getData == company.owner }
1412
1924
  ```
1413
1925
 
1414
1926
  This finds the root node. The array is a Java array. This enables easy passing of it to SWT `Tree#setSelection` method, which expects a Java array of `TreeItem` objects.
@@ -1424,10 +1936,10 @@ Glimmer comes with `Observer` module, which is used internally for data-binding,
1424
1936
 
1425
1937
  Glimmer supports observing widgets with two main types of events:
1426
1938
  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`).
1427
- 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)
1939
+ 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)
1428
1940
 
1429
1941
  Additionally, there are two more types of events:
1430
- - SWT `display` supports global listeners called filters that run on any widget. They are hooked via `on_event_{swt-event-constant}`
1942
+ - SWT `display` supports global listeners called filters that run on any widget. They are hooked via `on_swt_{swt-event-constant}`
1431
1943
  - SWT `display` supports Mac application menu item observers (`on_about` and `on_preferences`), which you can read about under [Miscellaneous](#miscellaneous).
1432
1944
 
1433
1945
  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.
@@ -1450,7 +1962,8 @@ Let's revisit the Tic Tac Toe example shown near the beginning of the page:
1450
1962
  ```ruby
1451
1963
  shell {
1452
1964
  text "Tic-Tac-Toe"
1453
- composite {
1965
+ minimum_size 150, 178
1966
+ composite {
1454
1967
  grid_layout 3, true
1455
1968
  (1..3).each { |row|
1456
1969
  (1..3).each { |column|
@@ -1472,21 +1985,21 @@ Note that every Tic Tac Toe grid cell has its `text` and `enabled` properties da
1472
1985
 
1473
1986
  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.
1474
1987
 
1475
- **Regarding number 2**, you can figure out all available events by looking at the `org.eclipse.swt.SWT` API:
1988
+ **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:
1476
1989
 
1477
1990
  https://help.eclipse.org/2019-12/nftopic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/SWT.html
1478
1991
 
1479
1992
  Example (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
1480
1993
 
1481
- `SWT.Show` - hooks a listener for showing a widget (using `on_event_show` in Glimmer)
1482
- `SWT.Hide` - hooks a listener for hiding a widget (using `on_event_hide` in Glimmer)
1994
+ `SWT.Show` - hooks a listener for showing a widget (using `on_swt_show` in Glimmer)
1995
+ `SWT.Hide` - hooks a listener for hiding a widget (using `on_swt_hide` in Glimmer)
1483
1996
 
1484
1997
  ```ruby
1485
1998
  shell {
1486
1999
  @button1 = button {
1487
2000
  text "Show 2nd Button"
1488
2001
  visible true
1489
- on_event_show {
2002
+ on_swt_show {
1490
2003
  @button2.swt_widget.setVisible(false)
1491
2004
  }
1492
2005
  on_widget_selected {
@@ -1496,7 +2009,7 @@ shell {
1496
2009
  @button2 = button {
1497
2010
  text "Show 1st Button"
1498
2011
  visible false
1499
- on_event_show {
2012
+ on_swt_show {
1500
2013
  @button1.swt_widget.setVisible(false)
1501
2014
  }
1502
2015
  on_widget_selected {
@@ -1506,7 +2019,7 @@ shell {
1506
2019
  }.open
1507
2020
  ```
1508
2021
 
1509
- **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`
2022
+ **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`
1510
2023
 
1511
2024
  ##### Alternative Syntax
1512
2025
 
@@ -1549,7 +2062,7 @@ class TicTacToe
1549
2062
  end
1550
2063
  ```
1551
2064
 
1552
- Observers can be a good mechanism for displaying dialog messages in Glimmer (using SWT's `MessageBox`).
2065
+ 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).
1553
2066
 
1554
2067
  Look at [`samples/elaborate/tictactoe/tic_tac_toe.rb`](samples/tictactoe/tic_tac_toe.rb) for more details starting with the code included below.
1555
2068
 
@@ -1575,10 +2088,10 @@ class TicTacToe
1575
2088
  end
1576
2089
 
1577
2090
  def display_game_over_message(message)
1578
- message_box = MessageBox.new(@shell.swt_widget)
1579
- message_box.setText("Game Over")
1580
- message_box.setMessage(message)
1581
- message_box.open
2091
+ message_box(@shell) {
2092
+ text 'Game Over'
2093
+ message message_text
2094
+ }.open
1582
2095
  @tic_tac_toe_board.reset
1583
2096
  end
1584
2097
  # ...
@@ -1750,6 +2263,11 @@ body {
1750
2263
 
1751
2264
  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`.
1752
2265
 
2266
+ #### Final Notes
2267
+
2268
+ 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:
2269
+ [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)
2270
+
1753
2271
  ### Custom Shells
1754
2272
 
1755
2273
  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.
@@ -1795,7 +2313,7 @@ shell { |app_shell|
1795
2313
  @current_step_number = 1
1796
2314
  @wizard_steps = 5.times.map { |n|
1797
2315
  wizard_step(number: n+1, step_count: 5) {
1798
- on_event_hide {
2316
+ on_swt_hide {
1799
2317
  if @current_step_number < 5
1800
2318
  @current_step_number += 1
1801
2319
  app_shell.hide
@@ -1815,6 +2333,62 @@ shell { |app_shell|
1815
2333
  }.open
1816
2334
  ```
1817
2335
 
2336
+ ### Drag and Drop
2337
+
2338
+ Glimmer offers Drag and Drop support, thanks to [SWT](https://www.eclipse.org/swt/) and Glimmer's lightweight [DSL syntax](#glimmer-dsl-syntax).
2339
+
2340
+ 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)
2341
+
2342
+ To get started, simply follow these steps:
2343
+ 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)
2344
+ 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)
2345
+ 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)
2346
+ 1. Read `event.data` and consume it (e.g. change widget text) inside the `on_drop` event handler block.
2347
+
2348
+ Example (taken from [samples/hello/hello_drag_and_drop.rb](#hello-drag-and-drop) / you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
2349
+
2350
+ ```ruby
2351
+ class Location
2352
+ attr_accessor :country
2353
+
2354
+ def country_options
2355
+ %w[USA Canada Mexico Columbia UK Australia Germany Italy Spain]
2356
+ end
2357
+ end
2358
+
2359
+ @location = Location.new
2360
+
2361
+ include Glimmer
2362
+
2363
+ shell {
2364
+ text 'Hello, Drag and Drop!'
2365
+ list {
2366
+ selection bind(@location, :country)
2367
+ on_drag_set_data { |event|
2368
+ list = event.widget.getControl
2369
+ event.data = list.getSelection.first
2370
+ }
2371
+ }
2372
+ label(:center) {
2373
+ text 'Drag a country here!'
2374
+ font height: 20
2375
+ on_drop { |event|
2376
+ event.widget.getControl.setText(event.data)
2377
+ }
2378
+ }
2379
+ }.open
2380
+ ```
2381
+
2382
+ ![Hello Drag and Drop](images/glimmer-hello-drag-and-drop.gif)
2383
+
2384
+ Optional steps:
2385
+ - 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.
2386
+ - Specify `drag_source_style` operation (may be: :drop_copy (default), :drop_link, :drop_move, :drop_none, or an array of multiple operations)
2387
+ - 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)
2388
+ - Specify `drop_target_style` operation (may be: :drop_copy (default), :drop_link, :drop_move, :drop_none, or an array of multiple operations)
2389
+ - 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)
2390
+ - Set drag operation in `event.detail` (e.g. DND::DROP_COPY) inside `on_drag_enter`
2391
+
1818
2392
  ### Miscellaneous
1819
2393
 
1820
2394
  #### Multi-DSL Support
@@ -1970,10 +2544,10 @@ class Example
1970
2544
  def initialize
1971
2545
  display {
1972
2546
  on_about {
1973
- message_box = MessageBox.new(@shell_proxy.swt_widget)
1974
- message_box.setText("About")
1975
- message_box.setMessage("About Application")
1976
- message_box.open
2547
+ message_box(@shell_proxy) {
2548
+ text 'About'
2549
+ message 'About Application'
2550
+ }.open
1977
2551
  }
1978
2552
  on_preferences {
1979
2553
  preferences_dialog = dialog {
@@ -2039,7 +2613,7 @@ Also, you may invoke `Display.setAppVersion('1.0.0')` if needed for OS app versi
2039
2613
 
2040
2614
  #### Video Widget
2041
2615
 
2042
- ![Video Widget](images/glimmer-video-widget.png)
2616
+ [![Video Widget](images/glimmer-video-widget.png)](https://github.com/AndyObtiva/glimmer-cw-video)
2043
2617
 
2044
2618
  Glimmer supports a [video custom widget](https://github.com/AndyObtiva/glimmer-cw-video) not in SWT.
2045
2619
 
@@ -2049,7 +2623,7 @@ You may obtain via `glimmer-cw-video` gem.
2049
2623
 
2050
2624
  ![Hello Browser](images/glimmer-hello-browser.png)
2051
2625
 
2052
- 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).
2626
+ 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).
2053
2627
 
2054
2628
  Example loading a URL (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
2055
2629
 
@@ -2085,6 +2659,170 @@ shell {
2085
2659
 
2086
2660
  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).
2087
2661
 
2662
+ ## Glimmer Configuration
2663
+
2664
+ Glimmer configuration may be done via the `Glimmer::Config` module.
2665
+
2666
+ ### logger
2667
+
2668
+ The Glimmer DSL engine supports logging via a standard `STDOUT` Ruby `Logger` configured in the `Glimmer::Config.logger` config option.
2669
+ It is set to level Logger::ERROR by default.
2670
+ Log level may be adjusted via `Glimmer::Config.logger.level` just like any other Ruby Logger.
2671
+
2672
+ Example:
2673
+
2674
+ ```ruby
2675
+ Glimmer::Config.logger.level = :debug
2676
+ ```
2677
+ This results in more verbose debug loggging to `STDOUT`, which is very helpful in troubleshooting Glimmer DSL syntax when needed.
2678
+
2679
+ Example log:
2680
+ ```
2681
+ D, [2017-07-21T19:23:12.587870 #35707] DEBUG -- : method: shell and args: []
2682
+ D, [2017-07-21T19:23:12.594405 #35707] DEBUG -- : ShellCommandHandler will handle command: shell with arguments []
2683
+ D, [2017-07-21T19:23:12.844775 #35707] DEBUG -- : method: composite and args: []
2684
+ D, [2017-07-21T19:23:12.845388 #35707] DEBUG -- : parent is a widget: true
2685
+ D, [2017-07-21T19:23:12.845833 #35707] DEBUG -- : on listener?: false
2686
+ D, [2017-07-21T19:23:12.864395 #35707] DEBUG -- : WidgetCommandHandler will handle command: composite with arguments []
2687
+ D, [2017-07-21T19:23:12.864893 #35707] DEBUG -- : widget styles are: []
2688
+ D, [2017-07-21T19:23:12.874296 #35707] DEBUG -- : method: list and args: [:multi]
2689
+ D, [2017-07-21T19:23:12.874969 #35707] DEBUG -- : parent is a widget: true
2690
+ D, [2017-07-21T19:23:12.875452 #35707] DEBUG -- : on listener?: false
2691
+ D, [2017-07-21T19:23:12.878434 #35707] DEBUG -- : WidgetCommandHandler will handle command: list with arguments [:multi]
2692
+ D, [2017-07-21T19:23:12.878798 #35707] DEBUG -- : widget styles are: [:multi]
2693
+ ```
2694
+
2695
+ The `logger` instance may be replaced with a custom logger via `Glimmer::Config.logger = custom_logger`
2696
+
2697
+ To reset `logger` to the default instance, you may call `Glimmer::Config.reset_logger!`
2698
+
2699
+ 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.
2700
+
2701
+ [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt) enhances Glimmer default logging support via the Ruby [`logging`](https://github.com/TwP/logging) gem, enabling buffered asynchronous logging in a separate thread, thus completely unhindering normal desktop app performance.
2702
+
2703
+ Other config options related to the [`logging`](https://github.com/TwP/logging) gem are mentioned below.
2704
+
2705
+ #### logging_devices
2706
+
2707
+ This is an array of these possible values: `:stdout` (default), `:stderr`, `:file`, `:syslog` (default), `:stringio`
2708
+
2709
+ It defaults to `[:stdout, :syslog]`
2710
+
2711
+ When `:file` is included, Glimmer creates a 'log' directory directly below the Glimmer app local directory.
2712
+ It may also be customized further via the `logging_device_file_options` option.
2713
+ This is useful on Windows as an alternative to `syslog`, which is not available on Windows by default.
2714
+
2715
+ #### logging_device_file_options
2716
+
2717
+ This is a hash of [`logging`](https://github.com/TwP/logging) gem options for the `:file` logging device.
2718
+
2719
+ Default: `{size: 1_000_000, age: 'daily', roll_by: 'number'}`
2720
+
2721
+ That ensures splitting log files at the 1MB size and daily, rolling them by unique number.
2722
+
2723
+ #### logging_appender_options
2724
+
2725
+ Appender options is a hash passed as options to every appender (logging device) used in the [`logging`](https://github.com/TwP/logging) gem.
2726
+
2727
+ Default: `{async: true, auto_flushing: 500, write_size: 500, flush_period: 60, immediate_at: [:error, :fatal], layout: logging_layout}`
2728
+
2729
+ That ensures asynchronous buffered logging that is flushed every 500 messages and 60 seconds, or immediately at error and fatal log levels
2730
+
2731
+ #### logging_layout
2732
+
2733
+ This is a [`logging`](https://github.com/TwP/logging) gem layout that formats the logging output.
2734
+
2735
+ Default:
2736
+
2737
+ ```
2738
+ Logging.layouts.pattern(
2739
+ pattern: '[%d] %-5l %c: %m\n',
2740
+ date_pattern: '%Y-%m-%d %H:%M:%S'
2741
+ )
2742
+ ```
2743
+
2744
+ ### import_swt_packages
2745
+
2746
+ 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.
2747
+
2748
+ As a result, you may call SWT Java classes from Glimmer Ruby code without mentioning Java package references explicitly.
2749
+
2750
+ For example, `org.eclipse.swt.graphics.Color` can be referenced as just `Color`
2751
+
2752
+ 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:
2753
+ ```
2754
+ org.eclipse.swt.*
2755
+ org.eclipse.swt.widgets.*
2756
+ org.eclipse.swt.layout.*
2757
+ org.eclipse.swt.graphics.*
2758
+ org.eclipse.swt.browser.*
2759
+ org.eclipse.swt.custom.*
2760
+ org.eclipse.swt.dnd.*
2761
+ ```
2762
+
2763
+ 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).
2764
+
2765
+ Example:
2766
+
2767
+ ```ruby
2768
+ Glimmer::Config.import_swt_packages += [
2769
+ 'org.eclipse.nebula.widgets.ganttchart'
2770
+ ]
2771
+ ```
2772
+
2773
+ 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)
2774
+
2775
+ Nonetheless, you can disable automatic Java package import if needed via this Glimmer configuration option:
2776
+
2777
+ ```ruby
2778
+ Glimmer::Config.import_swt_packages = false
2779
+ ```
2780
+
2781
+ Once disabled, to import SWT Java packages manually, you may simply:
2782
+
2783
+ 1. `include Glimmer::SWT::Packages`: lazily imports all SWT Java packages to your class, lazy-loading SWT Java class constants on first reference.
2784
+
2785
+ 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'`)
2786
+
2787
+ 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.
2788
+
2789
+ You can learn more about importing Java packages into Ruby code at this JRuby WIKI page:
2790
+
2791
+ https://github.com/jruby/jruby/wiki/CallingJavaFromJRuby
2792
+
2793
+ ### loop_max_count
2794
+
2795
+ Glimmer has infinite loop detection support.
2796
+ It can detect when an infinite loop is about to occur in method_missing and stops it.
2797
+ It detects potential infinite loops when the same keyword and args repeat more than 100 times, which is unusual in a GUI app.
2798
+
2799
+ The max limit can be changed via the `Glimmer::Config::loop_max_count=(count)` config option.
2800
+
2801
+ Infinite loop detection may be disabled altogether if needed by setting `Glimmer::Config::loop_max_count` to `-1`
2802
+
2803
+ ### excluded_keyword_checkers
2804
+
2805
+ Glimmer permits consumers to exclude keywords from DSL processing by its engine via the `excluded_keyword_checkers` config option.
2806
+
2807
+ To do so, add a proc to it that returns a boolean indicating if a keyword is excluded or not.
2808
+
2809
+ 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.
2810
+
2811
+ Example of keywords excluded by [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt):
2812
+
2813
+ ```ruby
2814
+ Glimmer::Config.excluded_keyword_checkers << lambda do |method_symbol, *args|
2815
+ method = method_symbol.to_s
2816
+ result = false
2817
+ result ||= method.start_with?('on_swt_') && is_a?(Glimmer::UI::CustomWidget) && respond_to?(method)
2818
+ result ||= method == 'dispose' && is_a?(Glimmer::UI::CustomWidget) && respond_to?(method)
2819
+ result ||= ['drag_source_proxy', 'drop_target_proxy'].include?(method) && is_a?(Glimmer::UI::CustomWidget)
2820
+ result ||= method == 'post_initialize_child'
2821
+ result ||= method.end_with?('=')
2822
+ result ||= ['finish_edit!', 'search', 'all_tree_items', 'depth_first_search'].include?(method) && is_a?(Glimmer::UI::CustomWidget) && body_root.respond_to?(method)
2823
+ end
2824
+ ```
2825
+
2088
2826
  ## Glimmer Style Guide
2089
2827
 
2090
2828
  - Widgets are declared with underscored lowercase versions of their SWT names minus the SWT package name.
@@ -2100,6 +2838,38 @@ This relies on Glimmer's [Multi-DSL Support](#multi-dsl-support) for building th
2100
2838
  - Custom widget body, before_body, and after_body blocks open their blocks and close them with curly braces.
2101
2839
  - 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.
2102
2840
 
2841
+ ## SWT Reference
2842
+
2843
+ https://www.eclipse.org/swt/docs.php
2844
+
2845
+ Here is the SWT API:
2846
+
2847
+ https://help.eclipse.org/2019-12/nftopic/org.eclipse.platform.doc.isv/reference/api/index.html
2848
+
2849
+ Here is a visual list of SWT widgets:
2850
+
2851
+ https://www.eclipse.org/swt/widgets/
2852
+
2853
+ Here is a textual list of SWT widgets:
2854
+
2855
+ https://help.eclipse.org/2019-12/topic/org.eclipse.platform.doc.isv/guide/swt_widgets_controls.htm?cp=2_0_7_0_0
2856
+
2857
+ Here is a list of SWT style bits as used in widget declaration:
2858
+
2859
+ https://wiki.eclipse.org/SWT_Widget_Style_Bits
2860
+
2861
+ Here is a SWT style bit constant reference:
2862
+
2863
+ https://help.eclipse.org/2019-12/nftopic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/SWT.html
2864
+
2865
+ Here is an SWT Drag and Drop guide:
2866
+
2867
+ https://www.eclipse.org/articles/Article-SWT-DND/DND-in-SWT.html
2868
+
2869
+ Here is an SWT Custom Widget guide:
2870
+
2871
+ https://www.eclipse.org/articles/Article-Writing%20Your%20Own%20Widget/Writing%20Your%20Own%20Widget.htm
2872
+
2103
2873
  ## Samples
2104
2874
 
2105
2875
  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`).
@@ -2112,233 +2882,325 @@ samples/launch
2112
2882
 
2113
2883
  ### Hello Samples
2114
2884
 
2115
- For "Hello, World!" type samples, check the following:
2885
+ For hello-type simple samples, check the following.
2886
+
2887
+ #### Hello, World! Sample
2888
+
2889
+ Code:
2890
+
2891
+ [samples/hello/hello_world.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/hello/hello_world.rb)
2892
+
2893
+ Run:
2116
2894
 
2117
2895
  ```
2118
2896
  glimmer samples/hello/hello_world.rb
2119
- glimmer samples/hello/hello_browser.rb # demonstrates browser widget
2120
- glimmer samples/hello/hello_tab.rb # demonstrates tabs
2121
- glimmer samples/hello/hello_combo.rb # demonstrates combo data-binding
2122
- glimmer samples/hello/hello_list_single_selection.rb # demonstrates list single-selection data-binding
2123
- glimmer samples/hello/hello_list_multi_selection.rb # demonstrates list multi-selection data-binding
2124
- glimmer samples/hello/hello_computed.rb # demonstrates computed data-binding
2125
2897
  ```
2126
2898
 
2127
- ### Elaborate Samples
2899
+ ![Hello World](images/glimmer-hello-world.png)
2128
2900
 
2129
- For more elaborate samples, check the following:
2901
+ #### Hello, Tab!
2130
2902
 
2131
- #### Login
2903
+ Code:
2904
+
2905
+ [samples/hello/hello_tab.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/hello/hello_tab.rb)
2906
+
2907
+ Run:
2132
2908
 
2133
2909
  ```
2134
- glimmer samples/elaborate/login.rb # demonstrates basic data-binding
2910
+ glimmer samples/hello/hello_tab.rb
2135
2911
  ```
2136
2912
 
2137
- ![Login](images/glimmer-login.png)
2138
- ![Login Filled In](images/glimmer-login-filled-in.png)
2139
- ![Login Logged In](images/glimmer-login-logged-in.png)
2913
+ ![Hello Tab English](images/glimmer-hello-tab-english.png)
2914
+ ![Hello Tab French](images/glimmer-hello-tab-french.png)
2915
+
2916
+ #### Hello, Combo!
2917
+
2918
+ This sample demonstrates combo data-binding.
2919
+
2920
+ Code:
2140
2921
 
2141
- #### Tic Tac Toe
2922
+ [samples/hello/hello_combo.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/hello/hello_combo.rb)
2923
+
2924
+ Run:
2142
2925
 
2143
2926
  ```
2144
- glimmer samples/elaborate/tic_tac_toe.rb # demonstrates a full MVC application
2927
+ glimmer samples/hello/hello_combo.rb
2145
2928
  ```
2146
2929
 
2147
- ![Tic Tac Toe](images/glimmer-tic-tac-toe.png)
2148
- ![Tic Tac Toe In Progress](images/glimmer-tic-tac-toe-in-progress.png)
2149
- ![Tic Tac Toe Game Over](images/glimmer-tic-tac-toe-game-over.png)
2930
+ ![Hello Combo](images/glimmer-hello-combo.png)
2931
+ ![Hello Combo Expanded](images/glimmer-hello-combo-expanded.png)
2932
+
2933
+ #### Hello, List Single Selection!
2150
2934
 
2151
- #### Contact Manager
2935
+ This sample demonstrates list single-selection data-binding.
2936
+
2937
+ Code:
2938
+
2939
+ [samples/hello/hello_list_single_selection.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/hello/hello_list_single_selection.rb)
2940
+
2941
+ Run:
2152
2942
 
2153
2943
  ```
2154
- glimmer samples/elaborate/contact_manager.rb # demonstrates table data-binding
2944
+ glimmer samples/hello/hello_list_single_selection.rb
2155
2945
  ```
2156
2946
 
2157
- Contact Manager
2947
+ ![Hello List Single Selection](images/glimmer-hello-list-single-selection.png)
2158
2948
 
2159
- ![Contact Manager](images/glimmer-contact-manager.png)
2949
+ #### Hello, List Multi Selection!
2160
2950
 
2161
- Contact Manager - Find
2951
+ This sample demonstrates list multi-selection data-binding.
2162
2952
 
2163
- ![Contact Manager](images/glimmer-contact-manager-find.png)
2953
+ Code:
2164
2954
 
2165
- Contact Manager - Edit Started
2955
+ [samples/hello/hello_list_multi_selection.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/hello/hello_list_multi_selection.rb)
2166
2956
 
2167
- ![Contact Manager](images/glimmer-contact-manager-edit-started.png)
2957
+ Run:
2168
2958
 
2169
- Contact Manager - Edit In Progress
2959
+ ```
2960
+ glimmer samples/hello/hello_list_multi_selection.rb
2961
+ ```
2170
2962
 
2171
- ![Contact Manager](images/glimmer-contact-manager-edit-in-progress.png)
2963
+ ![Hello List Multi Selection](images/glimmer-hello-list-multi-selection.png)
2172
2964
 
2173
- Contact Manager - Edit Done
2965
+ #### Hello, Computed!
2174
2966
 
2175
- ![Contact Manager](images/glimmer-contact-manager-edit-done.png)
2967
+ This sample demonstrates computed data-binding.
2176
2968
 
2177
- ### External Samples
2969
+ Code:
2178
2970
 
2179
- #### Glimmer Calculator
2971
+ [samples/hello/hello_computed.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/hello/hello_computed.rb)
2180
2972
 
2181
- [<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)
2973
+ Run:
2182
2974
 
2183
- [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).
2975
+ ```
2976
+ glimmer samples/hello/hello_computed.rb
2977
+ ```
2184
2978
 
2185
- #### Gladiator
2979
+ ![Hello Browser](images/glimmer-hello-computed.png)
2186
2980
 
2187
- [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer-cs-gladiator/v0.1.5/images/glimmer-gladiator.png" />](https://github.com/AndyObtiva/glimmer-cs-gladiator)
2981
+ #### Hello, Message Box!
2188
2982
 
2189
- [Gladiator](https://github.com/AndyObtiva/glimmer-cs-gladiator) (short for Glimmer Editor) is a Glimmer sample project under on-going development.
2190
- You may check it out to learn how to build a Glimmer Custom Shell gem.
2983
+ This sample demonstrates a `message_box` dialog.
2191
2984
 
2192
- Gladiator is a good demonstration of:
2193
- - MVP Pattern
2194
- - Tree data-binding
2195
- - List data-binding
2196
- - Text selection data-binding
2197
- - Tabs
2198
- - Context menus
2199
- - Custom Shell
2200
- - Custom widget
2985
+ Code:
2201
2986
 
2202
- ## In Production
2987
+ [samples/hello/hello_message_box.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/hello/hello_message_box.rb)
2203
2988
 
2204
- The following production apps have been built with Glimmer:
2989
+ Run:
2205
2990
 
2206
- [<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
2991
+ ```
2992
+ glimmer samples/hello/hello_message_box.rb
2993
+ ```
2207
2994
 
2208
- If you have a Glimmer app you would like referenced here, please mention in a Pull Request.
2995
+ ![Hello Message Box](images/glimmer-hello-message-box.png)
2996
+ ![Hello Message Box Dialog](images/glimmer-hello-message-box-dialog.png)
2209
2997
 
2210
- ## SWT Reference
2998
+ #### Hello, Browser!
2211
2999
 
2212
- https://www.eclipse.org/swt/docs.php
3000
+ This sample demonstrates the `browser` widget.
2213
3001
 
2214
- Here is the SWT API:
3002
+ Code:
2215
3003
 
2216
- https://help.eclipse.org/2019-12/nftopic/org.eclipse.platform.doc.isv/reference/api/index.html
3004
+ [samples/hello/hello_browser.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/hello/hello_browser.rb)
2217
3005
 
2218
- Here is a visual list of SWT widgets:
3006
+ Run:
2219
3007
 
2220
- https://www.eclipse.org/swt/widgets/
3008
+ ```
3009
+ glimmer samples/hello/hello_browser.rb
3010
+ ```
2221
3011
 
2222
- Here is a textual list of SWT widgets:
3012
+ ![Hello Browser](images/glimmer-hello-browser.png)
2223
3013
 
2224
- https://help.eclipse.org/2019-12/topic/org.eclipse.platform.doc.isv/guide/swt_widgets_controls.htm?cp=2_0_7_0_0
3014
+ #### Hello, Drag and Drop!
2225
3015
 
2226
- Here is a list of SWT style bits as used in widget declaration:
3016
+ This sample demonstrates drag and drop in Glimmer.
2227
3017
 
2228
- https://wiki.eclipse.org/SWT_Widget_Style_Bits
3018
+ Code:
2229
3019
 
2230
- Here is a SWT style bit constant reference:
3020
+ [samples/hello/hello_drag_and_drop.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/hello/hello_drag_and_drop.rb)
2231
3021
 
2232
- https://help.eclipse.org/2019-12/nftopic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/SWT.html
3022
+ Run:
3023
+
3024
+ ```
3025
+ glimmer samples/hello/hello_drag_and_drop.rb
3026
+ ```
3027
+
3028
+ ![Hello Drag and Drop](images/glimmer-hello-drag-and-drop.gif)
2233
3029
 
2234
- ## SWT Packages
3030
+ #### Hello, Menu Bar!
2235
3031
 
2236
- Glimmer automatically imports all SWT Java packages upon adding `include Glimmer` to a class or module.
3032
+ This sample demonstrates menus in Glimmer.
3033
+
3034
+ Code:
3035
+
3036
+ [samples/hello/hello_menu_bar.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/hello/hello_menu_bar.rb)
3037
+
3038
+ Run:
2237
3039
 
2238
- Here are the Java packages imported:
2239
3040
  ```
2240
- org.eclipse.swt.*
2241
- org.eclipse.swt.widgets.*
2242
- org.eclipse.swt.layout.*
2243
- org.eclipse.swt.graphics.*
2244
- org.eclipse.swt.browser.*
2245
- org.eclipse.swt.custom.*
3041
+ glimmer samples/hello/hello_menu_bar.rb
2246
3042
  ```
2247
3043
 
2248
- This allows you to call SWT Java classes from Ruby without mentioning Java package references.
3044
+ ![Hello Menu Bar](images/glimmer-hello-menu-bar.png)
3045
+ ![Hello Menu Bar File Menu](images/glimmer-hello-menu-bar-file-menu.png)
3046
+ ![Hello Menu Bar History Menu](images/glimmer-hello-menu-bar-history-menu.png)
2249
3047
 
2250
- For example, after imports, `org.eclipse.swt.graphics.Color` can be referenced by just `Color`
3048
+ #### Hello, Pop Up Context Menu!
2251
3049
 
2252
- Nonetheless, you can disable automatic import if needed via this Glimmer configuration option:
3050
+ This sample demonstrates pop up context menus in Glimmer.
2253
3051
 
2254
- ```ruby
2255
- Glimmer::Config.import_swt_packages = false
2256
- ```
3052
+ Code:
2257
3053
 
2258
- To import SWT Java packages manually instead, you have 2 options:
3054
+ [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)
2259
3055
 
2260
- 1. `include Glimmer::SwtPackages`: lazily imports all SWT Java packages to your class, lazy-loading SWT Java class constants on first reference.
3056
+ Run:
2261
3057
 
2262
- 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'`)
3058
+ ```
3059
+ glimmer samples/hello/hello_pop_up_context_menu.rb
3060
+ ```
2263
3061
 
2264
- 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.
3062
+ ![Hello Pop Up Context Menu](images/glimmer-hello-pop-up-context-menu.png)
3063
+ ![Hello Pop Up Context Menu Popped Up](images/glimmer-hello-pop-up-context-menu-popped-up.png)
2265
3064
 
2266
- You can learn more about importing Java packages into Ruby code at this JRuby WIKI page:
3065
+ ### Elaborate Samples
2267
3066
 
2268
- https://github.com/jruby/jruby/wiki/CallingJavaFromJRuby
3067
+ For more elaborate samples, check the following:
2269
3068
 
2270
- ## Infinite Loop Detection
3069
+ #### Login
2271
3070
 
2272
- Glimmer can detect if an infinite loop occurs with method_missing by ensuring it does not loop with the same keyword and args more than 100 times.
3071
+ This sample demonstrates basic data-binding, password and text fields, and field enablement data-binding.
2273
3072
 
2274
- The max limit can be changed via the `Glimmer::Config::loop_max_count=(count)` method.
3073
+ Code:
2275
3074
 
2276
- Infinite loop detection may be disabled by setting `Glimmer::Config::loop_max_count` to `-1`
3075
+ [samples/elaborate/login.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/elaborate/login.rb)
2277
3076
 
2278
- ## Logging
3077
+ Run:
2279
3078
 
2280
- Glimmer comes with a Ruby Logger accessible via `Glimmer::Config.logger`
2281
- Its level of logging defaults to `Logger::WARN`
2282
- It may be configured to show a different level of logging as follows:
2283
- ```ruby
2284
- Glimmer::Config.enable_logging
2285
- Glimmer::Config.logger.level = Logger::DEBUG
2286
3079
  ```
2287
- This results in more verbose debugging log to `STDOUT`, which is helpful in troubleshooting Glimmer DSL syntax when needed.
2288
-
2289
- Example log:
2290
- ```
2291
- D, [2017-07-21T19:23:12.587870 #35707] DEBUG -- : method: shell and args: []
2292
- D, [2017-07-21T19:23:12.594405 #35707] DEBUG -- : ShellCommandHandler will handle command: shell with arguments []
2293
- D, [2017-07-21T19:23:12.844775 #35707] DEBUG -- : method: composite and args: []
2294
- D, [2017-07-21T19:23:12.845388 #35707] DEBUG -- : parent is a widget: true
2295
- D, [2017-07-21T19:23:12.845833 #35707] DEBUG -- : on listener?: false
2296
- D, [2017-07-21T19:23:12.864395 #35707] DEBUG -- : WidgetCommandHandler will handle command: composite with arguments []
2297
- D, [2017-07-21T19:23:12.864893 #35707] DEBUG -- : widget styles are: []
2298
- D, [2017-07-21T19:23:12.874296 #35707] DEBUG -- : method: list and args: [:multi]
2299
- D, [2017-07-21T19:23:12.874969 #35707] DEBUG -- : parent is a widget: true
2300
- D, [2017-07-21T19:23:12.875452 #35707] DEBUG -- : on listener?: false
2301
- D, [2017-07-21T19:23:12.878434 #35707] DEBUG -- : WidgetCommandHandler will handle command: list with arguments [:multi]
2302
- D, [2017-07-21T19:23:12.878798 #35707] DEBUG -- : widget styles are: [:multi]
3080
+ glimmer samples/elaborate/login.rb
2303
3081
  ```
2304
3082
 
2305
- ## Raw JRuby Command
3083
+ ![Login](images/glimmer-login.png)
3084
+ ![Login Filled In](images/glimmer-login-filled-in.png)
3085
+ ![Login Logged In](images/glimmer-login-logged-in.png)
3086
+
3087
+ #### Tic Tac Toe Sample
2306
3088
 
2307
- If there is a need to run Glimmer directly via the `jruby` command, you
2308
- may run the following:
3089
+ 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)).
3090
+
3091
+ Code:
3092
+
3093
+ (Please note that on some Linux instances where the display x-axis is set to double-scale, you need to set the `shell` `minimum_size` to `300, 178` instead of `150, 178`)
3094
+
3095
+ [samples/elaborate/tic_tac_toe.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/elaborate/tic_tac_toe.rb)
3096
+
3097
+ Run:
2309
3098
 
2310
3099
  ```
2311
- jruby -J-classpath "path_to/swt.jar" -r glimmer -S application.rb
3100
+ glimmer samples/elaborate/tic_tac_toe.rb
2312
3101
  ```
2313
3102
 
2314
- The `-J-classpath` option specifies the `swt.jar` file path, which can be a
2315
- 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.
3103
+ ![Tic Tac Toe](images/glimmer-tic-tac-toe.png)
3104
+ ![Tic Tac Toe In Progress](images/glimmer-tic-tac-toe-in-progress.png)
3105
+ ![Tic Tac Toe Game Over](images/glimmer-tic-tac-toe-game-over.png)
2316
3106
 
2317
- The `-r` option preloads (requires) the `glimmer` library in Ruby.
3107
+ #### Contact Manager Sample
2318
3108
 
2319
- The `-S` option specifies a script to run.
3109
+ 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)).
2320
3110
 
2321
- ### Mac Support
3111
+ Code:
2322
3112
 
2323
- 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.
3113
+ [samples/elaborate/contact_manager.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/elaborate/contact_manager.rb)
3114
+
3115
+ Run:
2324
3116
 
2325
- Example:
2326
3117
  ```
2327
- jruby -J-XstartOnFirstThread -J-classpath "path_to/swt.jar" -r glimmer -S application.rb
3118
+ glimmer samples/elaborate/contact_manager.rb
2328
3119
  ```
2329
3120
 
3121
+ Contact Manager
3122
+
3123
+ ![Contact Manager](images/glimmer-contact-manager.png)
3124
+
3125
+ Contact Manager - Find
3126
+
3127
+ ![Contact Manager](images/glimmer-contact-manager-find.png)
3128
+
3129
+ Contact Manager - Edit Started
3130
+
3131
+ ![Contact Manager](images/glimmer-contact-manager-edit-started.png)
3132
+
3133
+ Contact Manager - Edit In Progress
3134
+
3135
+ ![Contact Manager](images/glimmer-contact-manager-edit-in-progress.png)
3136
+
3137
+ Contact Manager - Edit Done
3138
+
3139
+ ![Contact Manager](images/glimmer-contact-manager-edit-done.png)
3140
+
3141
+ ### External Samples
3142
+
3143
+ #### Glimmer Calculator
3144
+
3145
+ [<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).
3146
+
3147
+ [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer-cs-calculator/master/glimmer-cs-calculator-screenshot.png" />](https://github.com/AndyObtiva/glimmer-cs-calculator)
3148
+
3149
+ #### Gladiator
3150
+
3151
+ [<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.
3152
+ You may check it out to learn how to build a Glimmer Custom Shell gem.
3153
+
3154
+ [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer-cs-gladiator/master/images/glimmer-gladiator.png" />](https://github.com/AndyObtiva/glimmer-cs-gladiator)
3155
+
3156
+ Gladiator is a good demonstration of:
3157
+ - MVP Pattern
3158
+ - Tree data-binding
3159
+ - List data-binding
3160
+ - Text selection data-binding
3161
+ - Tabs
3162
+ - Context menus
3163
+ - Custom Shell
3164
+ - Custom widget
3165
+
3166
+ ## In Production
3167
+
3168
+ The following production apps have been built with Glimmer.
3169
+
3170
+ If you have a Glimmer app you would like referenced here, please mention in a Pull Request.
3171
+
3172
+ ### Math Bowling
3173
+
3174
+ [<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
3175
+
3176
+ ### Are We There Yet?
3177
+
3178
+ [<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
3179
+
3180
+ ### Garderie Rainbow Daily Agenda
3181
+
3182
+ [<img alt="Garderie Rainbow Daily Agenda Logo" src="https://github.com/AndyObtiva/garderie_rainbow_daily_agenda/raw/master/images/garderie_rainbow_daily_agenda_logo.png" width="40" />Garderie Rainbow Daily Agenda](https://github.com/AndyObtiva/garderie_rainbow_daily_agenda): A child nursery daily agenda reporting desktop app
3183
+
2330
3184
  ## Packaging & Distribution
2331
3185
 
2332
3186
  Glimmer apps may be packaged and distributed on the Mac, Windows, and Linux via these tools:
2333
3187
  - Warbler (https://github.com/jruby/warbler): Enables bundling a Glimmer app into a JAR file
2334
- - 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.
3188
+ - javapackager (https://docs.oracle.com/javase/8/docs/technotes/tools/unix/javapackager.html): Enables packaging a JAR file as a DMG/PKG/APP file on Mac, MSI/EXE on Windows, and DEB/RPM on Linux.
2335
3189
 
2336
- 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):
3190
+ Glimmer simplifies the process of Mac and Windows packaging via the `glimmer package` command:
2337
3191
 
2338
3192
  ```
2339
3193
  glimmer package
2340
3194
  ```
2341
3195
 
3196
+ It works out of the box for any application generated by [Glimmer Scaffolding](#scaffolding).
3197
+
3198
+ Otherwise, if you are using Glimmer manually, to make the `glimmer package` command available, you must add the following line to your application `Rakefile`:
3199
+
3200
+ ```ruby
3201
+ require 'glimmer/rake_task'
3202
+ ```
3203
+
2342
3204
  This will automatically generate a JAR file under `./dist` directory using Warbler, which is then used to automatically generate a DMG file (and pkg/app) under `./packages/bundles` using `javapackager`.
2343
3205
  JAR file name will match your application local directory name (e.g. `MathBowling.jar` for `~/code/MathBowling`)
2344
3206
  DMG file name will match the humanized local directory name + dash + application version (e.g. `Math Bowling-1.0.dmg` for `~/code/MathBowling` with version 1.0 or unspecified)
@@ -2346,6 +3208,14 @@ DMG file name will match the humanized local directory name + dash + application
2346
3208
  The `glimmer package` command will automatically set "mac.CFBundleIdentifier" to ="org.#{project_name}.application.#{project_name}".
2347
3209
  You may override by configuring as an extra argument for javapackger (e.g. Glimmer::Package.javapackager_extra_args = " -Bmac.CFBundleIdentifier=org.andymaleh.application.MathBowling")
2348
3210
 
3211
+ You may choose to generate a specific type of packaging by passing the `[type]` option:
3212
+
3213
+ ```
3214
+ glimmer package[msi]
3215
+ ```
3216
+
3217
+ That generates an MSI file on Windows (could specify exe or image as alternatives on Windows).
3218
+
2349
3219
  ### Packaging Defaults
2350
3220
 
2351
3221
  Glimmer employs smart defaults in packaging.
@@ -2406,6 +3276,14 @@ JAVAPACKAGER_EXTRA_ARGS='-Bmac.CFBundleName="Math Bowling Game"' glimmer package
2406
3276
 
2407
3277
  That overrides the default application display name.
2408
3278
 
3279
+ ### Windows Application Packaging
3280
+
3281
+ Windows offers two options for setup packaging:
3282
+ - `msi` (recommended): simpler packaging option. Requires [WiX Toolset](https://wixtoolset.org/) and [.NET Framework](https://dotnet.microsoft.com/download/dotnet-framework). Simply run `glimmer package[msi]` (or `glimmer package:native[msi]` if it's not your first time) and it will tell you what you need to install including which version of .NET Framework it needs.
3283
+ - `exe`: more advanced packaging option. Requires [Inno Setup](https://jrsoftware.org/isinfo.php). Simply run `glimmer package[exe]` (or `glimmer package:native[exe]` if it's not your first time) and it will tell you what you need to install.
3284
+
3285
+ If you just want to test out packaging into a native Windows app that is not packaged for Windows setup, just pass `image` to generate a native Windows app only.
3286
+
2409
3287
  ### Mac Application Distribution
2410
3288
 
2411
3289
  Recent macOS versions (starting with Catalina) have very stringent security requirements requiring all applications to be signed before running (unless the user goes to System Preferences -> Privacy -> General tab and clicks "Open Anyway" after failing to open application the first time they run it). So, to release a desktop application on the Mac, it is recommended to enroll in the [Apple Developer Program](https://developer.apple.com/programs/) to distribute on the [Mac App Store](https://developer.apple.com/distribute/) or otherwise request [app notarization from Apple](https://developer.apple.com/documentation/xcode/notarizing_macos_software_before_distribution) to distribute independently.
@@ -2471,6 +3349,10 @@ By the way, keep in mind that during normal operation, it does also indicate a f
2471
3349
  Exec failed with code 2 command [[/usr/bin/SetFile, -c, icnC, /var/folders/4_/g1sw__tx6mjdgyh3mky7vydc0000gp/T/fxbundler4076750801763032201/images/MathBowling/.VolumeIcon.icns] in unspecified directory
2472
3350
  ```
2473
3351
 
3352
+ ## App Updates
3353
+
3354
+ Glimmer already supports automatic (and manual) app updates via the Mac App Store for Mac apps. Simply run the `glimmer package` command with the Mac App Store keys configured as per [Mac Application Distribution](mac-application-distribution) instructions and you get automatic (and manual) app update support courtesy of the Mac App Store.
3355
+
2474
3356
  ## Resources
2475
3357
 
2476
3358
  * [Code Master Blog](http://andymaleh.blogspot.com/search/label/Glimmer)
@@ -2504,13 +3386,21 @@ Glimmer DSL Engine specific tasks are at:
2504
3386
 
2505
3387
  ## Change Log
2506
3388
 
3389
+ [glimmer-dsl-swt/CHANGELOG.md](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/CHANGELOG.md)
3390
+
2507
3391
  [CHANGELOG.md](CHANGELOG.md)
2508
3392
 
2509
3393
  ## Contributing
2510
3394
 
2511
3395
  **Contributors Wanted!**
2512
3396
 
2513
- 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 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).
3397
+ 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).
3398
+
3399
+ You may apply for contributing to any of these Glimmer DSL gems whether you prefer to focus on the desktop or web:
3400
+ - [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt): Glimmer DSL for SWT (Desktop GUI)
3401
+ - [glimmer-dsl-opal](https://github.com/AndyObtiva/glimmer-dsl-opal): Glimmer DSL for Opal (Web GUI Adapter for Desktop Apps)
3402
+ - [glimmer-dsl-xml](https://github.com/AndyObtiva/glimmer-dsl-xml): Glimmer DSL for XML (& HTML)
3403
+ - [glimmer-dsl-css](https://github.com/AndyObtiva/glimmer-dsl-css): Glimmer DSL for CSS (Cascading Style Sheets)
2514
3404
 
2515
3405
  [CONTRIBUTING.md](CONTRIBUTING.md)
2516
3406
 
@@ -2521,9 +3411,17 @@ If you would like to contribute to Glimmer, please study up on Glimmer and [SWT]
2521
3411
 
2522
3412
  [Click here to view contributor commits.](https://github.com/AndyObtiva/glimmer/graphs/contributors)
2523
3413
 
3414
+ ## Hire Me
3415
+
3416
+ 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/).
3417
+
2524
3418
  ## License
2525
3419
 
2526
- Copyright (c) 2007-2020 Andy Maleh.
2527
- See LICENSE.txt for further details.
3420
+ [MIT](https://opensource.org/licenses/MIT)
3421
+
3422
+ Copyright (c) 2007-2020 - Andy Maleh.
3423
+ See [LICENSE.txt](LICENSE.txt) for further details.
3424
+
3425
+ --
2528
3426
 
2529
3427
  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>