glimmer-dsl-swt 4.17.1.0 → 4.17.2.3

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: 881781afff00abf1690fde7bd43136ae6544e205b13af5c0cfb1e5120c01ab1a
4
- data.tar.gz: 84542383d33bcff92b92bac03f30cbf2238872871feadec3d128efec75020423
3
+ metadata.gz: 72abd42bfd0a4074ba03517643ae4f560cc892d1d592cefd9d96b7a4990195de
4
+ data.tar.gz: 6479abb04a31e9bd5670a4de48c9c98a46f7b05783f4491082c4e0c127f5aa1c
5
5
  SHA512:
6
- metadata.gz: f83516566007cb8043f91bbd2aea68395d862d0fe6795aa12b68b64324e4a2fe1d6b697786916288158738434e9799170eef1c56004e58f7d5e4e2189c80f9f0
7
- data.tar.gz: 02dc757afa476a696006183e4b4d07022376db57abc3ae927683857c0ef5eafc8c4e4f336f78a07bbfeef18df0a8394016877c6a0db4a037b16aeea2947b148e
6
+ metadata.gz: 46ecd1fbe2700184f8b3ea5f447cd7d3e2209a777080d40a787821edee1d65d7525e28befd96bd4ec5dbd48f646371810470eeef8777388d60bd6fce823da525
7
+ data.tar.gz: 74ecccfa3cbb21712178fa695ddbd2eed4cb3cbb400aae3b3bf5b5dc5358ccba3ae2ff056d1992d7adfc0dcd173dcf77cf52a6f6e4ecabe961f5ece49c6b69d9
@@ -1,5 +1,38 @@
1
1
  # Change Log
2
2
 
3
+ ### 4.17.2.3
4
+
5
+ - Maintain image file path upon scaling an ImageProxy
6
+ - Add a glimmer rake task that wraps the juwelier rake gemspec:generate task
7
+ - Accept `ImageProxy` as arg for `image` and `background_image` property methods
8
+ - (EXPERIMENTAL) Animate gif images when set as a `background_image` on a `composite`
9
+ - Fix issue with table redraw after data-binding changes leaving old removed table items visible (even if user cannot interact with anymore)
10
+ - Fix issue with running package rake task from `glimmer` command TUI
11
+
12
+ ### 4.17.2.2
13
+
14
+ - Small updates/refactorings in samples
15
+ - Fix issue with displaying `glimmer` command tasks on Windows
16
+
17
+ ### 4.17.2.1
18
+
19
+ - Add `--bundler=group` option to `glimmer` command
20
+ - Add `--pd` option to `glimmer` command
21
+ - Hello, Custom Widget! sample
22
+ - Hello, Custom Shell! sample
23
+
24
+ ### 4.17.2.0
25
+
26
+ - `glimmer` command --bundler option to run with bundler/setup (instead of picking gems directly)
27
+ - Remove Gemfile dependency on Juwelier since it does not relate to GUI (delaying install of it till scaffolding)
28
+ - Remove Gemfile dependency on Warbler since it does not relate to GUI (delaying install of it till packaging)
29
+ - Move Package and Scaffold classes under Glimmer::RakeTask (Glimmer::Package.javapackager_extra_args is now Glimmer::RakeTask::Package.javapackager_extra_args)
30
+ - Fixed issue with scaffolding spec/spec_helper.rb with Juwelier (since it changed from Jeweler)
31
+
32
+ ### 4.17.1.1
33
+
34
+ - Fixed issue with showing glimmer command tasks twice
35
+
3
36
  ### 4.17.1.0
4
37
 
