glimmer 0.9.1 → 0.10.0

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: 9a0e5867d64de61a6733bb4946eb3b366ae854a72bf99cdc048707c00cd9c276
4
- data.tar.gz: b3735c7bff7ee61219f822378b59077e00f9957ed1031b09fd1e3f461eb90868
3
+ metadata.gz: 5c67def84181cab028446e3087c2c22d091bb0b17d02aa91e3948a8d7b176113
4
+ data.tar.gz: a2613dc9b58d1ef2d048b93f695e2aef799b06c46ec85999a78ecb48a6c5d469
5
5
  SHA512:
6
- metadata.gz: b5e181bff40082c4620fc6ad1a306af61c7d59e24a30c13c6038606f008d9480da5532d07a704d0c39563318c23935efb909f958f596b7c49c5f2a6843ace165
7
- data.tar.gz: 0562d569471bb792943cac85d0c3a79462573074e1ad634fb0aac1f1e9b53bbe9121d8534f9ea1ce94f5b30b0c47947618e73938e38d72695cecbfba48684210
6
+ metadata.gz: cbab9c4d0212aa47f46dd73394c05a47ebb95d1b18afb1b76b7400c72ae188f849776f411e3808b3fbd75537d3c7ca416fe3bcf90c08aba17e3058a8bccbc228
7
+ data.tar.gz: f913e477fa27d42e46614470e3e9e3c18fafd08e2a8fb6eb65c579b6a5894884e61da5203fc0df1d41fd4860f5dc4b435c123c6b5822a4056f6c01bfb4854ff2
data/README.md CHANGED
@@ -1,12 +1,24 @@
1
- # Glimmer - Ruby Desktop Development GUI Library
1
+ # <img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 style="position: relative; top: 20px;" /> Glimmer (Ruby Desktop Development GUI Library)
2
2
  [![Gem Version](https://badge.fury.io/rb/glimmer.svg)](http://badge.fury.io/rb/glimmer)
3
- [![Travis CI](https://travis-ci.com/AndyObtiva/glimmer.svg?branch=master)](https://travis-ci.com/github/AndyObtiva/glimmer)
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
+ [![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)
6
+
7
+ **[Contributors Wanted! (Submit a Glimmer App Sample to Get Started)](#contributing)**
8
+
9
+ (The Original Glimmer Library Since 2007. Beware of Imitators!)
4
10
 
5
11
  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.
6
12
 
7
13
  [<img src="https://covers.oreillystatic.com/images/9780596519650/lrg.jpg" width=105 /><br />
8
14
  Featured in<br />JRuby Cookbook](http://shop.oreilly.com/product/9780596519650.do)
9
15
 
16
+ Glimmer DSL gems:
17
+ - [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt): Glimmer DSL for SWT (Desktop GUI)
18
+ - [glimmer-dsl-opal](https://github.com/AndyObtiva/glimmer-dsl-opal): Glimmer DSL for Opal (Web GUI Adapter for Desktop Apps)
19
+ - [glimmer-dsl-xml](https://github.com/AndyObtiva/glimmer-dsl-xml): Glimmer DSL for XML (& HTML)
20
+ - [glimmer-dsl-css](https://github.com/AndyObtiva/glimmer-dsl-css): Glimmer DSL for CSS
21
+
10
22
  ## Examples
11
23
 
12
24
  ### Hello, World!
@@ -67,15 +79,13 @@ glimmer samples/elaborate/tic_tac_toe.rb
67
79
 
68
80
  Glimmer app:
69
81
 
70
- ![Tic Tac Toe](images/glimmer-tic-tac-toe.png)
82
+ ![Tic Tac Toe](images/glimmer-tic-tac-toe-in-progress.png)
71
83
 
72
84
  NOTE: Glimmer is in beta mode. Please help make better by [contributing](#contributing), adopting for small or low risk projects, and providing feedback.
73
85
 
74
- Ruby is a dynamically-typed object-oriented language, which provides great productivity gains due to its powerful expressive syntax and dynamic nature. While it is proven by the Ruby on Rails framework for web development, it currently lacks a robust platform-independent framework for building desktop applications. Given that Java libraries can now be utilized in Ruby code through JRuby, Eclipse technologies, such as SWT, JFace, and RCP can help fill the gap of desktop application development with Ruby.
75
-
76
86
  ## Table of contents
77
87
 
78
- - [Glimmer - Ruby Desktop Development GUI Library](#glimmer---ruby-desktop-development-gui-library)
88
+ - [Glimmer (Ruby Desktop Development GUI Library)](#-glimmer-ruby-desktop-development-gui-library)
79
89
  - [Examples](#examples)
80
90
  - [Hello, World!](#hello-world)
81
91
  - [Tic Tac Toe](#tic-tac-toe)
@@ -94,6 +104,13 @@ Ruby is a dynamically-typed object-oriented language, which provides great produ
94
104
  - [Custom Widget](#custom-widget)
95
105
  - [Custom Shell Gem](#custom-shell-gem)
96
106
  - [Custom Widget Gem](#custom-widget-gem)
107
+ - [Gem Listing](#gem-listing)
108
+ - [Listing Custom Shell Gems](#listing-custom-shell-gems)
109
+ - [Listing Custom Widget Gems](#listing-custom-widget-gems)
110
+ - [Listing DSL Gems](#listing-dsl-gems)
111
+ - [Packaging](#packaging)
112
+ - [Raw JRuby Command](#raw-jruby-command)
113
+ - [Mac Support](#mac-support)
97
114
  - [Girb (Glimmer irb) Command](#girb-glimmer-irb-command)
98
115
  - [Glimmer DSL Syntax](#glimmer-dsl-syntax)
99
116
  - [Widgets](#widgets)
@@ -101,6 +118,7 @@ Ruby is a dynamically-typed object-oriented language, which provides great produ
101
118
  - [SWT Proxies](#swt-proxies)
102
119
  - [Dialog](#dialog)
103
120
  - [Menus](#menus)
121
+ - [ScrolledComposite](#scrolledcomposite)
104
122
  - [Widget Styles](#widget-styles)
105
123
  - [Explicit SWT Style Bit](#explicit-swt-style-bit)
106
124
  - [Negative SWT Style Bits](#negative-swt-style-bits)
@@ -121,29 +139,49 @@ Ruby is a dynamically-typed object-oriented language, which provides great produ
121
139
  - [Observing Models](#observing-models)
122
140
  - [Custom Widgets](#custom-widgets)
123
141
  - [Simple Example](#simple-example)
124
- - [Hook Example](#hook-example)
142
+ - [Lifecycle Hook Example](#lifecycle-hook-example)
143
+ - [Custom Widget API](#custom-widget-api)
125
144
  - [Content/Options Example](#contentoptions-example)
145
+ - [Custom Widget Lifecycle Hooks](#custom-widget-lifecycle-hooks)
126
146
  - [Gotcha](#gotcha)
147
+ - [Final Notes](#final-notes)
127
148
  - [Custom Shells](#custom-shells)
149
+ - [Drag and Drop](#drag-and-drop)
128
150
  - [Miscellaneous](#miscellaneous)
129
151
  - [Multi-DSL Support](#multi-dsl-support)
130
152
  - [Application Menu Items (About/Preferences)](#application-menu-items-aboutpreferences)
131
153
  - [App Name and Version](#app-name-and-version)
132
154
  - [Video Widget](#video-widget)
133
155
  - [Browser Widget](#browser-widget)
156
+ - [Glimmer Configuration](#glimmer-configuration)
157
+ - [logger](#logger)
158
+ - [import_swt_packages](#importswtpackages)
159
+ - [loop_max_count](#loopmaxcount)
134
160
  - [Glimmer Style Guide](#glimmer-style-guide)
161
+ - [SWT Reference](#swt-reference)
135
162
  - [Samples](#samples)
136
163
  - [Hello Samples](#hello-samples)
164
+ - [Hello, World! Sample](#hello-world-sample)
165
+ - [Hello, Tab!](#hello-tab)
166
+ - [Hello, Combo!](#hello-combo)
167
+ - [Hello, List Single Selection!](#hello-list-single-selection)
168
+ - [Hello, List Multi Selection!](#hello-list-multi-selection)
169
+ - [Hello, Computed!](#hello-computed)
170
+ - [Hello, Message Box!](#hello-message-box)
171
+ - [Hello, Browser!](#hello-browser)
172
+ - [Hello, Drag and Drop!](#hello-drag-and-drop)
173
+ - [Hello, Menu Bar!](#hello-menu-bar)
174
+ - [Hello, Pop Up Context Menu!](#hello-pop-up-context-menu)
137
175
  - [Elaborate Samples](#elaborate-samples)
176
+ - [Login](#login)
177
+ - [Tic Tac Toe Sample](#tic-tac-toe-sample)
178
+ - [Contact Manager](#contact-manager)
138
179
  - [External Samples](#external-samples)
139
180
  - [Glimmer Calculator](#glimmer-calculator)
140
181
  - [Gladiator](#gladiator)
141
182
  - [In Production](#in-production)
142
- - [SWT Reference](#swt-reference)
143
- - [SWT Packages](#swt-packages)
144
- - [Logging](#logging)
145
- - [Raw JRuby Command](#raw-jruby-command)
146
- - [Mac Support](#mac-support)
183
+ - [Math Bowling](#math-bowling)
184
+ - [Are We There Yet?](#are-we-there-yet)
147
185
  - [Packaging & Distribution](#packaging--distribution)
148
186
  - [Packaging Defaults](#packaging-defaults)
149
187
  - [Packaging Configuration](#packaging-configuration)
@@ -154,11 +192,12 @@ Ruby is a dynamically-typed object-oriented language, which provides great produ
154
192
  - [Resources](#resources)
155
193
  - [Help](#help)
156
194
  - [Issues](#issues)
157
- - [IRC Channel](#irc-channel)
195
+ - [Chat](#chat)
158
196
  - [Feature Suggestions](#feature-suggestions)
159
197
  - [Change Log](#change-log)
160
198
  - [Contributing](#contributing)
161
199
  - [Contributors](#contributors)
200
+ - [Hire Me](#hire-me)
162
201
  - [License](#license)
163
202
 
164
203
  ## Background
@@ -185,38 +224,52 @@ https://www.eclipse.org/swt/faq.php
185
224
  ## Pre-requisites
186
225
 
187
226
  - SWT 4.15 (comes included in Glimmer gem)
188
- - JRuby 9.2.11.1 (supporting Ruby 2.5.x syntax) (find at [https://www.jruby.org/download](https://www.jruby.org/download))
227
+ - JRuby 9.2.12.0 (supporting Ruby 2.5.x syntax) (find at [https://www.jruby.org/download](https://www.jruby.org/download))
189
228
  - JDK 8 - 10 (find at [https://www.oracle.com/java/technologies/javase-downloads.html](https://www.oracle.com/java/technologies/javase-downloads.html))
190
229
  - (Optional) RVM is needed for [Scaffolding](#scaffolding) only (find at [https://rvm.io/](https://rvm.io/))
191
230
 
192
231
  On **Mac** and **Linux**, an easy way to obtain JRuby is through [RVM](http://rvm.io) by running:
193
232
 
194
233
  ```bash
195
- rvm install jruby-9.2.11.1
234
+ rvm install jruby-9.2.12.0
196
235
  ```
197
236
 
198
237
  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.
199
238
 
200
239
  ## Setup
201
240
 
202
- Please follow these instructions to make the `glimmer` command available on your system.
241
+ 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.
203
242
 
204
- ### Option 1: Direct Install
243
+ 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)).
244
+
245
+ If you intend to build a Glimmer app from scratch on the Mac, pick Option 1 ([Direct Install](#option-1-direct-install)) to leverage [Glimmer Scaffolding](#scaffolding) (only available on the Mac).
246
+
247
+ Otherwise, Option 2 ([Bundler](#option-2-bundler)) is recommended for building Glimmer apps on other platforms (Windows and Linux).
248
+
249
+ ### Option 1: Direct Install
250
+ (Use for [Scaffolding](#scaffolding) on the Mac)
205
251
 
206
252
  Run this command to install directly:
207
253
  ```
208
- jgem install glimmer-dsl-swt -v 0.1.0
254
+ jgem install glimmer-dsl-swt -v 0.4.1
209
255
  ```
210
256
 
211
257
  `jgem` is JRuby's version of `gem` command.
212
258
  RVM allows running `gem` as an alias.
213
259
  Otherwise, you may also run `jruby -S gem install ...`
214
260
 
215
- ### Option 2: Bundler
261
+ 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.
262
+
263
+ 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.
264
+
265
+ Note: if you're using activerecord or activesupport, keep in mind that Glimmer unhooks ActiveSupport::Dependencies as it does not rely on it.
266
+
267
+ ### Option 2: Bundler
268
+ (Use for Manual App Creation)
216
269
 
217
270
  Add the following to `Gemfile`:
218
271
  ```
219
- gem 'glimmer-dsl-swt', '~> 0.1.0'
272
+ gem 'glimmer-dsl-swt', '~> 0.4.1'
220
273
  ```
221
274
 
222
275
  And, then run:
@@ -224,10 +277,16 @@ And, then run:
224
277
  jruby -S bundle install
225
278
  ```
226
279
 
227
- You may learn more about other Glimmer related gems at [Multi-DSL Support](#multi-dsl-support)
280
+ Note: if you're using activerecord or activesupport, keep in mind that Glimmer unhooks ActiveSupport::Dependencies as it does not rely on it.
281
+
282
+ 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)
228
283
 
229
284
  ## Glimmer Command
230
285
 
286
+ The `glimmer` command allows you to run, scaffold, package, and list Glimmer applications/gems.
287
+
288
+ If you are new to Glimmer, you may read the Basic Usage section and skip the rest until you have gone through [Girb (Glimmer irb) Command](#girb-glimmer-irb-command), [Glimmer DSL Syntax](#glimmer-dsl-syntax), and [Samples](#samples).
289
+
231
290
  ### Basic Usage
232
291
 
233
292
  ```
@@ -264,7 +323,11 @@ Either a single task or one or more applications may be specified.
264
323
  When a task is specified, it runs via rake. Some tasks take arguments in square brackets.
265
324
 
266
325
  Available tasks are below (you may also lookup by adding `require 'glimmer/rake_task'` in Rakefile and running rake -T):
326
+ glimmer list:custom_shell_gems[query] # List Glimmer custom shell gems available at rubygems.org (query is optional)
327
+ glimmer list:custom_widget_gems[query] # List Glimmer custom widget gems available at rubygems.org (query is optional)
328
+ glimmer list:dsl_gems[query] # List Glimmer DSL gems available at rubygems.org (query is optional)
267
329
  glimmer package # Package app for distribution (generating config, jar, and native files)
330
+ glimmer package:clean # Clean by removing "dist" and "packages" directories
268
331
  glimmer package:config # Generate JAR config file
269
332
  glimmer package:jar # Generate JAR file
270
333
  glimmer package:native # Generate Native files (DMG/PKG/APP on the Mac)
@@ -362,6 +425,10 @@ Eventually, it will launch an advanced "Hello, World!" app window having the tit
362
425
 
363
426
  ![Glimmer Scaffold App](images/glimmer-scaffolding-app.png)
364
427
 
428
+ On the Mac, it also comes with a boilerplate Preferences dialog.
429
+
430
+ ![Glimmer Scaffold App Preferences](images/glimmer-scaffolding-app-preferences.png)
431
+
365
432
  #### Custom Shell
366
433
 
367
434
  To scaffold a Glimmer custom shell (full window view) for an existing Glimmer app, run the following command:
@@ -417,11 +484,133 @@ The Ruby gem name will follow the convention "glimmer-cw-customwidgetname-namesp
417
484
 
418
485
  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)
419
486
 
420
- Example: [https://github.com/AndyObtiva/glimmer-cw-video](https://github.com/AndyObtiva/glimmer-cw-video)
487
+ Examples:
488
+
489
+ - [glimmer-cw-video](https://github.com/AndyObtiva/glimmer-cw-video): Video Widget
490
+ - [glimmer-cw-cdatetime-nebula](https://github.com/AndyObtiva/glimmer-cw-cdatetime-nebula): Nebula CDateTime Widget
491
+
492
+ ### Gem Listing
493
+
494
+ 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).
495
+
496
+ #### Listing Custom Shell Gems
497
+
498
+ 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):
499
+
500
+ ```
501
+ glimmer list:custom_shell_gems[query] # List Glimmer custom shell gems available at rubygems.org (query is optional)
502
+ ```
503
+
504
+ Example:
505
+
506
+ ```
507
+ glimmer list:custom_shell_gems
508
+ ```
509
+
510
+ Output:
511
+
512
+ ```
513
+
514
+ Glimmer Custom Shell Gems at rubygems.org:
515
+
516
+ Name Gem Version Author Description
517
+
518
+ Calculator glimmer-cs-calculator 1.0.1 Andy Maleh Calculator - Glimmer Custom Shell
519
+ Gladiator glimmer-cs-gladiator 0.2.0 Andy Maleh Gladiator (Glimmer Editor) - Glimmer Custom Shell
520
+
521
+ ```
522
+
523
+ #### Listing Custom Widget Gems
524
+
525
+ 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):
526
+
527
+ ```
528
+ glimmer list:custom_widget_gems[query] # List Glimmer custom widget gems available at rubygems.org (query is optional)
529
+ ```
530
+
531
+ Example:
532
+
533
+ Check if there is a custom video widget for Glimmer.
534
+
535
+ ```
536
+ glimmer list:custom_widget_gems[video]
537
+ ```
538
+
539
+ Output:
540
+
541
+ ```
542
+
543
+ Glimmer Custom Widget Gems matching [video] at rubygems.org:
544
+
545
+ Name Gem Version Author Description
546
+
547
+ Video glimmer-cw-video 0.1.1 Andy Maleh Glimmer Custom Widget - Video
548
+
549
+ ```
550
+
551
+ #### Listing DSL Gems
552
+
553
+ 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):
554
+
555
+ ```
556
+ glimmer list:dsl_gems[query] # List Glimmer DSL gems available at rubygems.org (query is optional)
557
+ ```
558
+
559
+ Example:
560
+
561
+ ```
562
+ glimmer list:dsl_gems
563
+ ```
564
+
565
+ Output:
566
+
567
+ ```
568
+
569
+ Glimmer DSL Gems at rubygems.org:
570
+
571
+ Name Gem Version Author Description
572
+
573
+ Css glimmer-dsl-css 0.1.0 AndyMaleh Glimmer DSL for CSS
574
+ Opal glimmer-dsl-opal 0.0.9 AndyMaleh Glimmer DSL for Opal
575
+ Swt glimmer-dsl-swt 0.4.1 AndyMaleh Glimmer DSL for SWT
576
+ Xml glimmer-dsl-xml 0.1.0 AndyMaleh Glimmer DSL for XML
577
+
578
+ ```
579
+
580
+ ### Packaging
581
+
582
+ Glimmer packaging tasks are detailed under [Packaging & Distribution](#packaging--distribution).
583
+
584
+ ### Raw JRuby Command
585
+
586
+ If there is a need to run Glimmer directly via the `jruby` command, you
587
+ may run the following:
588
+
589
+ ```
590
+ jruby -J-classpath "path_to/swt.jar" -r glimmer -S application.rb
591
+ ```
592
+
593
+ The `-J-classpath` option specifies the `swt.jar` file path, which can be a
594
+ 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.
595
+
596
+ The `-r` option preloads (requires) the `glimmer` library in Ruby.
597
+
598
+ The `-S` option specifies a script to run.
599
+
600
+ #### Mac Support
601
+
602
+ The Mac is well supported with the `glimmer` command. The advice below is not needed if you are using it.
603
+
604
+ 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).
605
+
606
+ Example:
607
+ ```
608
+ jruby -J-XstartOnFirstThread -J-classpath "path_to/swt.jar" -r glimmer -S application.rb
609
+ ```
421
610
 
422
611
  ## Girb (Glimmer irb) Command
423
612
 
424
- With Glimmer installed, you may want to run `girb` instead of standard `irb` to have SWT preloaded and the Glimmer library required and included for quick Glimmer coding/testing.
613
+ With `glimmer-dsl-swt` installed, you may want to run `girb` instead of standard `irb` to have SWT preloaded and the Glimmer library required and included for quick Glimmer coding/testing.
425
614
 
426
615
  ```
427
616
  girb
@@ -441,13 +630,13 @@ Keep in mind that all samples live under [https://github.com/AndyObtiva/glimmer-
441
630
 
442
631
  Glimmer DSL syntax consists of static keywords and dynamic keywords to build and bind user-interface objects.
443
632
 
444
- Static keywords are pre-identified keywords in the Glimmer DSL, such as `shell`, `rgb`, and `bind`.
633
+ Static keywords are pre-identified keywords in the Glimmer DSL, such as `shell`, `message_box`, `async_exec`, and `bind`.
445
634
 
446
- Dynamic keywords are dynamically figured out from available SWT widgets, custom widgets, and properties. Examples are: `label`, `combo`, and `text`.
635
+ Dynamic keywords are dynamically figured out from available SWT widgets, custom widgets, and properties. Examples are: `label`, `combo`, and `list`.
447
636
 
448
- 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.
637
+ 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.
449
638
 
450
- For example, if a project adds this custom SWT library:
639
+ For example, if a project adds this custom Java SWT library:
451
640
 
452
641
  https://www.eclipse.org/nebula/widgets/cdatetime/cdatetime.php?page=operation
453
642
 
@@ -540,22 +729,22 @@ Check out the [samples](samples) directory for more examples.
540
729
 
541
730
  Example from [hello_tab.rb](samples/hello/hello_tab.rb) sample (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
542
731
 
543
- ![Hello Tab 1](images/glimmer-hello-tab1.png)
732
+ ![Hello Tab English](images/glimmer-hello-tab-english.png)
544
733
 
545
- ![Hello Tab 2](images/glimmer-hello-tab2.png)
734
+ ![Hello Tab French](images/glimmer-hello-tab-french.png)
546
735
 
547
736
  ```ruby
548
737
  shell {
549
- text "SWT"
738
+ text "Hello, Tab!"
550
739
  tab_folder {
551
740
  tab_item {
552
- text "Tab 1"
741
+ text "English"
553
742
  label {
554
743
  text "Hello, World!"
555
744
  }
556
745
  }
557
746
  tab_item {
558
- text "Tab 2"
747
+ text "French"
559
748
  label {
560
749
  text "Bonjour Univers!"
561
750
  }
@@ -575,7 +764,7 @@ automatically uses the display created earlier without having to explicitly hook
575
764
  ```ruby
576
765
  @display = display {
577
766
  cursor_location 300, 300
578
- on_event_keydown {
767
+ on_swt_keydown {
579
768
  # ...
580
769
  }
581
770
  # ...
@@ -627,27 +816,34 @@ Example (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
627
816
  @shell.open
628
817
  ```
629
818
 
630
- ##### `#swt_widget`
819
+ ##### `message_box`
631
820
 
632
- 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.
821
+ 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.
633
822
 
634
823
  Example (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
635
824
 
636
825
  ```ruby
826
+ include Glimmer
827
+
637
828
  @shell = shell {
829
+ text 'Hello, Message Box!'
638
830
  button {
639
- text "Press Me"
831
+ text 'Please Click To Win a Surprise'
640
832
  on_widget_selected {
641
- message_box = MessageBox.new(@shell.swt_widget) # passing SWT Shell widget
642
- message_box.setText("Surprise")
643
- message_box.setMessage("You have won $1,000,000!")
644
- message_box.open
833
+ message_box(@shell) {
834
+ text 'Surprise'
835
+ message "Congratulations!\n\nYou have won $1,000,000!"
836
+ }.open
645
837
  }
646
838
  }
647
839
  }
648
840
  @shell.open
649
841
  ```
650
842
 
843
+ ##### `#swt_widget`
844
+
845
+ 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.
846
+
651
847
  ##### Shell widget proxy methods
652
848
 
653
849
  Shell widget proxy has extra methods specific to SWT Shell:
@@ -675,7 +871,7 @@ Glimmer DSL provides support for SWT Menu and MenuItem widgets.
675
871
 
676
872
  There are 2 main types of menus in SWT:
677
873
  - Menu Bar (shows up on top)
678
- - Pop Up Menu (shows up when right-clicking a widget)
874
+ - Pop Up Context Menu (shows up when right-clicking a widget)
679
875
 
680
876
  Underneath both types, there can be a 3rd menu type called Drop Down.
681
877
 
@@ -683,39 +879,63 @@ Glimmer provides special support for Drop Down menus as it automatically instant
683
879
 
684
880
  The ampersand symbol indicates the keyboard shortcut key for the menu item (e.g. '&Help' can be triggered on Windows by hitting ALT+H)
685
881
 
686
- Example [Menu Bar] (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
882
+ Example of a Menu Bar (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
687
883
 
688
884
  ```ruby
689
- shell {
885
+ shell { |shell_proxy|
886
+ text 'Hello, Menu Bar!'
887
+ grid_layout
888
+ label(:center) {
889
+ font height: 16
890
+ text 'Check Out The File Menu and History Menu in The Menu Bar Above!'
891
+ }
690
892
  menu_bar {
691
893
  menu {
692
- text "&File"
894
+ text '&File'
693
895
  menu_item {
694
- text "E&xit"
896
+ text 'E&xit'
695
897
  }
696
898
  menu_item(0) {
697
- text "&New"
899
+ text '&New'
900
+ on_widget_selected {
901
+ message_box(shell_proxy) {
902
+ text 'New File'
903
+ message 'New File Contents'
904
+ }.open
905
+ }
698
906
  }
699
907
  menu(1) {
700
- text "&Options"
908
+ text '&Options'
701
909
  menu_item(:radio) {
702
- text "Option 1"
910
+ text 'Option 1'
703
911
  }
704
912
  menu_item(:separator)
705
913
  menu_item(:check) {
706
- text "Option 3"
914
+ text 'Option 3'
707
915
  }
708
916
  }
709
917
  }
710
918
  menu {
711
- text "&History"
919
+ text '&History'
712
920
  menu {
713
- text "&Recent"
921
+ text '&Recent'
714
922
  menu_item {
715
- text "File 1"
923
+ text 'File 1'
924
+ on_widget_selected {
925
+ message_box(shell_proxy) {
926
+ text 'File 1'
927
+ message 'File 1 Contents'
928
+ }.open
929
+ }
716
930
  }
717
931
  menu_item {
718
- text "File 2"
932
+ text 'File 2'
933
+ on_widget_selected {
934
+ message_box(shell_proxy) {
935
+ text 'File 2'
936
+ message 'File 2 Contents'
937
+ }.open
938
+ }
719
939
  }
720
940
  }
721
941
  }
@@ -723,22 +943,37 @@ shell {
723
943
  }.open
724
944
  ```
725
945
 
726
- Example [Pop Up Menu] (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
946
+ Example of a Pop Up Context Menu (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
727
947
 
728
948
  ```ruby
729
- shell {
949
+ shell { |shell_proxy|
950
+ text 'Hello, Pop Up Context Menu!'
951
+ grid_layout
730
952
  label {
731
- text 'Right-Click Me'
953
+ font height: 16
954
+ text 'Right-Click To Pop Up a Context Menu'
732
955
  menu {
733
956
  menu {
734
957
  text '&History'
735
958
  menu {
736
- text "&Recent"
959
+ text '&Recent'
737
960
  menu_item {
738
- text "File 1"
961
+ text 'File 1'
962
+ on_widget_selected {
963
+ message_box(shell_proxy) {
964
+ text 'File 1'
965
+ message 'File 1 Contents'
966
+ }.open
967
+ }
739
968
  }
740
969
  menu_item {
741
- text "File 2"
970
+ text 'File 2'
971
+ on_widget_selected {
972
+ message_box(shell_proxy) {
973
+ text 'File 2'
974
+ message 'File 2 Contents'
975
+ }.open
976
+ }
742
977
  }
743
978
  }
744
979
  }
@@ -747,6 +982,13 @@ shell {
747
982
  }.open
748
983
  ```
749
984
 
985
+ #### ScrolledComposite
986
+
987
+ Glimmer provides smart defaults for the `scrolled_composite` widget by:
988
+ - Automatically setting the nested widget as its content (meaning use can just like a plain old `composite` to add scrolling)
989
+ - 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 )
990
+ - Automatically setting the expand horizontal and expand vertical SWT properties to `true`
991
+
750
992
  ### Widget Styles
751
993
 
752
994
  SWT widgets receive `SWT` styles in their constructor as per this guide:
@@ -992,9 +1234,12 @@ composite {
992
1234
  ```
993
1235
 
994
1236
  Here is a more sophisticated example taken from [hello_computed.rb](samples/hello/hello_computed.rb) sample:
1237
+
1238
+ ![Hello Computed](images/glimmer-hello-computed.png)
1239
+
995
1240
  ```ruby
996
1241
  shell {
997
- text "Hello Computed"
1242
+ text 'Hello, Computed!'
998
1243
  composite {
999
1244
  grid_layout {
1000
1245
  num_columns 2
@@ -1002,44 +1247,44 @@ shell {
1002
1247
  horizontal_spacing 20
1003
1248
  vertical_spacing 10
1004
1249
  }
1005
- label {text "First &Name: "}
1250
+ label {text 'First &Name: '}
1006
1251
  text {
1007
1252
  text bind(@contact, :first_name)
1008
1253
  layout_data {
1009
- horizontalAlignment :fill
1010
- grabExcessHorizontalSpace true
1254
+ horizontal_alignment :fill
1255
+ grab_excess_horizontal_space true
1011
1256
  }
1012
1257
  }
1013
- label {text "&Last Name: "}
1258
+ label {text '&Last Name: '}
1014
1259
  text {
1015
1260
  text bind(@contact, :last_name)
1016
1261
  layout_data {
1017
- horizontalAlignment :fill
1018
- grabExcessHorizontalSpace true
1262
+ horizontal_alignment :fill
1263
+ grab_excess_horizontal_space true
1019
1264
  }
1020
1265
  }
1021
- label {text "&Year of Birth: "}
1266
+ label {text '&Year of Birth: '}
1022
1267
  text {
1023
1268
  text bind(@contact, :year_of_birth)
1024
1269
  layout_data {
1025
- horizontalAlignment :fill
1026
- grabExcessHorizontalSpace true
1270
+ horizontal_alignment :fill
1271
+ grab_excess_horizontal_space true
1027
1272
  }
1028
1273
  }
1029
- label {text "Name: "}
1274
+ label {text 'Name: '}
1030
1275
  label {
1031
1276
  text bind(@contact, :name, computed_by: [:first_name, :last_name])
1032
1277
  layout_data {
1033
- horizontalAlignment :fill
1034
- grabExcessHorizontalSpace true
1278
+ horizontal_alignment :fill
1279
+ grab_excess_horizontal_space true
1035
1280
  }
1036
1281
  }
1037
- label {text "Age: "}
1282
+ label {text 'Age: '}
1038
1283
  label {
1039
1284
  text bind(@contact, :age, on_write: :to_i, computed_by: [:year_of_birth])
1040
1285
  layout_data {
1041
- horizontalAlignment :fill
1042
- grabExcessHorizontalSpace true
1286
+ horizontal_alignment :fill
1287
+ grab_excess_horizontal_space true
1043
1288
  }
1044
1289
  }
1045
1290
  }
@@ -1182,6 +1427,10 @@ Example from [samples/hello/hello_combo.rb](samples/hello_combo.rb) sample (you
1182
1427
 
1183
1428
  #### Combo
1184
1429
 
1430
+ 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.
1431
+
1432
+ When data-binding a `combo` widget, Glimmer can automatically deduce available options from data-bound model by convention: `{attribute_name}_options` method.
1433
+
1185
1434
  ![Hello Combo](images/glimmer-hello-combo.png)
1186
1435
 
1187
1436
  ![Hello Combo](images/glimmer-hello-combo-expanded.png)
@@ -1223,7 +1472,7 @@ end
1223
1472
  HelloCombo.new.launch
1224
1473
  ```
1225
1474
 
1226
- `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.
1475
+ `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.
1227
1476
 
1228
1477
  #### List
1229
1478
 
@@ -1337,6 +1586,9 @@ shell {
1337
1586
  }
1338
1587
  items bind(group, :people), column_properties(:name, :age, :adult)
1339
1588
  selection bind(group, :selected_person)
1589
+ on_mouse_up { |event|
1590
+ @table.edit_table_item(event.table_item, event.column_index)
1591
+ }
1340
1592
  }
1341
1593
  }
1342
1594
  ```
@@ -1344,6 +1596,7 @@ shell {
1344
1596
  The code above includes two data-bindings:
1345
1597
  - 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.
1346
1598
  - 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)
1599
+ - 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.)
1347
1600
 
1348
1601
  Additionally, Table `items` data-binding automatically stores each node model unto the SWT TableItem object via `setData` method. This enables things like searchability.
1349
1602
 
@@ -1363,6 +1616,67 @@ This automatically leverages the SWT TableEditor custom class behind the scenes,
1363
1616
  passed table item text into something else.
1364
1617
  It automatically persists the change to `items` data-bound model on ENTER/FOCUS-OUT or cancels on ESC/NO-CHANGE.
1365
1618
 
1619
+ ##### Table Sorting
1620
+
1621
+ Glimmer automatically adds sorting support to the SWT `Table` widget.
1622
+
1623
+ Check out the [Contact Manager](#contact-manager) sample for an example.
1624
+ You may click on any column and it will sort by ascending order first and descending if you click again.
1625
+
1626
+ Glimmer automatic table sorting supports `String`, `Integer`, and `Float` columns out of the box as well as any column data that is comparable.
1627
+
1628
+ 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`.
1629
+
1630
+ Should you have a special data type that could not be compared automatically, Glimmer offers the following 3 alternatives for custom sorting:
1631
+ - `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`).
1632
+ - `sort_by(&block)`: this works just like Ruby `Enumerable` `sort_by`. The block receives the table column data as argument.
1633
+ - `sort(&comparator)`: this works just like Ruby `Enumerable` `sort`. The comparator block receives two objects from the table column data.
1634
+
1635
+ 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)
1636
+
1637
+ Example:
1638
+
1639
+ ```ruby
1640
+ # ...
1641
+ table {
1642
+ table_column {
1643
+ text 'Task'
1644
+ width 120
1645
+ }
1646
+ table_column {
1647
+ text 'Project'
1648
+ width 120
1649
+ }
1650
+ table_column {
1651
+ text 'Duration (hours)'
1652
+ width 120
1653
+ sort_property :duration_in_hours
1654
+ }
1655
+ table_column {
1656
+ text 'Priority'
1657
+ width 120
1658
+ sort_by { |value| ['High', 'Medium', 'Low'].index(value) }
1659
+ }
1660
+ table_column {
1661
+ text 'Start Date'
1662
+ width 120
1663
+ sort { |d1, d2| d1.to_date <=> d2.to_date }
1664
+ }
1665
+ additional_sort_properties :project_name, :duration_in_hours, :name
1666
+ items bind(Task, :list), column_properties(:name, :project_name, :duration, :priority, :start_date)
1667
+ # ...
1668
+ }
1669
+ # ...
1670
+ ```
1671
+
1672
+ Here is an explanation of the example above:
1673
+ - Task and Project table columns are data-bound to the `:name` and `:project_name` properties and sorted through them automatically
1674
+ - Task Duration table column is data-bound to the `:duration` property, but sorted via the `:duration_in_hours` property instead
1675
+ - Task Priority table column has a custom sort_by block
1676
+ - Task Start Date table column has a custom sort comparator block
1677
+ - Additional (secondary) sort properties are applied when sorting by Task, Project, or Duration in the order specified
1678
+
1679
+
1366
1680
  #### Tree
1367
1681
 
1368
1682
  The SWT Tree widget visualizes a tree data-structure, such as an employment or composition hierarchy.
@@ -1410,10 +1724,10 @@ Glimmer comes with `Observer` module, which is used internally for data-binding,
1410
1724
 
1411
1725
  Glimmer supports observing widgets with two main types of events:
1412
1726
  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`).
1413
- 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)
1727
+ 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)
1414
1728
 
1415
1729
  Additionally, there are two more types of events:
1416
- - SWT `display` supports global listeners called filters that run on any widget. They are hooked via `on_event_{swt-event-constant}`
1730
+ - SWT `display` supports global listeners called filters that run on any widget. They are hooked via `on_swt_{swt-event-constant}`
1417
1731
  - SWT `display` supports Mac application menu item observers (`on_about` and `on_preferences`), which you can read about under [Miscellaneous](#miscellaneous).
1418
1732
 
1419
1733
  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.
@@ -1458,21 +1772,21 @@ Note that every Tic Tac Toe grid cell has its `text` and `enabled` properties da
1458
1772
 
1459
1773
  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.
1460
1774
 
1461
- **Regarding number 2**, you can figure out all available events by looking at the `org.eclipse.swt.SWT` API:
1775
+ **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:
1462
1776
 
1463
1777
  https://help.eclipse.org/2019-12/nftopic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/SWT.html
1464
1778
 
1465
1779
  Example (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
1466
1780
 
1467
- `SWT.Show` - hooks a listener for showing a widget (using `on_event_show` in Glimmer)
1468
- `SWT.Hide` - hooks a listener for hiding a widget (using `on_event_hide` in Glimmer)
1781
+ `SWT.Show` - hooks a listener for showing a widget (using `on_swt_show` in Glimmer)
1782
+ `SWT.Hide` - hooks a listener for hiding a widget (using `on_swt_hide` in Glimmer)
1469
1783
 
1470
1784
  ```ruby
1471
1785
  shell {
1472
1786
  @button1 = button {
1473
1787
  text "Show 2nd Button"
1474
1788
  visible true
1475
- on_event_show {
1789
+ on_swt_show {
1476
1790
  @button2.swt_widget.setVisible(false)
1477
1791
  }
1478
1792
  on_widget_selected {
@@ -1482,7 +1796,7 @@ shell {
1482
1796
  @button2 = button {
1483
1797
  text "Show 1st Button"
1484
1798
  visible false
1485
- on_event_show {
1799
+ on_swt_show {
1486
1800
  @button1.swt_widget.setVisible(false)
1487
1801
  }
1488
1802
  on_widget_selected {
@@ -1492,7 +1806,7 @@ shell {
1492
1806
  }.open
1493
1807
  ```
1494
1808
 
1495
- **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`
1809
+ **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`
1496
1810
 
1497
1811
  ##### Alternative Syntax
1498
1812
 
@@ -1535,7 +1849,7 @@ class TicTacToe
1535
1849
  end
1536
1850
  ```
1537
1851
 
1538
- Observers can be a good mechanism for displaying dialog messages in Glimmer (using SWT's `MessageBox`).
1852
+ 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).
1539
1853
 
1540
1854
  Look at [`samples/elaborate/tictactoe/tic_tac_toe.rb`](samples/tictactoe/tic_tac_toe.rb) for more details starting with the code included below.
1541
1855
 
@@ -1561,10 +1875,10 @@ class TicTacToe
1561
1875
  end
1562
1876
 
1563
1877
  def display_game_over_message(message)
1564
- message_box = MessageBox.new(@shell.swt_widget)
1565
- message_box.setText("Game Over")
1566
- message_box.setMessage(message)
1567
- message_box.open
1878
+ message_box(@shell) {
1879
+ text 'Game Over'
1880
+ message message_text
1881
+ }.open
1568
1882
  @tic_tac_toe_board.reset
1569
1883
  end
1570
1884
  # ...
@@ -1605,7 +1919,7 @@ shell {
1605
1919
 
1606
1920
  As you can see, `RedLabel` became Glimmer DSL keyword: `red_label`
1607
1921
 
1608
- #### Hook Example
1922
+ #### Lifecycle Hook Example
1609
1923
 
1610
1924
  (you may copy/paste in [`girb`](#girb-glimmer-irb-command))
1611
1925
 
@@ -1640,10 +1954,12 @@ shell {
1640
1954
  }.open
1641
1955
  ```
1642
1956
 
1643
- Notice how `Red::Composite` became `red__composite` with double-underscore, which is how Glimmer Custom Widgets signify namespaces by convention. Additionally, `before_body` hook was utilized to set a `@color` variable and use inside the `body`.
1957
+ Notice how `Red::Composite` became `red__composite` with double-underscore, which is how Glimmer Custom Widgets signify namespaces by convention. Additionally, the `before_body` lifecycle hook was utilized to set a `@color` variable and use inside the `body`.
1644
1958
 
1645
1959
  Keep in mind that namespaces are not needed to be specified if the Custom Widget class has a unique name, not clashing with a basic SWT widget or another custom widget name.
1646
1960
 
1961
+ #### Custom Widget API
1962
+
1647
1963
  Custom Widgets have the following attributes available to call from inside the `#body` method:
1648
1964
  - `#parent`: Glimmer object parenting custom widget
1649
1965
  - `#swt_style`: SWT style integer. Can be useful if you want to allow consumers to customize a widget inside the custom widget body
@@ -1698,7 +2014,9 @@ shell {
1698
2014
 
1699
2015
  Notice how `:no_focus` was the `swt_style` value, followed by the `options` hash `{orientation: :horizontal, bg_color: :white}`, and finally the `content` block containing the label with `'SANDWICH CONTENT'`
1700
2016
 
1701
- Last but not least, these are the available hooks:
2017
+ #### Custom Widget Lifecycle Hooks
2018
+
2019
+ Last but not least, these are the available lifecycle hooks:
1702
2020
  - `before_body`: takes a block that executes in the custom widget instance scope before calling `body`. Useful for initializing variables to later use in `body`
1703
2021
  - `after_body`: takes a block that executes in the custom widget instance scope after calling `body`. Useful for setting up observers on widgets built in `body` (set in instance variables) and linking to other shells.
1704
2022
 
@@ -1732,6 +2050,11 @@ body {
1732
2050
 
1733
2051
  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`.
1734
2052
 
2053
+ #### Final Notes
2054
+
2055
+ 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:
2056
+ [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)
2057
+
1735
2058
  ### Custom Shells
1736
2059
 
1737
2060
  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.
@@ -1777,7 +2100,7 @@ shell { |app_shell|
1777
2100
  @current_step_number = 1
1778
2101
  @wizard_steps = 5.times.map { |n|
1779
2102
  wizard_step(number: n+1, step_count: 5) {
1780
- on_event_hide {
2103
+ on_swt_hide {
1781
2104
  if @current_step_number < 5
1782
2105
  @current_step_number += 1
1783
2106
  app_shell.hide
@@ -1797,6 +2120,62 @@ shell { |app_shell|
1797
2120
  }.open
1798
2121
  ```
1799
2122
 
2123
+ ### Drag and Drop
2124
+
2125
+ Glimmer offers Drag and Drop support, thanks to [SWT](https://www.eclipse.org/swt/) and Glimmer's lightweight [DSL syntax](#glimmer-dsl-syntax).
2126
+
2127
+ 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)
2128
+
2129
+ To get started, simply follow these steps:
2130
+ 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)
2131
+ 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)
2132
+ 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)
2133
+ 1. Read `event.data` and consume it (e.g. change widget text) inside the `on_drop` event handler block.
2134
+
2135
+ Example (taken from [samples/hello/hello_drag_and_drop.rb](#hello-drag-and-drop) / you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
2136
+
2137
+ ```ruby
2138
+ class Location
2139
+ attr_accessor :country
2140
+
2141
+ def country_options
2142
+ %w[USA Canada Mexico Columbia UK Australia Germany Italy Spain]
2143
+ end
2144
+ end
2145
+
2146
+ @location = Location.new
2147
+
2148
+ include Glimmer
2149
+
2150
+ shell {
2151
+ text 'Hello, Drag and Drop!'
2152
+ list {
2153
+ selection bind(@location, :country)
2154
+ on_drag_set_data { |event|
2155
+ list = event.widget.getControl
2156
+ event.data = list.getSelection.first
2157
+ }
2158
+ }
2159
+ label(:center) {
2160
+ text 'Drag a country here!'
2161
+ font height: 20
2162
+ on_drop { |event|
2163
+ event.widget.getControl.setText(event.data)
2164
+ }
2165
+ }
2166
+ }.open
2167
+ ```
2168
+
2169
+ ![Hello Drag and Drop](images/glimmer-hello-drag-and-drop.gif)
2170
+
2171
+ Optional steps:
2172
+ - 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.
2173
+ - Specify `drag_source_style` operation (may be: :drop_copy (default), :drop_link, :drop_move, :drop_none, or an array of multiple operations)
2174
+ - 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)
2175
+ - Specify `drop_target_style` operation (may be: :drop_copy (default), :drop_link, :drop_move, :drop_none, or an array of multiple operations)
2176
+ - 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)
2177
+ - Set drag operation in `event.detail` (e.g. DND::DROP_COPY) inside `on_drag_enter`
2178
+
1800
2179
  ### Miscellaneous
1801
2180
 
1802
2181
  #### Multi-DSL Support
@@ -1952,10 +2331,10 @@ class Example
1952
2331
  def initialize
1953
2332
  display {
1954
2333
  on_about {
1955
- message_box = MessageBox.new(@shell_proxy.swt_widget)
1956
- message_box.setText("About")
1957
- message_box.setMessage("About Application")
1958
- message_box.open
2334
+ message_box(@shell_proxy) {
2335
+ text 'About'
2336
+ message 'About Application'
2337
+ }.open
1959
2338
  }
1960
2339
  on_preferences {
1961
2340
  preferences_dialog = dialog {
@@ -2021,7 +2400,7 @@ Also, you may invoke `Display.setAppVersion('1.0.0')` if needed for OS app versi
2021
2400
 
2022
2401
  #### Video Widget
2023
2402
 
2024
- ![Video Widget](images/glimmer-video-widget.png)
2403
+ [![Video Widget](images/glimmer-video-widget.png)](https://github.com/AndyObtiva/glimmer-cw-video)
2025
2404
 
2026
2405
  Glimmer supports a [video custom widget](https://github.com/AndyObtiva/glimmer-cw-video) not in SWT.
2027
2406
 
@@ -2029,7 +2408,9 @@ You may obtain via `glimmer-cw-video` gem.
2029
2408
 
2030
2409
  #### Browser Widget
2031
2410
 
2032
- 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).
2411
+ ![Hello Browser](images/glimmer-hello-browser.png)
2412
+
2413
+ 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).
2033
2414
 
2034
2415
  Example loading a URL (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
2035
2416
 
@@ -2065,6 +2446,100 @@ shell {
2065
2446
 
2066
2447
  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).
2067
2448
 
2449
+ ## Glimmer Configuration
2450
+
2451
+ Glimmer configuration may be done via the `Glimmer::Config` module.
2452
+
2453
+ ### logger
2454
+
2455
+ Glimmer supports logging via a standard `STDOUT` Ruby `Logger` configured in the `Glimmer::Config.logger` config option.
2456
+ It is set to level Logger::ERROR by default.
2457
+ Log level may be adjusted via `Glimmer::Config.logger.level` just like any other Ruby Logger.
2458
+ It may be replaced with a custom logger via `Glimmer::Config.logger = custom_logger`
2459
+ 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.
2460
+
2461
+ Example:
2462
+
2463
+ ```ruby
2464
+ Glimmer::Config.logger.level = :debug
2465
+ ```
2466
+ This results in more verbose debug loggging to `STDOUT`, which is very helpful in troubleshooting Glimmer DSL syntax when needed.
2467
+
2468
+ Example log:
2469
+ ```
2470
+ D, [2017-07-21T19:23:12.587870 #35707] DEBUG -- : method: shell and args: []
2471
+ D, [2017-07-21T19:23:12.594405 #35707] DEBUG -- : ShellCommandHandler will handle command: shell with arguments []
2472
+ D, [2017-07-21T19:23:12.844775 #35707] DEBUG -- : method: composite and args: []
2473
+ D, [2017-07-21T19:23:12.845388 #35707] DEBUG -- : parent is a widget: true
2474
+ D, [2017-07-21T19:23:12.845833 #35707] DEBUG -- : on listener?: false
2475
+ D, [2017-07-21T19:23:12.864395 #35707] DEBUG -- : WidgetCommandHandler will handle command: composite with arguments []
2476
+ D, [2017-07-21T19:23:12.864893 #35707] DEBUG -- : widget styles are: []
2477
+ D, [2017-07-21T19:23:12.874296 #35707] DEBUG -- : method: list and args: [:multi]
2478
+ D, [2017-07-21T19:23:12.874969 #35707] DEBUG -- : parent is a widget: true
2479
+ D, [2017-07-21T19:23:12.875452 #35707] DEBUG -- : on listener?: false
2480
+ D, [2017-07-21T19:23:12.878434 #35707] DEBUG -- : WidgetCommandHandler will handle command: list with arguments [:multi]
2481
+ D, [2017-07-21T19:23:12.878798 #35707] DEBUG -- : widget styles are: [:multi]
2482
+ ```
2483
+
2484
+ ### import_swt_packages
2485
+
2486
+ 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.
2487
+
2488
+ As a result, you may call SWT Java classes from Glimmer Ruby code without mentioning Java package references explicitly.
2489
+
2490
+ For example, `org.eclipse.swt.graphics.Color` can be referenced as just `Color`
2491
+
2492
+ 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:
2493
+ ```
2494
+ org.eclipse.swt.*
2495
+ org.eclipse.swt.widgets.*
2496
+ org.eclipse.swt.layout.*
2497
+ org.eclipse.swt.graphics.*
2498
+ org.eclipse.swt.browser.*
2499
+ org.eclipse.swt.custom.*
2500
+ org.eclipse.swt.dnd.*
2501
+ ```
2502
+
2503
+ 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).
2504
+
2505
+ Example:
2506
+
2507
+ ```ruby
2508
+ Glimmer::Config.import_swt_packages += [
2509
+ 'org.eclipse.nebula.widgets.ganttchart'
2510
+ ]
2511
+ ```
2512
+
2513
+ 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)
2514
+
2515
+ Nonetheless, you can disable automatic Java package import if needed via this Glimmer configuration option:
2516
+
2517
+ ```ruby
2518
+ Glimmer::Config.import_swt_packages = false
2519
+ ```
2520
+
2521
+ Once disabled, to import SWT Java packages manually, you may simply:
2522
+
2523
+ 1. `include Glimmer::SWT::Packages`: lazily imports all SWT Java packages to your class, lazy-loading SWT Java class constants on first reference.
2524
+
2525
+ 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'`)
2526
+
2527
+ 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.
2528
+
2529
+ You can learn more about importing Java packages into Ruby code at this JRuby WIKI page:
2530
+
2531
+ https://github.com/jruby/jruby/wiki/CallingJavaFromJRuby
2532
+
2533
+ ### loop_max_count
2534
+
2535
+ Glimmer has infinite loop detection support.
2536
+ It can detect when an infinite loop is about to occur in method_missing and stops it.
2537
+ It detects potential infinite loops when the same keyword and args repeat more than 100 times, which is unusual in a GUI app.
2538
+
2539
+ The max limit can be changed via the `Glimmer::Config::loop_max_count=(count)` config option.
2540
+
2541
+ Infinite loop detection may be disabled altogether if needed by setting `Glimmer::Config::loop_max_count` to `-1`
2542
+
2068
2543
  ## Glimmer Style Guide
2069
2544
 
2070
2545
  - Widgets are declared with underscored lowercase versions of their SWT names minus the SWT package name.
@@ -2080,11 +2555,43 @@ This relies on Glimmer's [Multi-DSL Support](#multi-dsl-support) for building th
2080
2555
  - Custom widget body, before_body, and after_body blocks open their blocks and close them with curly braces.
2081
2556
  - 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.
2082
2557
 
2558
+ ## SWT Reference
2559
+
2560
+ https://www.eclipse.org/swt/docs.php
2561
+
2562
+ Here is the SWT API:
2563
+
2564
+ https://help.eclipse.org/2019-12/nftopic/org.eclipse.platform.doc.isv/reference/api/index.html
2565
+
2566
+ Here is a visual list of SWT widgets:
2567
+
2568
+ https://www.eclipse.org/swt/widgets/
2569
+
2570
+ Here is a textual list of SWT widgets:
2571
+
2572
+ https://help.eclipse.org/2019-12/topic/org.eclipse.platform.doc.isv/guide/swt_widgets_controls.htm?cp=2_0_7_0_0
2573
+
2574
+ Here is a list of SWT style bits as used in widget declaration:
2575
+
2576
+ https://wiki.eclipse.org/SWT_Widget_Style_Bits
2577
+
2578
+ Here is a SWT style bit constant reference:
2579
+
2580
+ https://help.eclipse.org/2019-12/nftopic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/SWT.html
2581
+
2582
+ Here is an SWT Drag and Drop guide:
2583
+
2584
+ https://www.eclipse.org/articles/Article-SWT-DND/DND-in-SWT.html
2585
+
2586
+ Here is an SWT Custom Widget guide:
2587
+
2588
+ https://www.eclipse.org/articles/Article-Writing%20Your%20Own%20Widget/Writing%20Your%20Own%20Widget.htm
2589
+
2083
2590
  ## Samples
2084
2591
 
2085
- Check the [samples](samples) directory for examples on how to write Glimmer applications. To run a sample, make sure to install the `glimmer` gem first and then use the `glimmer` command to run it (alternatively, you may clone the repo, follow [CONTRIBUTING.md](CONTRIBUTING.md) instructions, and run samples locally with development glimmer command: `bin/glimmer`).
2592
+ 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`).
2086
2593
 
2087
- If you cloned the project and followed [CONTRIBUTING.md](CONTRIBUTING.md) instructions, you may run all samples at once via `samples/launch` command:
2594
+ If you cloned the project and followed [CONTRIBUTING.md](CONTRIBUTING.md) instructions, you may run all samples in [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt) at once via `samples/launch` command:
2088
2595
 
2089
2596
  ```
2090
2597
  samples/launch
@@ -2092,168 +2599,306 @@ samples/launch
2092
2599
 
2093
2600
  ### Hello Samples
2094
2601
 
2095
- For "Hello, World!" type samples, check the following:
2602
+ For hello-type simple samples, check the following.
2603
+
2604
+ #### Hello, World! Sample
2605
+
2606
+ Code:
2607
+
2608
+ [samples/hello/hello_world.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/hello/hello_world.rb)
2609
+
2610
+ Run:
2096
2611
 
2097
2612
  ```
2098
2613
  glimmer samples/hello/hello_world.rb
2099
- glimmer samples/hello/hello_browser.rb # demonstrates browser widget
2100
- glimmer samples/hello/hello_tab.rb # demonstrates tabs
2101
- glimmer samples/hello/hello_combo.rb # demonstrates combo data-binding
2102
- glimmer samples/hello/hello_list_single_selection.rb # demonstrates list single-selection data-binding
2103
- glimmer samples/hello/hello_list_multi_selection.rb # demonstrates list multi-selection data-binding
2104
- glimmer samples/hello/hello_computed.rb # demonstrates computed data-binding
2105
2614
  ```
2106
2615
 
2107
- ### Elaborate Samples
2616
+ ![Hello World](images/glimmer-hello-world.png)
2108
2617
 
2109
- For more elaborate samples, check the following:
2618
+ #### Hello, Tab!
2619
+
2620
+ Code:
2621
+
2622
+ [samples/hello/hello_tab.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/hello/hello_tab.rb)
2623
+
2624
+ Run:
2110
2625
 
2111
2626
  ```
2112
- glimmer samples/elaborate/login.rb # demonstrates basic data-binding
2113
- glimmer samples/elaborate/contact_manager.rb # demonstrates table data-binding
2114
- glimmer samples/elaborate/tic_tac_toe.rb # demonstrates a full MVC application
2627
+ glimmer samples/hello/hello_tab.rb
2115
2628
  ```
2116
2629
 
2117
- ### External Samples
2630
+ ![Hello Tab English](images/glimmer-hello-tab-english.png)
2631
+ ![Hello Tab French](images/glimmer-hello-tab-french.png)
2118
2632
 
2119
- #### Glimmer Calculator
2633
+ #### Hello, Combo!
2120
2634
 
2121
- [<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)
2635
+ This sample demonstrates combo data-binding.
2122
2636
 
2123
- [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).
2637
+ Code:
2124
2638
 
2125
- #### Gladiator
2639
+ [samples/hello/hello_combo.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/hello/hello_combo.rb)
2126
2640
 
2127
- [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer-cs-gladiator/v0.1.5/images/glimmer-gladiator.png" />](https://github.com/AndyObtiva/glimmer-cs-gladiator)
2641
+ Run:
2128
2642
 
2129
- [Gladiator](https://github.com/AndyObtiva/glimmer-cs-gladiator) (short for Glimmer Editor) is a Glimmer sample project under on-going development.
2130
- You may check it out to learn how to build a Glimmer Custom Shell gem.
2643
+ ```
2644
+ glimmer samples/hello/hello_combo.rb
2645
+ ```
2131
2646
 
2132
- ## In Production
2647
+ ![Hello Combo](images/glimmer-hello-combo.png)
2648
+ ![Hello Combo Expanded](images/glimmer-hello-combo-expanded.png)
2133
2649
 
2134
- The following production apps have been built with Glimmer:
2650
+ #### Hello, List Single Selection!
2135
2651
 
2136
- [<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
2652
+ This sample demonstrates list single-selection data-binding.
2137
2653
 
2138
- ## SWT Reference
2654
+ Code:
2139
2655
 
2140
- https://www.eclipse.org/swt/docs.php
2656
+ [samples/hello/hello_list_single_selection.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/hello/hello_list_single_selection.rb)
2141
2657
 
2142
- Here is the SWT API:
2658
+ Run:
2143
2659
 
2144
- https://help.eclipse.org/2019-12/nftopic/org.eclipse.platform.doc.isv/reference/api/index.html
2660
+ ```
2661
+ glimmer samples/hello/hello_list_single_selection.rb
2662
+ ```
2145
2663
 
2146
- Here is a visual list of SWT widgets:
2664
+ ![Hello List Single Selection](images/glimmer-hello-list-single-selection.png)
2147
2665
 
2148
- https://www.eclipse.org/swt/widgets/
2666
+ #### Hello, List Multi Selection!
2149
2667
 
2150
- Here is a textual list of SWT widgets:
2668
+ This sample demonstrates list multi-selection data-binding.
2151
2669
 
2152
- https://help.eclipse.org/2019-12/topic/org.eclipse.platform.doc.isv/guide/swt_widgets_controls.htm?cp=2_0_7_0_0
2670
+ Code:
2153
2671
 
2154
- Here is a list of SWT style bits as used in widget declaration:
2672
+ [samples/hello/hello_list_multi_selection.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/hello/hello_list_multi_selection.rb)
2155
2673
 
2156
- https://wiki.eclipse.org/SWT_Widget_Style_Bits
2674
+ Run:
2157
2675
 
2158
- Here is a SWT style bit constant reference:
2676
+ ```
2677
+ glimmer samples/hello/hello_list_multi_selection.rb
2678
+ ```
2159
2679
 
2160
- https://help.eclipse.org/2019-12/nftopic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/SWT.html
2680
+ ![Hello List Multi Selection](images/glimmer-hello-list-multi-selection.png)
2681
+
2682
+ #### Hello, Computed!
2161
2683
 
2162
- ## SWT Packages
2684
+ This sample demonstrates computed data-binding.
2163
2685
 
2164
- Glimmer automatically imports all SWT Java packages upon adding `include Glimmer` to a class or module.
2686
+ Code:
2687
+
2688
+ [samples/hello/hello_computed.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/hello/hello_computed.rb)
2689
+
2690
+ Run:
2165
2691
 
2166
- Here are the Java packages imported:
2167
2692
  ```
2168
- org.eclipse.swt.*
2169
- org.eclipse.swt.widgets.*
2170
- org.eclipse.swt.layout.*
2171
- org.eclipse.swt.graphics.*
2172
- org.eclipse.swt.browser.*
2173
- org.eclipse.swt.custom.*
2693
+ glimmer samples/hello/hello_computed.rb
2174
2694
  ```
2175
2695
 
2176
- This allows you to call SWT Java classes from Ruby without mentioning Java package references.
2696
+ ![Hello Browser](images/glimmer-hello-computed.png)
2177
2697
 
2178
- For example, after imports, `org.eclipse.swt.graphics.Color` can be referenced by just `Color`
2698
+ #### Hello, Message Box!
2179
2699
 
2180
- Nonetheless, you can disable automatic import if needed via this Glimmer configuration option:
2700
+ This sample demonstrates a `message_box` dialog.
2181
2701
 
2182
- ```ruby
2183
- Glimmer::Config.import_swt_packages = false
2702
+ Code:
2703
+
2704
+ [samples/hello/hello_message_box.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/hello/hello_message_box.rb)
2705
+
2706
+ Run:
2707
+
2708
+ ```
2709
+ glimmer samples/hello/hello_message_box.rb
2184
2710
  ```
2185
2711
 
2186
- To import SWT Java packages manually instead, you have 2 options:
2712
+ ![Hello Message Box](images/glimmer-hello-message-box.png)
2713
+ ![Hello Message Box Dialog](images/glimmer-hello-message-box-dialog.png)
2187
2714
 
2188
- 1. `include Glimmer::SwtPackages`: lazily imports all SWT Java packages to your class, lazy-loading SWT Java class constants on first reference.
2715
+ #### Hello, Browser!
2189
2716
 
2190
- 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'`)
2717
+ This sample demonstrates the `browser` widget.
2191
2718
 
2192
- 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.
2719
+ Code:
2193
2720
 
2194
- You can learn more about importing Java packages into Ruby code at this JRuby WIKI page:
2721
+ [samples/hello/hello_browser.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/hello/hello_browser.rb)
2195
2722
 
2196
- https://github.com/jruby/jruby/wiki/CallingJavaFromJRuby
2723
+ Run:
2197
2724
 
2198
- ## Logging
2725
+ ```
2726
+ glimmer samples/hello/hello_browser.rb
2727
+ ```
2199
2728
 
2200
- Glimmer comes with a Ruby Logger accessible via `Glimmer::Config.logger`
2201
- Its level of logging defaults to `Logger::WARN`
2202
- It may be configured to show a different level of logging as follows:
2203
- ```ruby
2204
- Glimmer::Config.enable_logging
2205
- Glimmer::Config.logger.level = Logger::DEBUG
2729
+ ![Hello Browser](images/glimmer-hello-browser.png)
2730
+
2731
+ #### Hello, Drag and Drop!
2732
+
2733
+ This sample demonstrates drag and drop in Glimmer.
2734
+
2735
+ Code:
2736
+
2737
+ [samples/hello/hello_drag_and_drop.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/hello/hello_drag_and_drop.rb)
2738
+
2739
+ Run:
2740
+
2741
+ ```
2742
+ glimmer samples/hello/hello_drag_and_drop.rb
2206
2743
  ```
2207
- This results in more verbose debugging log to `STDOUT`, which is helpful in troubleshooting Glimmer DSL syntax when needed.
2208
2744
 
2209
- Example log:
2745
+ ![Hello Drag and Drop](images/glimmer-hello-drag-and-drop.gif)
2746
+
2747
+ #### Hello, Menu Bar!
2748
+
2749
+ This sample demonstrates menus in Glimmer.
2750
+
2751
+ Code:
2752
+
2753
+ [samples/hello/hello_menu_bar.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/hello/hello_menu_bar.rb)
2754
+
2755
+ Run:
2756
+
2210
2757
  ```
2211
- D, [2017-07-21T19:23:12.587870 #35707] DEBUG -- : method: shell and args: []
2212
- D, [2017-07-21T19:23:12.594405 #35707] DEBUG -- : ShellCommandHandler will handle command: shell with arguments []
2213
- D, [2017-07-21T19:23:12.844775 #35707] DEBUG -- : method: composite and args: []
2214
- D, [2017-07-21T19:23:12.845388 #35707] DEBUG -- : parent is a widget: true
2215
- D, [2017-07-21T19:23:12.845833 #35707] DEBUG -- : on listener?: false
2216
- D, [2017-07-21T19:23:12.864395 #35707] DEBUG -- : WidgetCommandHandler will handle command: composite with arguments []
2217
- D, [2017-07-21T19:23:12.864893 #35707] DEBUG -- : widget styles are: []
2218
- D, [2017-07-21T19:23:12.874296 #35707] DEBUG -- : method: list and args: [:multi]
2219
- D, [2017-07-21T19:23:12.874969 #35707] DEBUG -- : parent is a widget: true
2220
- D, [2017-07-21T19:23:12.875452 #35707] DEBUG -- : on listener?: false
2221
- D, [2017-07-21T19:23:12.878434 #35707] DEBUG -- : WidgetCommandHandler will handle command: list with arguments [:multi]
2222
- D, [2017-07-21T19:23:12.878798 #35707] DEBUG -- : widget styles are: [:multi]
2758
+ glimmer samples/hello/hello_menu_bar.rb
2223
2759
  ```
2224
2760
 
2225
- ## Raw JRuby Command
2761
+ ![Hello Menu Bar](images/glimmer-hello-menu-bar.png)
2762
+ ![Hello Menu Bar File Menu](images/glimmer-hello-menu-bar-file-menu.png)
2763
+ ![Hello Menu Bar History Menu](images/glimmer-hello-menu-bar-history-menu.png)
2226
2764
 
2227
- If there is a need to run Glimmer directly via the `jruby` command, you
2228
- may run the following:
2765
+ #### Hello, Pop Up Context Menu!
2766
+
2767
+ This sample demonstrates pop up context menus in Glimmer.
2768
+
2769
+ Code:
2770
+
2771
+ [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)
2772
+
2773
+ Run:
2229
2774
 
2230
2775
  ```
2231
- jruby -J-classpath "path_to/swt.jar" -r glimmer -S application.rb
2776
+ glimmer samples/hello/hello_pop_up_context_menu.rb
2232
2777
  ```
2233
2778
 
2234
- The `-J-classpath` option specifies the `swt.jar` file path, which can be a
2235
- 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.
2779
+ ![Hello Pop Up Context Menu](images/glimmer-hello-pop-up-context-menu.png)
2780
+ ![Hello Pop Up Context Menu Popped Up](images/glimmer-hello-pop-up-context-menu-popped-up.png)
2236
2781
 
2237
- The `-r` option preloads (requires) the `glimmer` library in Ruby.
2782
+ ### Elaborate Samples
2238
2783
 
2239
- The `-S` option specifies a script to run.
2784
+ For more elaborate samples, check the following:
2240
2785
 
2241
- ### Mac Support
2786
+ #### Login
2242
2787
 
2243
- 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.
2788
+ This sample demonstrates basic data-binding, password and text fields, and field enablement data-binding.
2789
+
2790
+ Code:
2791
+
2792
+ [samples/elaborate/login.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/elaborate/login.rb)
2793
+
2794
+ Run:
2244
2795
 
2245
- Example:
2246
2796
  ```
2247
- jruby -J-XstartOnFirstThread -J-classpath "path_to/swt.jar" -r glimmer -S application.rb
2797
+ glimmer samples/elaborate/login.rb
2798
+ ```
2799
+
2800
+ ![Login](images/glimmer-login.png)
2801
+ ![Login Filled In](images/glimmer-login-filled-in.png)
2802
+ ![Login Logged In](images/glimmer-login-logged-in.png)
2803
+
2804
+ #### Tic Tac Toe Sample
2805
+
2806
+ 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)).
2807
+
2808
+ Code:
2809
+
2810
+ [samples/elaborate/tic_tac_toe.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/elaborate/tic_tac_toe.rb)
2811
+
2812
+ Run:
2813
+
2814
+ ```
2815
+ glimmer samples/elaborate/tic_tac_toe.rb
2248
2816
  ```
2249
2817
 
2818
+ ![Tic Tac Toe](images/glimmer-tic-tac-toe.png)
2819
+ ![Tic Tac Toe In Progress](images/glimmer-tic-tac-toe-in-progress.png)
2820
+ ![Tic Tac Toe Game Over](images/glimmer-tic-tac-toe-game-over.png)
2821
+
2822
+ #### Contact Manager
2823
+
2824
+ 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)).
2825
+
2826
+ Code:
2827
+
2828
+ [samples/elaborate/contact_manager.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/elaborate/contact_manager.rb)
2829
+
2830
+ Run:
2831
+
2832
+ ```
2833
+ glimmer samples/elaborate/contact_manager.rb
2834
+ ```
2835
+
2836
+ Contact Manager
2837
+
2838
+ ![Contact Manager](images/glimmer-contact-manager.png)
2839
+
2840
+ Contact Manager - Find
2841
+
2842
+ ![Contact Manager](images/glimmer-contact-manager-find.png)
2843
+
2844
+ Contact Manager - Edit Started
2845
+
2846
+ ![Contact Manager](images/glimmer-contact-manager-edit-started.png)
2847
+
2848
+ Contact Manager - Edit In Progress
2849
+
2850
+ ![Contact Manager](images/glimmer-contact-manager-edit-in-progress.png)
2851
+
2852
+ Contact Manager - Edit Done
2853
+
2854
+ ![Contact Manager](images/glimmer-contact-manager-edit-done.png)
2855
+
2856
+ ### External Samples
2857
+
2858
+ #### Glimmer Calculator
2859
+
2860
+ [<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).
2861
+
2862
+ [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer-cs-calculator/master/glimmer-cs-calculator-screenshot.png" />](https://github.com/AndyObtiva/glimmer-cs-calculator)
2863
+
2864
+ #### Gladiator
2865
+
2866
+ [<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.
2867
+ You may check it out to learn how to build a Glimmer Custom Shell gem.
2868
+
2869
+ [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer-cs-gladiator/master/images/glimmer-gladiator.png" />](https://github.com/AndyObtiva/glimmer-cs-gladiator)
2870
+
2871
+ Gladiator is a good demonstration of:
2872
+ - MVP Pattern
2873
+ - Tree data-binding
2874
+ - List data-binding
2875
+ - Text selection data-binding
2876
+ - Tabs
2877
+ - Context menus
2878
+ - Custom Shell
2879
+ - Custom widget
2880
+
2881
+ ## In Production
2882
+
2883
+ The following production apps have been built with Glimmer.
2884
+
2885
+ ### Math Bowling
2886
+
2887
+ [<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
2888
+
2889
+ ### Are We There Yet?
2890
+
2891
+ [<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
2892
+
2893
+ If you have a Glimmer app you would like referenced here, please mention in a Pull Request.
2894
+
2250
2895
  ## Packaging & Distribution
2251
2896
 
2252
2897
  Glimmer apps may be packaged and distributed on the Mac, Windows, and Linux via these tools:
2253
2898
  - Warbler (https://github.com/jruby/warbler): Enables bundling a Glimmer app into a JAR file
2254
2899
  - 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.
2255
2900
 
2256
- 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):
2901
+ Glimmer simplifies the process of Mac packaging via the `glimmer package` command. It works out of the box for any application generated by [Glimmer Scaffolding](#scaffolding):
2257
2902
 
2258
2903
  ```
2259
2904
  glimmer package
@@ -2391,10 +3036,6 @@ By the way, keep in mind that during normal operation, it does also indicate a f
2391
3036
  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
2392
3037
  ```
2393
3038
 
2394
- ## Limitations
2395
-
2396
- - Glimmer apps have a long startup up time and can take anywhere between 12 and 30 seconds to start depending on the app and the machine. Once started, Glimmer apps run very fast and perform very responsively since Ruby is more than fast and capable for handling desktop GUIs. In any case, one idea to address this limitation is to include a background service (daemon) that can launch Glimmer apps instantly or near instantly by keeping a JRuby runtime started and ready at all times.
2397
-
2398
3039
  ## Resources
2399
3040
 
2400
3041
  * [Code Master Blog](http://andymaleh.blogspot.com/search/label/Glimmer)
@@ -2412,24 +3053,38 @@ You may submit [issues](https://github.com/AndyObtiva/glimmer/issues) on [GitHub
2412
3053
 
2413
3054
  [Click here to submit an issue.](https://github.com/AndyObtiva/glimmer/issues)
2414
3055
 
2415
- ### IRC Channel
3056
+ ### Chat
2416
3057
 
2417
- If you need live help, try the [#glimmer](http://widget.mibbit.com/?settings=7514b8a196f8f1de939a351245db7aa8&server=irc.mibbit.net&channel=%23glimmer) IRC channel on [irc.mibbit.net](http://widget.mibbit.com/?settings=7514b8a196f8f1de939a351245db7aa8&server=irc.mibbit.net&channel=%23glimmer). If no one was available, you may [leave a GitHub issue](https://github.com/AndyObtiva/glimmer/issues) to schedule a meetup on IRC.
2418
-
2419
- [Click here to connect to #glimmer IRC channel immediately via a web interface.](http://widget.mibbit.com/?settings=7514b8a196f8f1de939a351245db7aa8&server=irc.mibbit.net&channel=%23glimmer)
3058
+ If you need live help, try to [![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)
2420
3059
 
2421
3060
  ## Feature Suggestions
2422
3061
 
2423
3062
  These features have been suggested. You might see them in a future version of Glimmer. You are welcome to contribute more feature suggestions.
2424
3063
 
2425
- [TODO.md](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/TODO.md)
3064
+ [glimmer-dsl-swt/TODO.md](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/TODO.md)
3065
+
3066
+ Glimmer DSL Engine specific tasks are at:
3067
+
3068
+ [TODO.md](TODO.md)
2426
3069
 
2427
3070
  ## Change Log
2428
3071
 
3072
+ [glimmer-dsl-swt/CHANGELOG.md](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/CHANGELOG.md)
3073
+
2429
3074
  [CHANGELOG.md](CHANGELOG.md)
2430
3075
 
2431
3076
  ## Contributing
2432
3077
 
3078
+ **Contributors Wanted!**
3079
+
3080
+ 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).
3081
+
3082
+ You may apply for contributing to any of these Glimmer DSL gems whether you prefer to focus on the desktop or web:
3083
+ - [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt): Glimmer DSL for SWT (Desktop GUI)
3084
+ - [glimmer-dsl-opal](https://github.com/AndyObtiva/glimmer-dsl-opal): Glimmer DSL for Opal (Web GUI Adapter for Desktop Apps)
3085
+ - [glimmer-dsl-xml](https://github.com/AndyObtiva/glimmer-dsl-xml): Glimmer DSL for XML (& HTML)
3086
+ - [glimmer-dsl-css](https://github.com/AndyObtiva/glimmer-dsl-css): Glimmer DSL for CSS (Cascading Style Sheets)
3087
+
2433
3088
  [CONTRIBUTING.md](CONTRIBUTING.md)
2434
3089
 
2435
3090
  ## Contributors
@@ -2439,7 +3094,17 @@ These features have been suggested. You might see them in a future version of Gl
2439
3094
 
2440
3095
  [Click here to view contributor commits.](https://github.com/AndyObtiva/glimmer/graphs/contributors)
2441
3096
 
3097
+ ## Hire Me
3098
+
3099
+ 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/).
3100
+
2442
3101
  ## License
2443
3102
 
2444
- Copyright (c) 2007-2020 Andy Maleh.
2445
- See LICENSE.txt for further details.
3103
+ [MIT](https://opensource.org/licenses/MIT)
3104
+
3105
+ Copyright (c) 2007-2020 - Andy Maleh.
3106
+ See [LICENSE.txt](LICENSE.txt) for further details.
3107
+
3108
+ --
3109
+
3110
+ 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>