5
38
  - Switch to Juwelier gem (from Jeweler)
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 />](https://github.com/AndyObtiva/glimmer) Glimmer DSL for SWT 4.17.1.0
1
+ # [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 />](https://github.com/AndyObtiva/glimmer) Glimmer DSL for SWT 4.17.2.3
2
2
  ## JRuby Desktop Development GUI Library
3
3
  [![Gem Version](https://badge.fury.io/rb/glimmer-dsl-swt.svg)](http://badge.fury.io/rb/glimmer-dsl-swt)
4
4
  [![Travis CI](https://travis-ci.com/AndyObtiva/glimmer-dsl-swt.svg?branch=master)](https://travis-ci.com/github/AndyObtiva/glimmer-dsl-swt)
@@ -10,11 +10,9 @@
10
10
 
11
11
  (The Original Glimmer Library Since 2007. Beware of Imitators!)
12
12
 
13
- [**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).
13
+ [**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/), MSI/EXE files on [Windows](https://www.microsoft.com/en-ca/windows), and [Gem Packaged Shell Scripts](#custom-shell-gem) on [Linux](https://www.linux.org/).
14
14
 
15
- [Glimmer receives two updates per month](https://rubygems.org/gems/glimmer-dsl-swt/versions). You can trust [Glimmer](https://rubygems.org/gems/glimmer) with your Ruby desktop GUI development needs.
16
-
17
- NOTE: Glimmer is in beta mode. Please make better by providing feedback and [contributing](#contributing) when possible. The more feedback and issues you report the better.
15
+ [Glimmer receives two updates per month](https://rubygems.org/gems/glimmer-dsl-swt/versions). You can trust [Glimmer](https://rubygems.org/gems/glimmer) with your Ruby desktop GUI development needs. Please make [Glimmer](https://rubygems.org/gems/glimmer) even better by providing feedback and [contributing](#contributing) when possible.
18
16
 
19
17
  [<img src="https://covers.oreillystatic.com/images/9780596519650/lrg.jpg" width=105 /><br />
20
18
  Featured in<br />JRuby Cookbook](http://shop.oreilly.com/product/9780596519650.do)
@@ -335,6 +333,8 @@ Glimmer App:
335
333
  - [Hello, Drag and Drop!](#hello-drag-and-drop)
336
334
  - [Hello, Menu Bar!](#hello-menu-bar)
337
335
  - [Hello, Pop Up Context Menu!](#hello-pop-up-context-menu)
336
+ - [Hello, Custom Widget!](#hello-custom-widget)
337
+ - [Hello, Custom Shell!](#hello-custom-shell)
338
338
  - [Elaborate Samples](#elaborate-samples)
339
339
  - [User Profile](#user-profile)
340
340
  - [Login](#login)
@@ -416,6 +416,8 @@ If you intend to build a Glimmer app from scratch with [scaffolding](#scaffoldin
416
416
 
417
417
  Otherwise, Option 2 ([Bundler](#option-2-bundler)) can be followed in rare cases where you want to build an app without [scaffolding](#scaffolding).
418
418
 
419
+ Note: if you encounter any [issues](https://github.com/AndyObtiva/glimmer-dsl-swt/issues), please [report](https://github.com/AndyObtiva/glimmer-dsl-swt/issues) and then install a previous version instead from the list of [Glimmer Releases](https://rubygems.org/gems/glimmer-dsl-swt/versions).
420
+
419
421
  ### Option 1: Direct Install
420
422
  (Use for [Scaffolding](#scaffolding))
421
423
 
@@ -426,7 +428,7 @@ jgem install glimmer-dsl-swt
426
428
 
427
429
  Or this command if you want a specific version:
428
430
  ```
429
- jgem install glimmer-dsl-swt -v 4.17.1.0
431
+ jgem install glimmer-dsl-swt -v 4.17.2.3
430
432
  ```
431
433
 
432
434
  Note: Gem version numbers are in sync with the SWT library versions. The first two digits represent the SWT version number. The last two digits represent the minor and patch versions of Glimmer DSL for SWT.
@@ -474,6 +476,8 @@ On Windows, it simply lists the available Glimmer tasks at the end (courtsey of
474
476
 
475
477
  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).
476
478
 
479
+ Note: If you encounter an issue running the `glimmer` command, run `bundle exec glimmer` instead.
480
+
477
481
  ### Basic Usage
478
482
 
479
483
  ```
@@ -501,9 +505,9 @@ bin/glimmer sample:run[hello_world]
501
505
  Below are the full usage instructions that come up when running `glimmer` without args.
502
506
 
503
507
  ```
504
- Glimmer (Ruby Desktop Development GUI Library) - JRuby Gem: glimmer-dsl-swt v4.17.1.0
508
+ Glimmer (Ruby Desktop Development GUI Library) - JRuby Gem: glimmer-dsl-swt v4.17.2.3
505
509
 
506
- Usage: glimmer [--quiet] [--debug] [--log-level=VALUE] [[ENV_VAR=VALUE]...] [[-jruby-option]...] (application.rb or task[task_args]) [[application2.rb]...]
510
+ Usage: glimmer [--bundler] [--pd] [--quiet] [--debug] [--log-level=VALUE] [[ENV_VAR=VALUE]...] [[-jruby-option]...] (application.rb or task[task_args]) [[application2.rb]...]
507
511
 
508
512
  Runs Glimmer applications and tasks.
509
513
 
@@ -513,7 +517,9 @@ automatically preloading the glimmer Ruby gem and SWT jar dependency.
513
517
  Optionally, extra Glimmer options, JRuby options, and/or environment variables may be passed in.
514
518
 
515
519
  Glimmer options:
516
- - "--quiet" : Does not announce file path of Glimmer application being launched
520
+ - "--bundler=GROUP" : Activates gems in Bundler default group in Gemfile
521
+ - "--pd=BOOLEAN" : Requires puts_debuggerer to enable pd method
522
+ - "--quiet=BOOLEAN" : Does not announce file path of Glimmer application being launched
517
523
  - "--debug" : Displays extra debugging information, passes "--debug" to JRuby, and enables debug logging
518
524
  - "--log-level=VALUE" : Sets Glimmer's Ruby logger level ("ERROR" / "WARN" / "INFO" / "DEBUG"; default is none)
519
525
 
@@ -528,6 +534,7 @@ Select a Glimmer task to run: (Press ↑/↓ arrow to move, Enter to select and
528
534
  glimmer package[type] # Package app for distribution (generating config, jar, and native files) (type is optional)
529
535
  glimmer package:clean # Clean by removing "dist" and "packages" directories
530
536
  glimmer package:config # Generate JAR config file
537
+ glimmer package:gemspec # Generate gemspec
531
538
  glimmer package:jar # Generate JAR file
532
539
  glimmer package:lock_jars # Lock JARs
533
540
  glimmer package:native[type] # Generate Native files
@@ -614,7 +621,7 @@ This will run the hello_tab sample and output its code:
614
621
  ```
615
622
  $ glimmer sample:run[hello_tab]
616
623
 
617
- # /Users/User/.rvm/gems/jruby-9.2.13.0@glimmerapp/gems/glimmer-dsl-swt-4.17.1.0/samples/hello/hello_tab.rb
624
+ # /Users/User/.rvm/gems/jruby-9.2.13.0@glimmerapp/gems/glimmer-dsl-swt-4.17.2.3/samples/hello/hello_tab.rb
618
625
 
619
626
  class HelloTab
620
627
  include Glimmer
@@ -659,7 +666,7 @@ Example:
659
666
  ```
660
667
  $ glimmer sample:code[tic_tac_toe]
661
668
 
662
- # /Users/User/.rvm/gems/jruby-9.2.13.0@glimmerapp/gems/glimmer-dsl-swt-4.17.1.0/samples/elaborate/tic_tac_toe.rb
669
+ # /Users/User/.rvm/gems/jruby-9.2.13.0@glimmerapp/gems/glimmer-dsl-swt-4.17.2.3/samples/elaborate/tic_tac_toe.rb
663
670
 
664
671
  require_relative "tic_tac_toe/board"
665
672
 
@@ -720,7 +727,7 @@ TicTacToe.new.open
720
727
  # # #
721
728
 
722
729
 
723
- # /Users/User/.rvm/gems/jruby-9.2.13.0@glimmerapp/gems/glimmer-dsl-swt-4.17.1.0/samples/elaborate/tic_tac_toe/cell.rb
730
+ # /Users/User/.rvm/gems/jruby-9.2.13.0@glimmerapp/gems/glimmer-dsl-swt-4.17.2.3/samples/elaborate/tic_tac_toe/cell.rb
724
731
 
725
732
  class TicTacToe
726
733
  class Cell
@@ -753,7 +760,7 @@ end
753
760
  # # #
754
761
 
755
762
 
756
- # /Users/User/.rvm/gems/jruby-9.2.13.0@glimmerapp/gems/glimmer-dsl-swt-4.17.1.0/samples/elaborate/tic_tac_toe/board.rb
763
+ # /Users/User/.rvm/gems/jruby-9.2.13.0@glimmerapp/gems/glimmer-dsl-swt-4.17.2.3/samples/elaborate/tic_tac_toe/board.rb
757
764
 
758
765
  require_relative 'cell'
759
766
 
@@ -938,7 +945,7 @@ $ glimmer scaffold[greeter]
938
945
  create spec/spec_helper.rb
939
946
  create spec/greeter_spec.rb
940
947
  create .rspec
941
- Jeweler has prepared your gem in ./greeter
948
+ Juwelier has prepared your gem in ./greeter
942
949
  Created greeter/.gitignore
943
950
  Created greeter/.ruby-version
944
951
  Created greeter/.ruby-gemset
@@ -1009,7 +1016,7 @@ glimmer scaffold:cw[name]
1009
1016
  #### Custom Shell Gem
1010
1017
 
1011
1018
  Custom shell gems are self-contained Glimmer apps as well as reusable custom shells.
1012
- 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.
1019
+ They have everything scaffolded Glimmer apps come with in addition to gem content like a [Juwelier](https://rubygems.org/gems/juwelier) Rakefile that can build gemspec and release gems.
1013
1020
  Unlike scaffolded Glimmer apps, custom shell gem content lives under the `lib` directory (not `app`).
1014
1021
  They can be packaged as both a native executable (e.g. Mac DMG/PKG/APP) and a Ruby gem.
1015
1022
  Of course, you can just build a Ruby gem and disregard native executable packaging if you do not need it.
@@ -1034,7 +1041,7 @@ Only official Glimmer gems created by the Glimmer project committers will have n
1034
1041
 
1035
1042
  Since custom shell gems are both an app and a gem, they provide two ways to run:
1036
1043
  - Run the `glimmer` command and pass it the generated script under the `bin` directory that matches the gem name (e.g. run `glimmer bin/glimmer-cs-calculator`)
1037
- - Run the executable binary file that ships with the gem directly (without `glimmer`). It intentionally has a shorter name for convenience since it is meant to be used on the command line (not in a package), so you can leave out the `glimmer-cs-` prefix (e.g. run `bin/calculator` directly)
1044
+ - Run the executable shell script that ships with the gem directly (does not need the `glimmer` command). It intentionally has a shorter name for convenience since it is meant to be used on the command line (not in a package), so you can leave out the `glimmer-cs-` prefix (e.g. run `bin/calculator` directly). This is also used as the main way of running custom shell gems on Linux.
1038
1045
 
1039
1046
  Examples:
1040
1047
 
@@ -1139,6 +1146,28 @@ Output:
1139
1146
 
1140
1147
  ```
1141
1148
 
1149
+ Example:
1150
+
1151
+ Check all custom widgets for Glimmer.
1152
+
1153
+ ```
1154
+ glimmer list:gems:cw
1155
+ ```
1156
+
1157
+ Output:
1158
+
1159
+ ```
1160
+
1161
+ Glimmer Custom Widget Gems at rubygems.org:
1162
+
1163
+ Name Gem Version Author Description
1164
+
1165
+ Browser (Chromium) glimmer-cw-browser-chromium 1.0.0 Andy Maleh Chromium Browser - Glimmer Custom Widget
1166
+ Cdatetime (Nebula) glimmer-cw-cdatetime-nebula 1.5.0.0.1 Andy Maleh Nebula CDateTime Widget - Glimmer Custom Widget
1167
+ Video glimmer-cw-video 1.0.0 Andy Maleh Glimmer Custom Widget - Video
1168
+
1169
+ ```
1170
+
1142
1171
  #### Listing DSL Gems
1143
1172
 
1144
1173
  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):
@@ -1161,24 +1190,46 @@ Output:
1161
1190
 
1162
1191
  Name Gem Version Author Description
1163
1192
 
1164
- Css glimmer-dsl-css 0.2.0 AndyMaleh Glimmer DSL for CSS
1165
- Opal glimmer-dsl-opal 0.1.0 AndyMaleh Glimmer DSL for Opal
1166
- Swt glimmer-dsl-swt 4.17.1.0 AndyMaleh Glimmer DSL for SWT
1193
+ Css glimmer-dsl-css 1.1.0 AndyMaleh Glimmer DSL for CSS
1194
+ Opal glimmer-dsl-opal 0.3.0 AndyMaleh Glimmer DSL for Opal
1195
+ Swt glimmer-dsl-swt 4.17.2.3 AndyMaleh Glimmer DSL for SWT
1167
1196
  Tk glimmer-dsl-tk 0.0.5 AndyMaleh Glimmer DSL for Tk
1168
- Xml glimmer-dsl-xml 0.2.0 AndyMaleh Glimmer DSL for XML
1197
+ Xml glimmer-dsl-xml 1.1.0 AndyMaleh Glimmer DSL for XML
1169
1198
  ```
1170
1199
 
1171
1200
  ### Packaging
1172
1201
 
1202
+ Glimmer supports packaging applications as native files on Mac and Windows.
1203
+
1173
1204
  Glimmer packaging tasks are detailed under [Packaging & Distribution](#packaging--distribution).
1174
1205
 
1206
+ On Linux, the Glimmer [Custom Shell Gem](#custom-shell-gem) approach provides a [Gem Packaged Shell Script](#custom-shell-gem) (e.g. `calculator` command becomes available after installing the [glimmer-cs-calculator](https://github.com/AndyObtiva/glimmer-cs-calculator) gem)
1207
+
1175
1208
  ### Raw JRuby Command
1176
1209
 
1177
1210
  If there is a need to run Glimmer directly via the `jruby` command, you
1178
- may run the following:
1211
+ may run the following on Windows/Linux:
1212
+
1213
+ ```
1214
+ jruby -r glimmer-dsl-swt -S application.rb
1215
+ ```
1216
+
1217
+ Or, the following on Mac:
1218
+
1219
+ ```
1220
+ jruby -J-XstartOnFirstThread -r glimmer-dsl-swt -S application.rb
1221
+ ```
1222
+
1223
+ If you want to use a specific custom version of SWT, run the following on Windows/Linux:
1224
+
1225
+ ```
1226
+ jruby -J-classpath "path_to/swt.jar" -r glimmer-dsl-swt -S application.rb
1227
+ ```
1228
+
1229
+ Or, the following on Mac:
1179
1230
 
1180
1231
  ```
1181
- jruby -J-classpath "path_to/swt.jar" -r glimmer -S application.rb
1232
+ jruby -J-XstartOnFirstThread -J-classpath "path_to/swt.jar" -r glimmer-dsl-swt -S application.rb
1182
1233
  ```
1183
1234
 
1184
1235
  The `-J-classpath` option specifies the `swt.jar` file path, which can be a
@@ -1196,7 +1247,7 @@ However, if there is a reason to use the raw `jruby` command directly instead of
1196
1247
 
1197
1248
  Example:
1198
1249
  ```
1199
- jruby -J-XstartOnFirstThread -J-classpath "path_to/swt.jar" -r glimmer -S application.rb
1250
+ jruby -J-XstartOnFirstThread -J-classpath "path_to/swt.jar" -r glimmer-dsl-swt -S application.rb
1200
1251
  ```
1201
1252
 
1202
1253
  ## Girb (Glimmer irb) Command
@@ -1280,19 +1331,21 @@ Glimmer DSL syntax consists mainly of:
1280
1331
 
1281
1332
  ### DSL Auto-Expansion
1282
1333
 
1283
- Glimmer supports a new and radical Ruby DSL concept called DSL Auto-Expansion. It is explained by first mentioning the two types of Glimmer GUI DSL keywords: static and dynamic.
1334
+ Glimmer supports a new and radical Ruby DSL concept called DSL Auto-Expansion. To explain, let's first mention the two types of Glimmer GUI DSL keywords: static and dynamic.
1284
1335
 
1285
1336
  Static keywords are pre-identified keywords in the Glimmer DSL, such as `shell`, `display`, `message_box`, `async_exec`, `sync_exec`, and `bind`.
1286
1337
 
1287
- 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.
1338
+ Dynamic keywords are dynamically figured out from currently imported (aka required/loaded) SWT widgets and custom widgets. Examples are: `label`, `combo`, and `list` for SWT widgets and `c_date_time`, `video`, and `gantt_chart` for custom widgets.
1339
+
1340
+ The only reason to distinguish between the two is to realize that importing new Glimmer [custom widgets](#custom-widgets) and Java SWT custom widget libraries automatically expands Glimmer's DSL vocabulary with new dynamic keywords.
1288
1341
 
1289
- 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.
1342
+ For example, if a project adds this custom Java SWT library from the [Nebula Project](https://www.eclipse.org/nebula/):
1290
1343
 
1291
- For example, if a project adds this custom Java SWT library:
1344
+ https://www.eclipse.org/nebula/widgets/gallery/gallery.php
1292
1345
 
1293
- https://www.eclipse.org/nebula/widgets/cdatetime/cdatetime.php?page=operation
1346
+ Glimmer will automatically support using the keyword `gallery`
1294
1347
 
1295
- Glimmer will automatically support using the keyword `c_date_time`
1348
+ This is what DSL Auto-Expansion is.
1296
1349
 
1297
1350
  You will learn more about widgets next.
1298
1351
 
@@ -1407,6 +1460,10 @@ shell {
1407
1460
 
1408
1461
  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.
1409
1462
 
1463
+ If you are advanced and need more widgets, check out the [Nebula Project](https://www.eclipse.org/nebula/) for an extensive list of high quality custom widgets:
1464
+
1465
+ https://www.eclipse.org/nebula/
1466
+
1410
1467
  #### Display
1411
1468
 
1412
1469
  SWT Display is a singleton in Glimmer. It is used in SWT to represent your display device, allowing you to manage GUI globally
@@ -2602,12 +2659,45 @@ end
2602
2659
 
2603
2660
  ### Custom Widgets
2604
2661
 
2605
- Glimmer supports creating custom widgets with minimal code, which automatically extends Glimmer's DSL syntax with an underscored lowercase keyword.
2662
+ Custom widgets are brand new Glimmer DSL keywords that represent aggregates of existing widgets (e.g. `address_form`), customized existing widgets (e.g. `greeting_label`), or brand new widgets (e.g. `oscilloscope`)
2606
2663
 
2607
- Simply create a new class that includes `Glimmer::UI::CustomWidget` and put Glimmer DSL code in its `#body` block (its return value is stored in `#body_root` attribute). Glimmer will then automatically recognize this class by convention when it encounters a keyword matching the class name converted to underscored lowercase (and namespace double-colons `::` replaced with double-underscores `__`)
2664
+ You can find out about [published Glimmer Custom Widgets](https://github.com/AndyObtiva/glimmer-dsl-swt#gem-listing) by running the `glimmer list:gems:customwidget` command
2665
+
2666
+ Glimmer supports two ways of creating custom widgets with minimal code:
2667
+ 1. Method-based Custom Widgets (for single-view-internal reuse): Extract a method containing Glimmer DSL widget syntax. Useful for quickly eliminating redundant code within a single view.
2668
+ 2. Class-based Custom Widgets (for multiple-view-external reuse): Create a class that includes the `Glimmer::UI::CustomWidget` module and Glimmer DSL widget syntax in a `body {}` block. This will automatically extend Glimmer's DSL syntax with an underscored lowercase keyword matching the class name by convention. Useful in making a custom widget available in many views.
2669
+
2670
+ Approach #1 is a casual Ruby-based approach. Approach #2 is the official Glimmer approach. Typically, when referring to Custom Widgets, we are talking about Class-based Custom Widgets.
2671
+
2672
+ A developer might start with approach #1 to eliminate duplication in a view and later upgrade it to approach #2 when needing to export a custom widget to make it available in many views.
2673
+
2674
+ Class-based Custom Widgets offer a number of benefits over method-based custom widgets, such as built-in support for passing SWT style, nested block of extra widgets and properties, and `before_body`/`after_body` hooks.
2608
2675
 
2609
2676
  #### Simple Example
2610
2677
 
2678
+ ##### Method-Based Custom Widget Example
2679
+
2680
+ (you may copy/paste in [`girb`](#girb-glimmer-irb-command))
2681
+
2682
+ Definition and usage in the same file:
2683
+ ```ruby
2684
+ def red_label(label_text)
2685
+ label {
2686
+ text label_text
2687
+ background :red
2688
+ }
2689
+ end
2690
+
2691
+ shell {
2692
+ red_label('Red Label')
2693
+ }.open
2694
+ ```
2695
+
2696
+
2697
+ ##### Class-Based Custom Widget Example
2698
+
2699
+ Simply create a new class that includes `Glimmer::UI::CustomWidget` and put Glimmer DSL code in its `#body` block (its return value is stored in `#body_root` attribute). Glimmer will then automatically recognize this class by convention when it encounters a keyword matching the class name converted to underscored lowercase (and namespace double-colons `::` replaced with double-underscores `__`)
2700
+
2611
2701
  (you may copy/paste in [`girb`](#girb-glimmer-irb-command))
2612
2702
 
2613
2703
  Definition:
@@ -2626,15 +2716,22 @@ end
2626
2716
  Usage:
2627
2717
  ```ruby
2628
2718
  shell {
2629
- red_label {
2630
- text 'Red Label'
2719
+ red_label(:center) {
2720
+ text 'Red Label'
2721
+ foreground :green
2631
2722
  }
2632
2723
  }.open
2633
2724
  ```
2634
2725
 
2635
- As you can see, `RedLabel` became Glimmer DSL keyword: `red_label`
2726
+ As you can see, `RedLabel` became the Glimmer DSL keyword `red_label` and worked just like a standard label by taking in SWT style and nested properties. As such, it is a first-class citizen of the Glimmer GUI DSL.
2727
+
2728
+ #### Custom Widget Lifecycle Hooks
2636
2729
 
2637
- #### Lifecycle Hook Example
2730
+ You may execute code before or after evaluating the body with these lifecycle hooks:
2731
+ - `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`
2732
+ - `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.
2733
+
2734
+ #### Lifecycle Hooks Example
2638
2735
 
2639
2736
  (you may copy/paste in [`girb`](#girb-glimmer-irb-command))
2640
2737
 
@@ -2729,12 +2826,6 @@ shell {
2729
2826
 
2730
2827
  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'`
2731
2828
 
2732
- #### Custom Widget Lifecycle Hooks
2733
-
2734
- Last but not least, these are the available lifecycle hooks:
2735
- - `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`
2736
- - `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.
2737
-
2738
2829
  #### Gotcha
2739
2830
 
2740
2831
  Beware of defining a custom attribute that is a common SWT widget property name.
@@ -2770,12 +2861,16 @@ The `text` method invoked in the custom widget body will call the one you define
2770
2861
  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:
2771
2862
  [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)
2772
2863
 
2864
+ Also, you may check out [Hello, Custom Widget!](#hello-custom-widget) for another example.
2865
+
2773
2866
  ### Custom Shells
2774
2867
 
2775
2868
  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.
2776
2869
 
2777
2870
  They may also be chained in a wizard fashion.
2778
2871
 
2872
+ You can find out about [published Glimmer Custom Shells](https://github.com/AndyObtiva/glimmer-dsl-swt#gem-listing) by running the `glimmer list:gems:customshell` command
2873
+
2779
2874
  Example (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
2780
2875
 
2781
2876
  ```ruby
@@ -2835,6 +2930,8 @@ shell { |app_shell|
2835
2930
  }.open
2836
2931
  ```
2837
2932
 
2933
+ You may check out [Hello, Custom Shell!](#hello-custom-shell) for another example.
2934
+
2838
2935
  ### Drag and Drop
2839
2936
 
2840
2937
  Glimmer offers Drag and Drop support, thanks to [SWT](https://www.eclipse.org/swt/) and Glimmer's lightweight [DSL syntax](#glimmer-dsl-syntax).
@@ -3393,6 +3490,10 @@ Here is an SWT Custom Widget guide:
3393
3490
 
3394
3491
  https://www.eclipse.org/articles/Article-Writing%20Your%20Own%20Widget/Writing%20Your%20Own%20Widget.htm
3395
3492
 
3493
+ Here is the Nebula Project (custom widget library) homepage:
3494
+
3495
+ https://www.eclipse.org/nebula/
3496
+
3396
3497
  ## Samples
3397
3498
 
3398
3499
  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`).
@@ -3585,6 +3686,41 @@ glimmer sample:run[hello_pop_up_context_menu]
3585
3686
  ![Hello Pop Up Context Menu](images/glimmer-hello-pop-up-context-menu.png)
3586
3687
  ![Hello Pop Up Context Menu Popped Up](images/glimmer-hello-pop-up-context-menu-popped-up.png)
3587
3688
 
3689
+ #### Hello, Custom Widget!
3690
+
3691
+ This sample demonstrates the use of a custom widget in Glimmer.
3692
+
3693
+ Code:
3694
+
3695
+ [samples/hello/hello_custom_widget.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/hello/hello_custom_widget.rb)
3696
+
3697
+ Run:
3698
+
3699
+ ```
3700
+ glimmer sample:run[hello_custom_widget]
3701
+ ```
3702
+
3703
+ ![Hello Custom Widget](images/glimmer-hello-custom-widget.gif)
3704
+
3705
+ #### Hello, Custom Shell!
3706
+
3707
+ This sample demonstrates the use of a custom shell (aka custom window) in Glimmer.
3708
+
3709
+ Code:
3710
+
3711
+ [samples/hello/hello_custom_shell.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/hello/hello_custom_shell.rb)
3712
+
3713
+ Run:
3714
+
3715
+ ```
3716
+ glimmer sample:run[hello_custom_shell]
3717
+ ```
3718
+
3719
+ ![Hello Custom Shell](images/glimmer-hello-custom-shell.png)
3720
+ ![Hello Custom Shell Email1](images/glimmer-hello-custom-shell-email1.png)
3721
+ ![Hello Custom Shell Email2](images/glimmer-hello-custom-shell-email2.png)
3722
+ ![Hello Custom Shell Email3](images/glimmer-hello-custom-shell-email3.png)
3723
+
3588
3724
  ### Elaborate Samples
3589
3725
 
3590
3726
  For more elaborate samples, check the following:
@@ -3706,7 +3842,7 @@ Gladiator is a good demonstration of:
3706
3842
 
3707
3843
  #### Timer
3708
3844
 
3709
- [<img alt="Glimmer Timer Icon" src="https://raw.githubusercontent.com/AndyObtiva/glimmer-cs-timer/master/images/glimmer-timer-logo.png" height=40 /> Timer](https://github.com/AndyObtiva/glimmer-cs-timer) is a sample app demonstrating data-binding and multi-threading in a desktop application.
3845
+ [<img alt="Glimmer Timer Icon" src="https://raw.githubusercontent.com/AndyObtiva/glimmer-cs-timer/master/images/glimmer-timer-logo.png" height=40 /> Timer](https://github.com/AndyObtiva/glimmer-cs-timer) is a sample app demonstrating data-binding, multi-threading, and Java (Sound) library integration in a desktop application.
3710
3846
 
3711
3847
  [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer-cs-timer/master/glimmer-timer-screenshot.png" />](https://github.com/AndyObtiva/glimmer-cs-timer)
3712
3848
 
@@ -3730,6 +3866,8 @@ If you have a Glimmer app you would like referenced here, please mention in a Pu
3730
3866
 
3731
3867
  ## Packaging & Distribution
3732
3868
 
3869
+ Note: this section mostly applies to Mac and Windows. On Linux, the Glimmer [Custom Shell Gem](#custom-shell-gem) approach provides a [Gem Packaged Shell Script](#custom-shell-gem) (e.g. `calculator` command becomes available after installing the [glimmer-cs-calculator](https://github.com/AndyObtiva/glimmer-cs-calculator) gem)
3870
+
3733
3871
  Glimmer simplifies the process of native-executable packaging and distribution on Mac and Windows via a single `glimmer package` command:
3734
3872
 
3735
3873
  ```
@@ -3754,8 +3892,8 @@ require 'glimmer/rake_task'
3754
3892
  ```
3755
3893
 
3756
3894
  The Glimmer packaging process done in the `glimmer package` command consists of the following steps:
3757
- 1. Generate gemspec via Jeweler (`rake gemspec:generate`): Having a gemspec is required by the [`jar-dependencies`](https://github.com/mkristian/jar-dependencies) JRuby gem, used by JRuby libraries to declare JAR dependencies.
3758
- 1. Lock JAR versions (`glimmer package:lock_jars`): This locks versions of JAR dependencies leveraged by the `jar-dependencies` JRuby gem, downloading them into the `./vendor` directory so they would get inside the top-level Glimmer app/gem JAR file.
3895
+ 1. Generate gemspec via [Juwelier](https://rubygems.org/gems/juwelier) (`rake gemspec:generate`): Having a gemspec is required by the [`jar-dependencies`](https://github.com/mkristian/jar-dependencies) JRuby gem, used by JRuby libraries to declare JAR dependencies.
3896
+ 1. Lock JAR versions (`glimmer package:4.17.2.3`): This locks versions of JAR dependencies leveraged by the `jar-dependencies` JRuby gem, downloading them into the `./vendor` directory so they would get inside the top-level Glimmer app/gem JAR file.
3759
3897
  1. Generate [Warbler](https://github.com/jruby/warbler) config (`glimmer package:config`): Generates initial Warbler config file (under `./config/warble.rb`) to use for generating JAR file.
3760
3898
  1. Generate JAR file using [Warbler](https://github.com/jruby/warbler) (`glimmer package:jar`): Enables bundling a Glimmer app into a JAR file under the `./dist` directory
3761
3899
  1. Generate native executable using [javapackager](https://docs.oracle.com/javase/8/docs/technotes/tools/unix/javapackager.html) (`glimmer package:native`): Enables packaging a JAR file as a DMG/PKG/APP file on Mac, MSI/EXE/APP on Windows, and DEB/RPM/APP on Linux (Glimmer does not officially support Linux with the `glimmer package` command yet, but it generates the JAR file successfully, and you could use `javapackager` manually afterwards if needed).
@@ -3765,7 +3903,7 @@ The JAR file name will match your application local directory name (e.g. `MathBo
3765
3903
  The 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)
3766
3904
 
3767
3905
  The `glimmer package` command will automatically set "mac.CFBundleIdentifier" to ="org.#{project_name}.application.#{project_name}".
3768
- You may override by configuring as an extra argument for javapackger (e.g. Glimmer::Package.javapackager_extra_args = " -Bmac.CFBundleIdentifier=org.andymaleh.application.MathBowling")
3906
+ You may override by configuring as an extra argument for javapackger (e.g. Glimmer::RakeTask::Package.javapackager_extra_args = " -Bmac.CFBundleIdentifier=org.andymaleh.application.MathBowling")
3769
3907
 
3770
3908
  ### Packaging Defaults
3771
3909
 
@@ -3793,7 +3931,7 @@ require_relative '../app/my_application.rb'
3793
3931
  - Include DMG Background Icon (Optional): Simply place a .png file under `package/macosx/{HumanAppName}-background.png`
3794
3932
  - Include Version (Optional): Create a `VERSION` file in your application and fill it your app version on one line (e.g. `1.1.0`)
3795
3933
  - Include License (Optional): Create a `LICENSE.txt` file in your application and fill it up with your license (e.g. MIT). It will show up to people when installing your app. Note that, you may optionally also specify license type, but you'd have to do so manually via `-BlicenseType=MIT` shown in an [example below](#javapackager-extra-arguments).
3796
- - Extra args (Optional): You may optionally add the following to `Rakefile` to configure extra arguments for javapackager: `Glimmer::Packager.javapackager_extra_args = "..."` (Useful to avoid re-entering extra arguments on every run of rake task.). Read about them in [their section below](#javapackager-extra-arguments).
3934
+ - Extra args (Optional): You may optionally add the following to `Rakefile` to configure extra arguments for javapackager: `Glimmer::RakeTask::Package.javapackager_extra_args = "..."` (Useful to avoid re-entering extra arguments on every run of rake task.). Read about them in [their section below](#javapackager-extra-arguments).
3797
3935
 
3798
3936
  ### javapackager Extra Arguments
3799
3937
 
@@ -3805,7 +3943,7 @@ In order to explicitly configure javapackager, Mac package attributes, or sign y
3805
3943
  - https://developer.apple.com/library/archive/releasenotes/General/SubmittingToMacAppStore/index.html#//apple_ref/doc/uid/TP40010572-CH16-SW8
3806
3944
 
3807
3945
  The Glimmer rake task allows passing extra options to javapackager via:
3808
- - `Glimmer::Packager.javapackager_extra_args="..."` in your application Rakefile
3946
+ - `Glimmer::RakeTask::Package.javapackager_extra_args="..."` in your application Rakefile
3809
3947
  - Environment variable: `JAVAPACKAGER_EXTRA_ARGS`
3810
3948
 
3811
3949
  Example (Rakefile):
@@ -3813,7 +3951,7 @@ Example (Rakefile):
3813
3951
  ```ruby
3814
3952
  require 'glimmer/rake_task'
3815
3953
 
3816
- Glimmer::Package.javapackager_extra_args = '-BlicenseType="MIT" -Bmac.category="public.app-category.business" -Bmac.signing-key-developer-id-app="Andy Maleh"'
3954
+ Glimmer::RakeTask::Package.javapackager_extra_args = '-BlicenseType="MIT" -Bmac.category="public.app-category.business" -Bmac.signing-key-developer-id-app="Andy Maleh"'
3817
3955
  ```
3818
3956
 
3819
3957
  Note that `mac.category` defaults to "public.app-category.business", but can be overridden with one of the category UTI values mentioned here:
@@ -3830,7 +3968,7 @@ That overrides the default application display name.
3830
3968
 
3831
3969
  ### Verbose Mode
3832
3970
 
3833
- Pass `-v` to javapackager in `Glimmer::Package.javapackager_extra_args` or by running `glimmer package:native[type] -v` to learn more about further available customizations for the installer you are requesting to generate.
3971
+ Pass `-v` to javapackager in `Glimmer::RakeTask::Package.javapackager_extra_args` or by running `glimmer package:native[type] -v` to learn more about further available customizations for the installer you are requesting to generate.
3834
3972
 
3835
3973
  ### Windows Application Packaging
3836
3974
 
@@ -3844,7 +3982,7 @@ If you just want to test out packaging into a native Windows app that is not pac
3844
3982
 
3845
3983
  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.
3846
3984
 
3847
- Afterwards, you may add developer-id/signing-key arguments to `javapackager` via `Glimmer::Package.javapackager_extra_args` or `JAVAPACKAGER_EXTRA_ARGS` according to this webpage: https://docs.oracle.com/javase/9/tools/javapackager.htm#JSWOR719
3985
+ Afterwards, you may add developer-id/signing-key arguments to `javapackager` via `Glimmer::RakeTask::Package.javapackager_extra_args` or `JAVAPACKAGER_EXTRA_ARGS` according to this webpage: https://docs.oracle.com/javase/9/tools/javapackager.htm#JSWOR719
3848
3986
 
3849
3987
  DMG signing key argument:
3850
3988
  ```
@@ -3872,12 +4010,12 @@ To do so, you may follow these steps (abbreviated version from https://developer
3872
4010
  - Enter Name (referred to below as "CertificateName")
3873
4011
  - Set 'Certificate Type' to 'Code Signing'
3874
4012
  - Create (if you alternatively override defaults, make sure to enable all capabilities)
3875
- - Add the following option to javapackager: `-Bmac.signing-key-developer-id-app="CertificateName"` via `Glimmer::Package.javapackager_extra_args` or `JAVAPACKAGER_EXTRA_ARGS`
4013
+ - Add the following option to javapackager: `-Bmac.signing-key-developer-id-app="CertificateName"` via `Glimmer::RakeTask::Package.javapackager_extra_args` or `JAVAPACKAGER_EXTRA_ARGS`
3876
4014
 
3877
4015
  Example:
3878
4016
 
3879
4017
  ```ruby
3880
- Glimmer::Package.javapackager_extra_args = '-Bmac.signing-key-developer-id-app="Andy Maleh"'
4018
+ Glimmer::RakeTask::Package.javapackager_extra_args = '-Bmac.signing-key-developer-id-app="Andy Maleh"'
3881
4019
  ```
3882
4020
 
3883
4021
  Now, when you run `glimmer package`, it builds a self-signed DMG file. When you make available online, and users download, upon launching application, they are presented with your certificate, which they have to sign if they trust you in order to use the application.
@@ -3892,7 +4030,7 @@ Keep that in mind if you are not going to rely on the default `LICENSE.txt` supp
3892
4030
  Example:
3893
4031
 
3894
4032
  ```ruby
3895
- Glimmer::Package.javapackager_extra_args = '-srcfiles "ACME.txt" -BlicenseFile="ACME.txt" -BlicenseType="ACME"'
4033
+ Glimmer::RakeTask::Package.javapackager_extra_args = '-srcfiles "ACME.txt" -BlicenseFile="ACME.txt" -BlicenseType="ACME"'
3896
4034
  ```
3897
4035
 
3898
4036
  2. Mounted DMG Residue
@@ -3912,7 +4050,7 @@ Glimmer already supports automatic (and manual) app updates via the Mac App Stor
3912
4050
  ## Glimmer Supporting Libraries
3913
4051
 
3914
4052
  Here is a list of notable 3rd party gems used by Glimmer:
3915
- - [jeweler](https://github.com/technicalpickles/jeweler): generates app gems during [Glimmer Scaffolding](#scaffolding)
4053
+ - [juwelier](https://rubygems.org/gems/juwelier): generates app gems during [Glimmer Scaffolding](#scaffolding)
3916
4054
  - [logging](https://github.com/TwP/logging): provides extra logging capabilities not available in Ruby Logger such as multi-threaded buffered asynchronous logging (to avoid affecting app performance) and support for multiple appenders such as stdout, syslog, and log files (the last one is needed on Windows where syslog is not supported)
3917
4055
  - [nested_inherited_jruby_include_package](https://github.com/AndyObtiva/nested_inherited_jruby_include_package): makes included [SWT](https://www.eclipse.org/swt/)/[Java](https://www.java.com/en/) packages available to all classes/modules that mix in the Glimmer module without having to manually reimport
3918
4056
  - [os](https://github.com/rdp/os): provides OS detection capabilities (e.g. `OS.mac?` or `OS.windows?`) to write cross-platform code inexpensively