glimmer 0.10.1 → 0.10.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4e5e05e1e5ce6544e9c0286a46f5436c82ff92e8659044b31794d3f4d9db40f2
4
- data.tar.gz: 3ad9c659f81fed05328533f1af05713939d44297693af78d78799006009cad71
3
+ metadata.gz: f5296edf57183b7bffa288342e5c3c4ab14713dbd70af643bf8117f608314d2a
4
+ data.tar.gz: 5a9285de28140f0f7a94ed80ec9c6c597ae163a5fdce4f4ad8a060f5ad341775
5
5
  SHA512:
6
- metadata.gz: 674f6f7ea6cf2908261b83ce3580b770bb39ac47c1069c2b26651c897d109863516349d7b09d94199c928b2efceb19719d41123453caa7fde187127bb0c3b16a
7
- data.tar.gz: c5d22e44fa047b35f5aadb232f446cc074873dbb4b8638b2f83038208ae0e32535e0668cd19419994d76d1aac95e7a917b711cc8853d589ac3757e9ca90e350c
6
+ metadata.gz: ef36cf024e59cc0111d8f3a283c6d89134eea01390574962ef0b36ef89c75d482d6912b83fd1bfc609f40f262f72156df9ab8d8481ac41118bb799b1a718e473
7
+ data.tar.gz: 65c0d12d30f2ea846766d98bb91aa0b3ae86eaac11697532d6b3ed55a139816d0be797a94584297c40c949f8cff436dfa15cbc0176cbb652207bab452c148071
data/README.md CHANGED
@@ -1,14 +1,17 @@
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)
1
+ # [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=85 style="position: relative; top: 20px;" />](https://rubygems.org/gems/glimmer) Glimmer (Ruby Desktop Development GUI Library)
2
2
  [![Gem Version](https://badge.fury.io/rb/glimmer.svg)](http://badge.fury.io/rb/glimmer)
3
3
  [![Travis CI](https://travis-ci.com/AndyObtiva/glimmer.svg?branch=master)](https://travis-ci.com/github/AndyObtiva/glimmer)
4
4
  [![Coverage Status](https://coveralls.io/repos/github/AndyObtiva/glimmer/badge.svg?branch=master)](https://coveralls.io/github/AndyObtiva/glimmer?branch=master)
5
+ [![Maintainability](https://api.codeclimate.com/v1/badges/38fbc278022862794414/maintainability)](https://codeclimate.com/github/AndyObtiva/glimmer/maintainability)
5
6
  [![Join the chat at https://gitter.im/AndyObtiva/glimmer](https://badges.gitter.im/AndyObtiva/glimmer.svg)](https://gitter.im/AndyObtiva/glimmer?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
6
7
 
7
8
  **[Contributors Wanted! (Submit a Glimmer App Sample to Get Started)](#contributing)**
8
9
 
9
10
  (The Original Glimmer Library Since 2007. Beware of Imitators!)
10
11
 
11
- [**Glimmer**](https://rubygems.org/gems/glimmer) is a native-GUI cross-platform desktop development library written in [JRuby](https://www.jruby.org/), a highly portable faster version of [Ruby](https://www.ruby-lang.org/en/). [**Glimmer**](https://rubygems.org/gems/glimmer)'s main innovation is a declarative [Ruby DSL](#glimmer-dsl-syntax) that enables productive and efficient authoring of desktop application user-interfaces while relying on the robust [Eclipse SWT library](https://www.eclipse.org/swt/). [**Glimmer**](https://rubygems.org/gems/glimmer) additionally innovates by having built-in [data-binding](#data-binding) support, which greatly facilitates synchronizing the GUI with domain models. This achieves true decoupling of object oriented components, enabling developers to solve business problems without worrying about GUI concerns or alternatively drive development GUI-first and then write clean business models test-first afterwards. To get started quickly, [Glimmer](https://rubygems.org/gems/glimmer) offers [scaffolding](#scaffolding) options for [Apps](#in-production), [Gems](#custom-shell-gem), and [Custom Widgets](#custom-widgets). Last but not least, [Glimmer](https://rubygems.org/gems/glimmer) includes native-executable [packaging](#packaging--distribution) support, sorely lacking in competing libraries, thus enabling delivery of desktop apps written in [Ruby](https://www.ruby-lang.org/en/) as truly native DMG/PKG/APP files on the [Mac](https://www.apple.com/ca/macos) + [App Store](https://developer.apple.com/macos/distribution/) and MSI/EXE files on [Windows](https://www.microsoft.com/en-ca/windows). Given that [JRuby](https://www.jruby.org/) runs on the [JVM](https://java.com/en/download/faq/whatis_java.xml) (Java Virtual Machine), unlike competing libraries like TK, it does not require recompilation of [Ruby](https://www.ruby-lang.org/en/) to use native GUI libraries on every platform. [Glimmer](https://rubygems.org/gems/glimmer) runs native GUI out of the box on every platform thanks to the [JVM](https://java.com/en/download/faq/whatis_java.xml) and [Eclipse SWT library](https://www.eclipse.org/swt/).
12
+ [**Glimmer**](https://rubygems.org/gems/glimmer) is a native-GUI cross-platform desktop development library written in [JRuby](https://www.jruby.org/), an OS-threaded faster version of [Ruby](https://www.ruby-lang.org/en/). [Glimmer](https://rubygems.org/gems/glimmer)'s main innovation is a declarative [Ruby DSL](#glimmer-dsl-syntax) that enables productive and efficient authoring of desktop application user-interfaces while relying on the robust [Eclipse SWT library](https://www.eclipse.org/swt/). [Glimmer](https://rubygems.org/gems/glimmer) additionally innovates by having built-in [data-binding](#data-binding) support, which greatly facilitates synchronizing the GUI with domain models, thus achieving true decoupling of object oriented components and enabling developers to solve business problems (test-first) without worrying about GUI concerns. To get started quickly, [Glimmer](https://rubygems.org/gems/glimmer) offers [scaffolding](#scaffolding) options for [Apps](#in-production), [Gems](#custom-shell-gem), and [Custom Widgets](#custom-widgets). [Glimmer](https://rubygems.org/gems/glimmer) also includes native-executable [packaging](#packaging--distribution) support, sorely lacking in other libraries, thus enabling the delivery of desktop apps written in [Ruby](https://www.ruby-lang.org/en/) as truly native DMG/PKG/APP files on the [Mac](https://www.apple.com/ca/macos) + [App Store](https://developer.apple.com/macos/distribution/) and MSI/EXE files on [Windows](https://www.microsoft.com/en-ca/windows). Unlike libraries like TK, [Glimmer](https://rubygems.org/gems/glimmer) does not require recompilation of [Ruby](https://www.ruby-lang.org/en/). [Glimmer](https://rubygems.org/gems/glimmer) runs native GUI out of the box on every platform thanks to the [JVM](https://java.com/en/download/faq/whatis_java.xml), [JRuby](https://www.jruby.org/), and the [Eclipse SWT library](https://www.eclipse.org/swt/).
13
+
14
+ NOTE: Glimmer is in beta mode. Please help make better by [contributing](#contributing), adopting for small or low risk projects, and providing feedback. While a lot of hard work has gone into it, it is by no means polished, and definitely has bugs waiting to be reported. The more feedback and issues you report the better.
12
15
 
13
16
  [<img src="https://covers.oreillystatic.com/images/9780596519650/lrg.jpg" width=105 /><br />
14
17
  Featured in<br />JRuby Cookbook](http://shop.oreilly.com/product/9780596519650.do)
@@ -171,8 +174,6 @@ Glimmer App:
171
174
 
172
175
  ![Contact Manager](images/glimmer-contact-manager.png)
173
176
 
174
- NOTE: Glimmer is in beta mode. Please help make better by [contributing](#contributing), adopting for small or low risk projects, and providing feedback.
175
-
176
177
  ## Table of contents
177
178
 
178
179
  - [Glimmer (Ruby Desktop Development GUI Library)](#-glimmer-ruby-desktop-development-gui-library)
@@ -202,7 +203,7 @@ NOTE: Glimmer is in beta mode. Please help make better by [contributing](#contri
202
203
  - [Raw JRuby Command](#raw-jruby-command)
203
204
  - [Mac Support](#mac-support)
204
205
  - [Girb (Glimmer irb) Command](#girb-glimmer-irb-command)
205
- - [Glimmer DSL Syntax](#glimmer-dsl-syntax)
206
+ - [Glimmer GUI DSL Syntax](#glimmer-gui-dsl-syntax)
206
207
  - [Widgets](#widgets)
207
208
  - [Display](#display)
208
209
  - [SWT Proxies](#swt-proxies)
@@ -272,6 +273,7 @@ NOTE: Glimmer is in beta mode. Please help make better by [contributing](#contri
272
273
  - [In Production](#in-production)
273
274
  - [Math Bowling](#math-bowling)
274
275
  - [Are We There Yet?](#are-we-there-yet)
276
+ - [Garderie Rainbow Daily Agenda](#garderie-rainbow-daily-agenda)
275
277
  - [Packaging & Distribution](#packaging--distribution)
276
278
  - [Packaging Defaults](#packaging-defaults)
277
279
  - [Packaging Configuration](#packaging-configuration)
@@ -279,6 +281,7 @@ NOTE: Glimmer is in beta mode. Please help make better by [contributing](#contri
279
281
  - [Mac Application Distribution](#mac-application-distribution)
280
282
  - [Self Signed Certificate](#self-signed-certificate)
281
283
  - [Gotchas](#gotchas)
284
+ - [App Updates](#app-updates)
282
285
  - [Resources](#resources)
283
286
  - [Help](#help)
284
287
  - [Issues](#issues)
@@ -313,18 +316,17 @@ https://www.eclipse.org/swt/faq.php
313
316
 
314
317
  ## Pre-requisites
315
318
 
316
- - SWT 4.15 (comes included in Glimmer gem)
317
- - JRuby 9.2.12.0 (supporting Ruby 2.5.x syntax) (find at [https://www.jruby.org/download](https://www.jruby.org/download))
318
- - JDK 8 (find at [https://www.oracle.com/java/technologies/javase-downloads.html](https://www.oracle.com/java/technologies/javase-downloads.html))
319
- - (Optional) RVM is needed for [Scaffolding](#scaffolding) only (find at [https://rvm.io/](https://rvm.io/))
319
+ - SWT 4.16 (comes included in Glimmer gem)
320
+ - JRuby 9.2.13.0 (supporting Ruby 2.5.x syntax) (get via [RVM](http://rvm.io) on Mac and Linux or find at [https://www.jruby.org/download](https://www.jruby.org/download) for Windows)
321
+ - JDK 8 (find at https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html)
320
322
 
321
- On **Mac** and **Linux**, an easy way to obtain JRuby is through [RVM](http://rvm.io) by running:
323
+ To obtain JRuby through [RVM](http://rvm.io), you may run:
322
324
 
323
325
  ```bash
324
- rvm install jruby-9.2.12.0
326
+ rvm install jruby-9.2.13.0
325
327
  ```
326
328
 
327
- Glimmer might still work on lower versions of Java, JRuby and SWT, but there are no guarantees, so it is best to stick to the pre-requisites outlined above.
329
+ Glimmer might still work on other versions of Java, JRuby and SWT, but there are no guarantees, so it is best to stick to the pre-requisites outlined above.
328
330
 
329
331
  ## Setup
330
332
 
@@ -332,16 +334,16 @@ Please follow these instructions to make the `glimmer` command available on your
332
334
 
333
335
  If you intend to learn the basics of Glimmer but are not ready to build a Glimmer app yet, pick Option 1 ([Direct Install](#option-1-direct-install)).
334
336
 
335
- If you intend to build a Glimmer app from scratch on the Mac, pick Option 1 ([Direct Install](#option-1-direct-install)) to leverage [Glimmer Scaffolding](#scaffolding) (only available on the Mac).
337
+ If you intend to build a Glimmer app from scratch with [scaffolding](#scaffolding), pick Option 1 ([Direct Install](#option-1-direct-install)) as well.
336
338
 
337
- Otherwise, Option 2 ([Bundler](#option-2-bundler)) is recommended for building Glimmer apps on other platforms (Windows and Linux).
339
+ Otherwise, Option 2 ([Bundler](#option-2-bundler)) can be followed in rare cases where you want to build an app without [scaffolding](#scaffolding).
338
340
 
339
341
  ### Option 1: Direct Install
340
- (Use for [Scaffolding](#scaffolding) on the Mac)
342
+ (Use for [Scaffolding](#scaffolding))
341
343
 
342
344
  Run this command to install directly:
343
345
  ```
344
- jgem install glimmer-dsl-swt -v 0.4.1
346
+ jgem install glimmer-dsl-swt -v 0.6.1
345
347
  ```
346
348
 
347
349
  `jgem` is JRuby's version of `gem` command.
@@ -359,7 +361,7 @@ Note: if you're using activerecord or activesupport, keep in mind that Glimmer u
359
361
 
360
362
  Add the following to `Gemfile`:
361
363
  ```
362
- gem 'glimmer-dsl-swt', '~> 0.4.1'
364
+ gem 'glimmer-dsl-swt', '~> 0.6.1'
363
365
  ```
364
366
 
365
367
  And, then run:
@@ -375,7 +377,7 @@ You may learn more about other Glimmer related gems ([`glimmer-dsl-opal`](https:
375
377
 
376
378
  The `glimmer` command allows you to run, scaffold, package, and list Glimmer applications/gems.
377
379
 
378
- If you are new to Glimmer, you may read the Basic Usage section and skip the rest until you have gone through [Girb (Glimmer irb) Command](#girb-glimmer-irb-command), [Glimmer DSL Syntax](#glimmer-dsl-syntax), and [Samples](#samples).
380
+ If you are new to Glimmer, you may read the Basic Usage section and skip the rest until you have gone through [Girb (Glimmer irb) Command](#girb-glimmer-irb-command), [Glimmer GUI DSL Syntax](#glimmer-gui-dsl-syntax), and [Samples](#samples).
379
381
 
380
382
  ### Basic Usage
381
383
 
@@ -413,19 +415,20 @@ Either a single task or one or more applications may be specified.
413
415
  When a task is specified, it runs via rake. Some tasks take arguments in square brackets.
414
416
 
415
417
  Available tasks are below (you may also lookup by adding `require 'glimmer/rake_task'` in Rakefile and running rake -T):
416
- glimmer list:custom_shell_gems[query] # List Glimmer custom shell gems available at rubygems.org (query is optional)
417
- glimmer list:custom_widget_gems[query] # List Glimmer custom widget gems available at rubygems.org (query is optional)
418
- glimmer list:dsl_gems[query] # List Glimmer DSL gems available at rubygems.org (query is optional)
419
- glimmer package # Package app for distribution (generating config, jar, and native files)
420
- glimmer package:clean # Clean by removing "dist" and "packages" directories
421
- glimmer package:config # Generate JAR config file
422
- glimmer package:jar # Generate JAR file
423
- glimmer package:native # Generate Native files (DMG/PKG/APP on the Mac)
424
- glimmer scaffold[app_name] # Scaffold a Glimmer application directory structure to begin building a new app
425
- glimmer scaffold:custom_shell[custom_shell_name,namespace] # Scaffold a Glimmer::UI::CustomShell subclass (represents a full window view) under app/views (namespace is optional)
426
- glimmer scaffold:custom_shell_gem[custom_shell_name,namespace] # Scaffold a Glimmer::UI::CustomShell subclass (represents a full window view) under its own Ruby gem + app project (namespace is required)
427
- glimmer scaffold:custom_widget[custom_widget_name,namespace] # Scaffold a Glimmer::UI::CustomWidget subclass (represents a part of a view) under app/views (namespace is optional)
428
- glimmer scaffold:custom_widget_gem[custom_widget_name,namespace] # Scaffold a Glimmer::UI::CustomWidget subclass (represents a part of a view) under its own Ruby gem project (namespace is required)
418
+ glimmer list:gems:customshell[query] # List Glimmer custom shell gems available at rubygems.org (query is optional) [alt: list:gems:cs]
419
+ glimmer list:gems:customwidget[query] # List Glimmer custom widget gems available at rubygems.org (query is optional) [alt: list:gems:cw]
420
+ glimmer list:gems:dsl[query] # List Glimmer DSL gems available at rubygems.org (query is optional)
421
+ glimmer package[type] # Package app for distribution (generating config, jar, and native files) (type is optional)
422
+ glimmer package:clean # Clean by removing "dist" and "packages" directories
423
+ glimmer package:config # Generate JAR config file
424
+ glimmer package:jar # Generate JAR file
425
+ glimmer package:lock_jars # Lock JARs
426
+ glimmer package:native[type] # Generate Native files (DMG/PKG/APP on the Mac, MSI/EXE/IMAGE on Windows, RPM/DEB on Linux) (type is optional)
427
+ glimmer scaffold[app_name] # Scaffold Glimmer application directory structure to build a new app
428
+ glimmer scaffold:customshell[name,namespace] # Scaffold Glimmer::UI::CustomShell subclass (full window view) under app/views (namespace is optional) [alt: scaffold:cs]
429
+ glimmer scaffold:customwidget[name,namespace] # Scaffold Glimmer::UI::CustomWidget subclass (part of a view) under app/views (namespace is optional) [alt: scaffold:cw]
430
+ glimmer scaffold:gem:customshell[name,namespace] # Scaffold Glimmer::UI::CustomShell subclass (full window view) under its own Ruby gem + app project (namespace is required) [alt: scaffold:gem:cs]
431
+ glimmer scaffold:gem:customwidget[name,namespace] # Scaffold Glimmer::UI::CustomWidget subclass (part of a view) under its own Ruby gem project (namespace is required) [alt: scaffold:gem:cw]
429
432
 
430
433
  When applications are specified, they are run using JRuby,
431
434
  automatically preloading the glimmer Ruby gem and SWT jar dependency.
@@ -467,7 +470,7 @@ getting you to a running and delivered state of an advanced "Hello, World!" Glim
467
470
  This should greatly facilitate building a new Glimmer app by helping you be productive and focus on app details while
468
471
  letting Glimmer scaffolding take care of initial app file structure concerns, such as adding:
469
472
  - Main application class that includes Glimmer
470
- - Main application view that houses main window content, about dialog, and preferences dialog
473
+ - Main application view that houses main window content, menu, about dialog, and preferences dialog
471
474
  - View and Model directories
472
475
  - Rakefile including Glimmer tasks
473
476
  - Version
@@ -475,7 +478,7 @@ letting Glimmer scaffolding take care of initial app file structure concerns, su
475
478
  - Icon
476
479
  - Bin file for starting application
477
480
 
478
- NOTE: Scaffolding requires RVM and currently supports Mac packaging only at the moment.
481
+ NOTE: Scaffolding supports Mac and Windows packaging at the moment.
479
482
 
480
483
  #### App
481
484
 
@@ -511,20 +514,35 @@ Created CarMaker/bin/car_maker
511
514
  ...
512
515
  ```
513
516
 
514
- Eventually, it will launch an advanced "Hello, World!" app window having the title of your application and a Mac icon.
517
+ Eventually, it will launch an advanced "Hello, World!" app window having the title of your application.
515
518
 
516
519
  ![Glimmer Scaffold App](images/glimmer-scaffolding-app.png)
517
520
 
518
- On the Mac, it also comes with a boilerplate Preferences dialog.
521
+ It also comes with a boilerplate Preferences dialog.
519
522
 
520
523
  ![Glimmer Scaffold App Preferences](images/glimmer-scaffolding-app-preferences.png)
521
524
 
525
+ Here is a Windows scaffolded app called Greeter:
526
+
527
+ ![Glimmer Scaffold App Windows](images/glimmer-scaffolding-app-windows.png)
528
+
529
+ Here is the Windows version of the boilerplate Preferences dialog.
530
+
531
+ ![Glimmer Scaffold App Windows Preferences](images/glimmer-scaffolding-app-windows-preferences.png)
532
+
533
+
522
534
  #### Custom Shell
523
535
 
524
536
  To scaffold a Glimmer custom shell (full window view) for an existing Glimmer app, run the following command:
525
537
 
526
538
  ```
527
- glimmer scaffold:custom_shell[custom_shell_name]
539
+ glimmer scaffold:customshell[name]
540
+ ```
541
+
542
+ Or the following alternative abbreviation:
543
+
544
+ ```
545
+ glimmer scaffold:cs[name]
528
546
  ```
529
547
 
530
548
  #### Custom Widget
@@ -532,13 +550,19 @@ glimmer scaffold:custom_shell[custom_shell_name]
532
550
  To scaffold a Glimmer custom widget (part of a view) for an existing Glimmer app, run the following command:
533
551
 
534
552
  ```
535
- glimmer scaffold:custom_widget[custom_widget_name]
553
+ glimmer scaffold:customwidget[name]
554
+ ```
555
+
556
+ Or the following alternative abbreviation:
557
+
558
+ ```
559
+ glimmer scaffold:cw[name]
536
560
  ```
537
561
 
538
562
  #### Custom Shell Gem
539
563
 
540
564
  Custom shell gems are self-contained Glimmer apps as well as reusable custom shells.
541
- They have everything scaffolded Glimmer apps come with in addition to gem content like a Jeweler Rakefile that can build gemspec and release gems.
565
+ They have everything scaffolded Glimmer apps come with in addition to gem content like a [jeweler](https://github.com/technicalpickles/jeweler) Rakefile that can build gemspec and release gems.
542
566
  Unlike scaffolded Glimmer apps, custom shell gem content lives under the `lib` directory (not `app`).
543
567
  They can be packaged as both a native executable (e.g. Mac DMG/PKG/APP) and a Ruby gem.
544
568
  Of course, you can just build a Ruby gem and disregard native executable packaging if you do not need it.
@@ -546,7 +570,13 @@ Of course, you can just build a Ruby gem and disregard native executable packagi
546
570
  To scaffold a Glimmer custom shell gem (full window view distributed as a Ruby gem), run the following command:
547
571
 
548
572
  ```
549
- glimmer scaffold:custom_shell_gem[custom_shell_name, namespace]
573
+ glimmer scaffold:gem:customshell[name,namespace]
574
+ ```
575
+
576
+ Or the following alternative abbreviation:
577
+
578
+ ```
579
+ glimmer scaffold:gem:cs[name,namespace]
550
580
  ```
551
581
 
552
582
  It is important to specify a namespace to avoid having your gem clash with existing gems.
@@ -565,9 +595,16 @@ Examples:
565
595
  To scaffold a Glimmer custom widget gem (part of a view distributed as a Ruby gem), run the following command:
566
596
 
567
597
  ```
568
- glimmer scaffold:custom_widget_gem[custom_widget_name, namespace]
598
+ glimmer scaffold:gem:customwidget[name,namespace]
599
+ ```
600
+
601
+ Or the following alternative abbreviation:
602
+
603
+ ```
604
+ glimmer scaffold:gem:cw[name,namespace]
569
605
  ```
570
606
 
607
+
571
608
  It is important to specify a namespace to avoid having your gem clash with existing gems.
572
609
 
573
610
  The Ruby gem name will follow the convention "glimmer-cw-customwidgetname-namespace" (the 'cw' is for Custom Widget)
@@ -588,13 +625,19 @@ The `glimmer` command comes with tasks for listing Glimmer related gems to make
588
625
  The following command lists available Glimmer [Custom Shell Gems](#custom-shell-gem) (prefixed with "glimmer-cs-" by scaffolding convention) created by the the Glimmer community and published on [rubygems.org](http://www.rubygems.org):
589
626
 
590
627
  ```
591
- glimmer list:custom_shell_gems[query] # List Glimmer custom shell gems available at rubygems.org (query is optional)
628
+ glimmer list:gems:customshell[query]
629
+ ```
630
+
631
+ Or the following alternative abbreviation:
632
+
633
+ ```
634
+ glimmer list:gems:cs[query]
592
635
  ```
593
636
 
594
637
  Example:
595
638
 
596
639
  ```
597
- glimmer list:custom_shell_gems
640
+ glimmer list:gems:cs
598
641
  ```
599
642
 
600
643
  Output:
@@ -606,7 +649,7 @@ Output:
606
649
  Name Gem Version Author Description
607
650
 
608
651
  Calculator glimmer-cs-calculator 1.0.1 Andy Maleh Calculator - Glimmer Custom Shell
609
- Gladiator glimmer-cs-gladiator 0.2.0 Andy Maleh Gladiator (Glimmer Editor) - Glimmer Custom Shell
652
+ Gladiator glimmer-cs-gladiator 0.2.3 Andy Maleh Gladiator (Glimmer Editor) - Glimmer Custom Shell
610
653
 
611
654
  ```
612
655
 
@@ -615,7 +658,13 @@ Output:
615
658
  The following command lists available Glimmer [Custom Widget Gems](#custom-widget-gem) (prefixed with "glimmer-cw-" by scaffolding convention) created by the the Glimmer community and published on [rubygems.org](http://www.rubygems.org):
616
659
 
617
660
  ```
618
- glimmer list:custom_widget_gems[query] # List Glimmer custom widget gems available at rubygems.org (query is optional)
661
+ glimmer list:gems:customwidget[query]
662
+ ```
663
+
664
+ Or the following alternative abbreviation:
665
+
666
+ ```
667
+ glimmer list:gems:cw[query]
619
668
  ```
620
669
 
621
670
  Example:
@@ -623,7 +672,7 @@ Example:
623
672
  Check if there is a custom video widget for Glimmer.
624
673
 
625
674
  ```
626
- glimmer list:custom_widget_gems[video]
675
+ glimmer list:gems:cw[video]
627
676
  ```
628
677
 
629
678
  Output:
@@ -634,7 +683,7 @@ Output:
634
683
 
635
684
  Name Gem Version Author Description
636
685
 
637
- Video glimmer-cw-video 0.1.1 Andy Maleh Glimmer Custom Widget - Video
686
+ Video glimmer-cw-video 0.1.3 Andy Maleh Glimmer Custom Widget - Video
638
687
 
639
688
  ```
640
689
 
@@ -643,13 +692,13 @@ Output:
643
692
  The following command lists available Glimmer [DSL Gems](#multi-dsl-support) (prefixed with "glimmer-dsl-" by convention) created by the the Glimmer community and published on [rubygems.org](http://www.rubygems.org):
644
693
 
645
694
  ```
646
- glimmer list:dsl_gems[query] # List Glimmer DSL gems available at rubygems.org (query is optional)
695
+ glimmer list:gems:dsl[query]
647
696
  ```
648
697
 
649
698
  Example:
650
699
 
651
700
  ```
652
- glimmer list:dsl_gems
701
+ glimmer list:gems:dsl
653
702
  ```
654
703
 
655
704
  Output:
@@ -660,10 +709,10 @@ Output:
660
709
 
661
710
  Name Gem Version Author Description
662
711
 
663
- Css glimmer-dsl-css 0.1.0 AndyMaleh Glimmer DSL for CSS
664
- Opal glimmer-dsl-opal 0.0.9 AndyMaleh Glimmer DSL for Opal
665
- Swt glimmer-dsl-swt 0.4.1 AndyMaleh Glimmer DSL for SWT
666
- Xml glimmer-dsl-xml 0.1.0 AndyMaleh Glimmer DSL for XML
712
+ Css glimmer-dsl-css 0.2.0 AndyMaleh Glimmer DSL for CSS
713
+ Opal glimmer-dsl-opal 0.1.0 AndyMaleh Glimmer DSL for Opal
714
+ Swt glimmer-dsl-swt 0.6.1 AndyMaleh Glimmer DSL for SWT
715
+ Xml glimmer-dsl-xml 0.2.0 AndyMaleh Glimmer DSL for XML
667
716
 
668
717
  ```
669
718
 
@@ -716,13 +765,24 @@ Watch out for hands-on examples in this README indicated by "you may copy/paste
716
765
 
717
766
  Keep in mind that all samples live under [https://github.com/AndyObtiva/glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt)
718
767
 
719
- ## Glimmer DSL Syntax
768
+ ## Glimmer GUI DSL Syntax
720
769
 
721
- Glimmer DSL syntax consists of static keywords and dynamic keywords to build and bind user-interface objects.
770
+ Glimmer is mainly a GUI DSL with a lightweight visual syntax that makes it easy to visualize the nesting of widgets in the GUI hierarchy tree.
722
771
 
723
- Static keywords are pre-identified keywords in the Glimmer DSL, such as `shell`, `message_box`, `async_exec`, and `bind`.
772
+ The GUI DSL intentionally avoids overly verbose syntax, requiring as little declarative code as possible to describe what GUI to render, how to style it, and what properties to data-bind to the Models.
724
773
 
725
- Dynamic keywords are dynamically figured out from available SWT widgets, custom widgets, and properties. Examples are: `label`, `combo`, and `list`.
774
+ As such, it breaks off from Ruby's convention of using `do end` for multi-line blocks, opting instead for the lightweight and visual `{ }` curly brace blocks everywhere inside the GUI DSL. More details about Glimmer's syntax conventions may be found in the [Glimmer Style Guide](#glimmer-style-guide)
775
+
776
+ Glimmer DSL syntax consists mainly of:
777
+ - keywords (e.g. `table` for a table widget)
778
+ - style/args (e.g. :multi as in `table(:multi)` for a multi-line selection table widget)
779
+ - content (e.g. `{ table_column { text 'Name'} }` as in `table(:multi) { table_column { text 'name'} }` for a multi-line selection table widget with a table column having header text property `'Name'` as content)
780
+
781
+ Glimmer keywords may be static or dynamic.
782
+
783
+ Static keywords are pre-identified keywords in the Glimmer DSL, such as `shell`, `display`, `message_box`, `async_exec`, `sync_exec`, and `bind`.
784
+
785
+ Dynamic keywords are dynamically figured out from currently imported (aka required/loaded) SWT widgets, custom widgets, and widget properties. Examples are: `label`, `combo`, and `list` for widgets and `enabled`, `text`, and `selection` for properties.
726
786
 
727
787
  The only reason to distinguish between the two types of Glimmer DSL keywords is to realize that importing new Glimmer [custom widgets](#custom-widgets) and Java SWT custom widget libraries automatically expands Glimmer's DSL vocabulary via new dynamic keywords.
728
788
 
@@ -742,9 +802,9 @@ https://www.eclipse.org/swt/widgets/
742
802
 
743
803
  This screenshot taken from the link above should give a glimpse of how SWT widgets look and feel:
744
804
 
745
- ![SWT Widgets](images/glimmer-swt-widgets.png)
805
+ [![SWT Widgets](images/glimmer-swt-widgets.png)](https://www.eclipse.org/swt/widgets/)
746
806
 
747
- In Glimmer DSL, widgets are declared with lowercase underscored names mirroring their SWT names minus the package name:
807
+ In Glimmer DSL, widgets are declared with lowercase underscored names mirroring their SWT names minus the package name. For example, here are some Glimmer widgets and their SWT counterparts:
748
808
 
749
809
  - `shell` instantiates `org.eclipse.swt.widgets.Shell`
750
810
  - `text` instantiates `org.eclipse.swt.widgets.Text`
@@ -760,8 +820,8 @@ In Glimmer DSL, widgets are declared with lowercase underscored names mirroring
760
820
  - `list` instantiates `org.eclipse.swt.widgets.List`
761
821
 
762
822
  Every **widget** is sufficiently declared by name, but may optionally be accompanied with:
763
- - SWT **style** ***argument*** wrapped by parenthesis according to [Glimmer Style Guide](#glimmer-style-guide) (see [next section](#widget-styles) for details).
764
- - Ruby block containing **properties** (widget attributes) and **content** (nested widgets)
823
+ - SWT **style**/***arguments*** wrapped by parenthesis according to [Glimmer Style Guide](#glimmer-style-guide) (see [next section](#widget-styles) for details).
824
+ - Ruby block containing **content**, which may be **properties** (e.g. `enabled false`) or nested **widgets** (e.g. `table_column` nested inside `table`)
765
825
 
766
826
  For example, if we were to revisit `samples/hello/hello_world.rb` above (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
767
827
 
@@ -843,6 +903,8 @@ shell {
843
903
  }.open
844
904
  ```
845
905
 
906
+ If you are new to Glimmer, you have learned enough to start running some [samples](#samples). Go ahead and run all Glimmer [samples](#samples), and come back to read the rest in any order you like since this material is more organized like a reference.
907
+
846
908
  #### Display
847
909
 
848
910
  SWT Display is a singleton in Glimmer. It is used in SWT to represent your display device, allowing you to manage GUI globally
@@ -930,6 +992,21 @@ include Glimmer
930
992
  @shell.open
931
993
  ```
932
994
 
995
+ ![Hello Message Box Dialog](images/glimmer-hello-message-box-dialog.png)
996
+
997
+ It is also possible to use `message_box` even before instantiating the first `shell` ([Glimmer](https://rubygems.org/gems/glimmer) builds a throwaway `shell` parent automatically for it):
998
+
999
+ Example (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
1000
+
1001
+ ```ruby
1002
+ include Glimmer
1003
+
1004
+ message_box {
1005
+ text 'Greeting'
1006
+ message "Hello, World!"
1007
+ }.open
1008
+ ```
1009
+
933
1010
  ##### `#swt_widget`
934
1011
 
935
1012
  Glimmer widget objects come with an instance method `#swt_widget` that returns the actual SWT `Widget` object wrapped by the Glimmer widget object. It is useful in cases you'd like to do some custom SWT programming outside of Glimmer.
@@ -949,6 +1026,24 @@ Shell widget proxy has extra methods specific to SWT Shell:
949
1026
  - `#pack`: Packs contained widgets using SWT's `Shell#pack` method
950
1027
  - `#pack_same_size`: Packs contained widgets without changing shell's size when widget sizes change
951
1028
 
1029
+ ##### Shell Icon
1030
+
1031
+ To set the shell icon, simply set the `image` property under the `shell` widget. This shows up in the operating system toolbar and app-switcher (e.g. CMD+TAB) (and application window top-left corner in Windows)
1032
+
1033
+ Example:
1034
+
1035
+ ```ruby
1036
+ shell {
1037
+ # ...
1038
+ image 'path/to/image.png'
1039
+ # ...
1040
+ }
1041
+ ```
1042
+
1043
+ ###### Shell Icon Tip for Packaging on Windows
1044
+
1045
+ When setting shell icon for a [packaged](#packaging--distribution) app, which has a JAR file at its core, you can reference the `ico` file that ships with the app by going one level up (e.g. `'../AppName.ico'`)
1046
+
952
1047
  #### Dialog
953
1048
 
954
1049
  Dialog is a variation on Shell. It is basically a shell that is modal (blocks what's behind it) and belongs to another shell. It only has a close button.
@@ -1124,7 +1219,7 @@ text(:center, :border) { # Multiple SWT styles separated by comma
1124
1219
  Glimmer ships with SWT style **smart defaults** so you wouldn't have to set them yourself most of the time (albeit you can always override them):
1125
1220
 
1126
1221
  - `text(:border)`
1127
- - `table(:border)`
1222
+ - `table(:border, :virtual, :full_selection)`
1128
1223
  - `tree(:border, :virtual, :v_scroll, :h_scroll)`
1129
1224
  - `spinner(:border)`
1130
1225
  - `list(:border, :v_scroll)`
@@ -1200,7 +1295,7 @@ button {
1200
1295
 
1201
1296
  In the above example, the `text` widget `enabled` property was data-bound to `#empty` method on `@tic_tac_toe_board.box(row, column)` (learn more about data-binding below)
1202
1297
 
1203
- #### Colors
1298
+ #### Color
1204
1299
 
1205
1300
  Colors make up a subset of widget properties. SWT accepts color objects created with RGB (Red Green Blue) or RGBA (Red Green Blue Alpha). Glimmer supports constructing color objects using the `rgb` and `rgba` DSL keywords.
1206
1301
 
@@ -1249,7 +1344,7 @@ Example:
1249
1344
  color(:black).swt_color # returns SWT Color object
1250
1345
  ```
1251
1346
 
1252
- #### Fonts
1347
+ #### Font
1253
1348
 
1254
1349
  Fonts are represented in Glimmer as a hash of name, height, and style keys.
1255
1350
 
@@ -1278,7 +1373,34 @@ label {
1278
1373
  # ...
1279
1374
  ```
1280
1375
 
1281
- ### Layouts
1376
+ You may simply use the standalone `font` keyword without nesting in a parent if there is a need to build a Font object to use in manual SWT programming outside of widget font property setting.
1377
+
1378
+ Example:
1379
+
1380
+ ```ruby
1381
+ @font = font(name: 'Arial', height: 36, style: :normal)
1382
+ ```
1383
+
1384
+ ### Cursor
1385
+
1386
+ SWT widget `cursor` property represents the mouse cursor you see on the screen when you hover over that widget.
1387
+
1388
+ The `Display` class provides a way to obtain standard system cursors matching of the SWT style constants starting with prefix `CURSOR_` (e.g. `SWT::CURSOR_HELP` shows a question mark mouse cursor)
1389
+
1390
+ Glimmer provides an easier way to obtain and set `cursor` property on a widget by simply mentioning the SWT style constant as an abbreviated symbol excluding the "CURSOR_" suffix.
1391
+
1392
+ Example:
1393
+
1394
+ ```ruby
1395
+ shell {
1396
+ minimum_size 128, 128
1397
+ cursor :appstarting
1398
+ }
1399
+ ```
1400
+
1401
+ This sets the shell `cursor` to that of `SWT::CURSOR_APPSTARTING`
1402
+
1403
+ ### Layout
1282
1404
 
1283
1405
  Glimmer lays widgets out visually using SWT layouts, which can only be set on composite widget and subclasses.
1284
1406
 
@@ -1840,7 +1962,8 @@ Let's revisit the Tic Tac Toe example shown near the beginning of the page:
1840
1962
  ```ruby
1841
1963
  shell {
1842
1964
  text "Tic-Tac-Toe"
1843
- composite {
1965
+ minimum_size 150, 178
1966
+ composite {
1844
1967
  grid_layout 3, true
1845
1968
  (1..3).each { |row|
1846
1969
  (1..3).each { |column|
@@ -2542,11 +2665,9 @@ Glimmer configuration may be done via the `Glimmer::Config` module.
2542
2665
 
2543
2666
  ### logger
2544
2667
 
2545
- Glimmer supports logging via a standard `STDOUT` Ruby `Logger` configured in the `Glimmer::Config.logger` config option.
2668
+ The Glimmer DSL engine supports logging via a standard `STDOUT` Ruby `Logger` configured in the `Glimmer::Config.logger` config option.
2546
2669
  It is set to level Logger::ERROR by default.
2547
2670
  Log level may be adjusted via `Glimmer::Config.logger.level` just like any other Ruby Logger.
2548
- It may be replaced with a custom logger via `Glimmer::Config.logger = custom_logger`
2549
- All logging is done lazily via blocks (e.g. `logger.debug {message}`) to avoid affecting app performance with logging when below the configured logging level threshold.
2550
2671
 
2551
2672
  Example:
2552
2673
 
@@ -2571,6 +2692,55 @@ D, [2017-07-21T19:23:12.878434 #35707] DEBUG -- : WidgetCommandHandler will hand
2571
2692
  D, [2017-07-21T19:23:12.878798 #35707] DEBUG -- : widget styles are: [:multi]
2572
2693
  ```
2573
2694
 
2695
+ The `logger` instance may be replaced with a custom logger via `Glimmer::Config.logger = custom_logger`
2696
+
2697
+ To reset `logger` to the default instance, you may call `Glimmer::Config.reset_logger!`
2698
+
2699
+ All logging is done lazily via blocks (e.g. `logger.debug {message}`) to avoid affecting app performance with logging when below the configured logging level threshold.
2700
+
2701
+ [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt) enhances Glimmer default logging support via the Ruby [`logging`](https://github.com/TwP/logging) gem, enabling buffered asynchronous logging in a separate thread, thus completely unhindering normal desktop app performance.
2702
+
2703
+ Other config options related to the [`logging`](https://github.com/TwP/logging) gem are mentioned below.
2704
+
2705
+ #### logging_devices
2706
+
2707
+ This is an array of these possible values: `:stdout` (default), `:stderr`, `:file`, `:syslog` (default), `:stringio`
2708
+
2709
+ It defaults to `[:stdout, :syslog]`
2710
+
2711
+ When `:file` is included, Glimmer creates a 'log' directory directly below the Glimmer app local directory.
2712
+ It may also be customized further via the `logging_device_file_options` option.
2713
+ This is useful on Windows as an alternative to `syslog`, which is not available on Windows by default.
2714
+
2715
+ #### logging_device_file_options
2716
+
2717
+ This is a hash of [`logging`](https://github.com/TwP/logging) gem options for the `:file` logging device.
2718
+
2719
+ Default: `{size: 1_000_000, age: 'daily', roll_by: 'number'}`
2720
+
2721
+ That ensures splitting log files at the 1MB size and daily, rolling them by unique number.
2722
+
2723
+ #### logging_appender_options
2724
+
2725
+ Appender options is a hash passed as options to every appender (logging device) used in the [`logging`](https://github.com/TwP/logging) gem.
2726
+
2727
+ Default: `{async: true, auto_flushing: 500, write_size: 500, flush_period: 60, immediate_at: [:error, :fatal], layout: logging_layout}`
2728
+
2729
+ That ensures asynchronous buffered logging that is flushed every 500 messages and 60 seconds, or immediately at error and fatal log levels
2730
+
2731
+ #### logging_layout
2732
+
2733
+ This is a [`logging`](https://github.com/TwP/logging) gem layout that formats the logging output.
2734
+
2735
+ Default:
2736
+
2737
+ ```
2738
+ Logging.layouts.pattern(
2739
+ pattern: '[%d] %-5l %c: %m\n',
2740
+ date_pattern: '%Y-%m-%d %H:%M:%S'
2741
+ )
2742
+ ```
2743
+
2574
2744
  ### import_swt_packages
2575
2745
 
2576
2746
  Glimmer automatically imports all SWT Java packages upon adding `include Glimmer`, `include Glimmer::UI::CustomWidget`, or `include Glimmer::UI::CustomShell` to a class or module. It relies on JRuby's `include_package` for lazy-importing upon first reference of a Java class.
@@ -2920,6 +3090,8 @@ This sample demonstrates a full MVC application, including GUI layout, text and
2920
3090
 
2921
3091
  Code:
2922
3092
 
3093
+ (Please note that on some Linux instances where the display x-axis is set to double-scale, you need to set the `shell` `minimum_size` to `300, 178` instead of `150, 178`)
3094
+
2923
3095
  [samples/elaborate/tic_tac_toe.rb](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/samples/elaborate/tic_tac_toe.rb)
2924
3096
 
2925
3097
  Run:
@@ -2995,6 +3167,8 @@ Gladiator is a good demonstration of:
2995
3167
 
2996
3168
  The following production apps have been built with Glimmer.
2997
3169
 
3170
+ If you have a Glimmer app you would like referenced here, please mention in a Pull Request.
3171
+
2998
3172
  ### Math Bowling
2999
3173
 
3000
3174
  [<img alt="Math Bowling Logo" src="https://raw.githubusercontent.com/AndyObtiva/MathBowling/master/images/math-bowling-logo.png" width="40" />Math Bowling](https://github.com/AndyObtiva/MathBowling): an educational math game for elementary level kids
@@ -3003,20 +3177,30 @@ The following production apps have been built with Glimmer.
3003
3177
 
3004
3178
  [<img alt="Are We There Yet Logo" src="https://raw.githubusercontent.com/AndyObtiva/are-we-there-yet/master/are-we-there-yet-logo.svg" width="40" />Are We There Yet?](https://github.com/AndyObtiva/are-we-there-yet): A tool that helps you learn when your small projects will finish
3005
3179
 
3006
- If you have a Glimmer app you would like referenced here, please mention in a Pull Request.
3180
+ ### Garderie Rainbow Daily Agenda
3181
+
3182
+ [<img alt="Garderie Rainbow Daily Agenda Logo" src="https://github.com/AndyObtiva/garderie_rainbow_daily_agenda/raw/master/images/garderie_rainbow_daily_agenda_logo.png" width="40" />Garderie Rainbow Daily Agenda](https://github.com/AndyObtiva/garderie_rainbow_daily_agenda): A child nursery daily agenda reporting desktop app
3007
3183
 
3008
3184
  ## Packaging & Distribution
3009
3185
 
3010
3186
  Glimmer apps may be packaged and distributed on the Mac, Windows, and Linux via these tools:
3011
3187
  - Warbler (https://github.com/jruby/warbler): Enables bundling a Glimmer app into a JAR file
3012
- - javapackager (https://docs.oracle.com/javase/8/docs/technotes/tools/unix/javapackager.html): Enables packaging a JAR file as a DMG file on Mac, EXE on Windows, and multiple Linux supported formats on Linux.
3188
+ - javapackager (https://docs.oracle.com/javase/8/docs/technotes/tools/unix/javapackager.html): Enables packaging a JAR file as a DMG/PKG/APP file on Mac, MSI/EXE on Windows, and DEB/RPM on Linux.
3013
3189
 
3014
- Glimmer simplifies the process of Mac packaging via the `glimmer package` command. It works out of the box for any application generated by [Glimmer Scaffolding](#scaffolding):
3190
+ Glimmer simplifies the process of Mac and Windows packaging via the `glimmer package` command:
3015
3191
 
3016
3192
  ```
3017
3193
  glimmer package
3018
3194
  ```
3019
3195
 
3196
+ It works out of the box for any application generated by [Glimmer Scaffolding](#scaffolding).
3197
+
3198
+ Otherwise, if you are using Glimmer manually, to make the `glimmer package` command available, you must add the following line to your application `Rakefile`:
3199
+
3200
+ ```ruby
3201
+ require 'glimmer/rake_task'
3202
+ ```
3203
+
3020
3204
  This will automatically generate a JAR file under `./dist` directory using Warbler, which is then used to automatically generate a DMG file (and pkg/app) under `./packages/bundles` using `javapackager`.
3021
3205
  JAR file name will match your application local directory name (e.g. `MathBowling.jar` for `~/code/MathBowling`)
3022
3206
  DMG file name will match the humanized local directory name + dash + application version (e.g. `Math Bowling-1.0.dmg` for `~/code/MathBowling` with version 1.0 or unspecified)
@@ -3024,6 +3208,14 @@ DMG file name will match the humanized local directory name + dash + application
3024
3208
  The `glimmer package` command will automatically set "mac.CFBundleIdentifier" to ="org.#{project_name}.application.#{project_name}".
3025
3209
  You may override by configuring as an extra argument for javapackger (e.g. Glimmer::Package.javapackager_extra_args = " -Bmac.CFBundleIdentifier=org.andymaleh.application.MathBowling")
3026
3210
 
3211
+ You may choose to generate a specific type of packaging by passing the `[type]` option:
3212
+
3213
+ ```
3214
+ glimmer package[msi]
3215
+ ```
3216
+
3217
+ That generates an MSI file on Windows (could specify exe or image as alternatives on Windows).
3218
+
3027
3219
  ### Packaging Defaults
3028
3220
 
3029
3221
  Glimmer employs smart defaults in packaging.
@@ -3084,6 +3276,14 @@ JAVAPACKAGER_EXTRA_ARGS='-Bmac.CFBundleName="Math Bowling Game"' glimmer package
3084
3276
 
3085
3277
  That overrides the default application display name.
3086
3278
 
3279
+ ### Windows Application Packaging
3280
+
3281
+ Windows offers two options for setup packaging:
3282
+ - `msi` (recommended): simpler packaging option. Requires [WiX Toolset](https://wixtoolset.org/) and [.NET Framework](https://dotnet.microsoft.com/download/dotnet-framework). Simply run `glimmer package[msi]` (or `glimmer package:native[msi]` if it's not your first time) and it will tell you what you need to install including which version of .NET Framework it needs.
3283
+ - `exe`: more advanced packaging option. Requires [Inno Setup](https://jrsoftware.org/isinfo.php). Simply run `glimmer package[exe]` (or `glimmer package:native[exe]` if it's not your first time) and it will tell you what you need to install.
3284
+
3285
+ If you just want to test out packaging into a native Windows app that is not packaged for Windows setup, just pass `image` to generate a native Windows app only.
3286
+
3087
3287
  ### Mac Application Distribution
3088
3288
 
3089
3289
  Recent macOS versions (starting with Catalina) have very stringent security requirements requiring all applications to be signed before running (unless the user goes to System Preferences -> Privacy -> General tab and clicks "Open Anyway" after failing to open application the first time they run it). So, to release a desktop application on the Mac, it is recommended to enroll in the [Apple Developer Program](https://developer.apple.com/programs/) to distribute on the [Mac App Store](https://developer.apple.com/distribute/) or otherwise request [app notarization from Apple](https://developer.apple.com/documentation/xcode/notarizing_macos_software_before_distribution) to distribute independently.
@@ -3149,6 +3349,10 @@ By the way, keep in mind that during normal operation, it does also indicate a f
3149
3349
  Exec failed with code 2 command [[/usr/bin/SetFile, -c, icnC, /var/folders/4_/g1sw__tx6mjdgyh3mky7vydc0000gp/T/fxbundler4076750801763032201/images/MathBowling/.VolumeIcon.icns] in unspecified directory
3150
3350
  ```
3151
3351
 
3352
+ ## App Updates
3353
+
3354
+ Glimmer already supports automatic (and manual) app updates via the Mac App Store for Mac apps. Simply run the `glimmer package` command with the Mac App Store keys configured as per [Mac Application Distribution](mac-application-distribution) instructions and you get automatic (and manual) app update support courtesy of the Mac App Store.
3355
+
3152
3356
  ## Resources
3153
3357
 
3154
3358
  * [Code Master Blog](http://andymaleh.blogspot.com/search/label/Glimmer)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.10.1
1
+ 0.10.2
@@ -4,6 +4,7 @@
4
4
  # UI with domain models.
5
5
  require 'logger'
6
6
  require 'set'
7
+ require 'array_include_methods'
7
8
 
8
9
  $LOAD_PATH.unshift(File.expand_path('..', __FILE__))
9
10
 
@@ -15,9 +15,7 @@ module Glimmer
15
15
  end
16
16
 
17
17
  def reset_excluded_keyword_checkers!
18
- @excluded_keyword_checkers = [
19
- lambda { |method_symbol, *args| method_symbol.to_s.match(REGEX_METHODS_EXCLUDED) }
20
- ]
18
+ @excluded_keyword_checkers = [ lambda { |method_symbol, *args| method_symbol.to_s.match(REGEX_METHODS_EXCLUDED) } ]
21
19
  end
22
20
 
23
21
  def loop_max_count
@@ -25,7 +23,7 @@ module Glimmer
25
23
  end
26
24
 
27
25
  # Returns Glimmer logger (standard Ruby logger)
28
- def logger
26
+ def logger
29
27
  reset_logger! unless defined? @@logger
30
28
  @@logger
31
29
  end
@@ -36,13 +34,9 @@ module Glimmer
36
34
 
37
35
  def reset_logger!
38
36
  self.logger = Logger.new(STDOUT).tap do |logger|
39
- logger.level = Logger::ERROR
37
+ logger.level = ENV['GLIMMER_LOGGER_LEVEL'] ? ENV['GLIMMER_LOGGER_LEVEL'].downcase : Logger::ERROR
40
38
  end
41
39
  end
42
40
  end
43
41
  end
44
42
  end
45
-
46
- if ENV['GLIMMER_LOGGER_LEVEL']
47
- Glimmer::Config.logger.level = ENV['GLIMMER_LOGGER_LEVEL'].downcase
48
- end
@@ -1,77 +1,280 @@
1
1
  require 'set'
2
+ require 'array_include_methods'
2
3
 
3
4
  require 'glimmer/data_binding/observable'
4
5
 
6
+ using ArrayIncludeMethods
7
+
5
8
  module Glimmer
6
9
  module DataBinding
7
10
  # TODO prefix utility methods with double-underscore
8
11
  module ObservableArray
9
12
  include Observable
10
13
 
11
- def add_observer(observer, element_properties=nil)
12
- return observer if has_observer?(observer) && element_properties.nil?
14
+ def add_observer(observer, *element_properties)
15
+ element_properties = element_properties.flatten.compact.uniq
16
+ return observer if has_observer?(observer) && has_observer_element_properties?(observer, element_properties)
13
17
  property_observer_list << observer
14
- [element_properties].flatten.compact.each do |property|
15
- each do |element|
16
- observer.observe(element, property)
17
- end
18
- end
18
+ observer_element_properties[observer] = element_properties_for(observer) + Set.new(element_properties)
19
+ each { |element| add_element_observer(element, observer) }
19
20
  observer
20
21
  end
22
+
23
+ def add_element_observers(element)
24
+ property_observer_list.each do |observer|
25
+ add_element_observer(element, observer)
26
+ end
27
+ end
21
28
 
22
- def remove_observer(observer, element_properties=nil)
23
- property_observer_list.delete(observer)
24
- [element_properties].flatten.compact.each do |property|
29
+ def add_element_observer(element, observer)
30
+ element_properties_for(observer).each do |property|
31
+ observer.observe(element, property)
32
+ end
33
+ end
34
+
35
+ def remove_observer(observer, *element_properties)
36
+ element_properties = element_properties.flatten.compact.uniq
37
+ if !element_properties.empty?
38
+ old_element_properties = element_properties_for(observer)
39
+ observer_element_properties[observer] = element_properties_for(observer) - Set.new(element_properties)
25
40
  each do |element|
26
- observer.unobserve(element, property)
41
+ element_properties.each do |property|
42
+ observer.unobserve(element, property)
43
+ end
27
44
  end
28
45
  end
46
+ if element_properties_for(observer).empty?
47
+ property_observer_list.delete(observer)
48
+ observer_element_properties.delete(observer)
49
+ each { |element| remove_element_observer(element, observer) }
50
+ end
29
51
  observer
30
52
  end
31
53
 
54
+ def remove_element_observers(element)
55
+ property_observer_list.each do |observer|
56
+ remove_element_observer(element, observer)
57
+ end
58
+ end
59
+
60
+ def remove_element_observer(element, observer)
61
+ element_properties_for(observer).each do |property|
62
+ observer.unobserve(element, property)
63
+ end
64
+ end
65
+
32
66
  def has_observer?(observer)
33
67
  property_observer_list.include?(observer)
34
68
  end
69
+
70
+ def has_observer_element_properties?(observer, element_properties)
71
+ element_properties_for(observer).to_a.include_all?(element_properties)
72
+ end
35
73
 
36
74
  def property_observer_list
37
75
  @property_observer_list ||= Set.new
38
76
  end
39
77
 
78
+ def observer_element_properties
79
+ @observer_element_properties ||= {}
80
+ end
81
+
82
+ def element_properties_for(observer)
83
+ observer_element_properties[observer] ||= Set.new
84
+ end
85
+
40
86
  def notify_observers
41
87
  property_observer_list.to_a.each(&:call)
42
88
  end
43
89
 
44
90
  def <<(element)
45
- super(element)
46
- notify_observers
91
+ super(element).tap do
92
+ add_element_observers(element)
93
+ notify_observers
94
+ end
47
95
  end
96
+ alias push <<
48
97
 
49
98
  def []=(index, value)
50
99
  old_value = self[index]
51
100
  unregister_dependent_observers(old_value)
52
- super(index, value)
53
- notify_observers
101
+ remove_element_observers(old_value)
102
+ add_element_observers(value)
103
+ super(index, value).tap do
104
+ notify_observers
105
+ end
106
+ end
107
+
108
+ def pop
109
+ popped_element = last
110
+ unregister_dependent_observers(popped_element)
111
+ remove_element_observers(popped_element)
112
+ super.tap do
113
+ notify_observers
114
+ end
54
115
  end
55
116
 
56
117
  def delete(element)
57
118
  unregister_dependent_observers(element)
58
- super(element)
59
- notify_observers
119
+ remove_element_observers(element)
120
+ super(element).tap do
121
+ notify_observers
122
+ end
60
123
  end
61
124
 
62
125
  def delete_at(index)
63
126
  old_value = self[index]
64
127
  unregister_dependent_observers(old_value)
65
- super(index)
66
- notify_observers
128
+ remove_element_observers(old_value)
129
+ super(index).tap do
130
+ notify_observers
131
+ end
132
+ end
133
+
134
+ def delete_if(&block)
135
+ if block_given?
136
+ old_array = Array.new(self)
137
+ super(&block).tap do |new_array|
138
+ (old_array - new_array).each do |element|
139
+ unregister_dependent_observers(element)
140
+ remove_element_observers(element)
141
+ end
142
+ notify_observers
143
+ end
144
+ else
145
+ super
146
+ end
67
147
  end
68
148
 
69
149
  def clear
70
150
  each do |old_value|
71
151
  unregister_dependent_observers(old_value)
152
+ remove_element_observers(old_value)
153
+ end
154
+ super.tap do
155
+ notify_observers
156
+ end
157
+ end
158
+
159
+ def reverse!
160
+ super.tap do
161
+ notify_observers
162
+ end
163
+ end
164
+
165
+ def collect!(&block)
166
+ if block_given?
167
+ each do |old_value|
168
+ unregister_dependent_observers(old_value)
169
+ remove_element_observers(old_value)
170
+ end
171
+ super(&block).tap do
172
+ each do |element|
173
+ add_element_observers(element)
174
+ end
175
+ notify_observers
176
+ end
177
+ else
178
+ super
179
+ end
180
+ end
181
+ alias map! collect!
182
+
183
+ def compact!
184
+ super.tap do
185
+ notify_observers
186
+ end
187
+ end
188
+
189
+ def flatten!(level=nil)
190
+ each do |old_value|
191
+ unregister_dependent_observers(old_value)
192
+ remove_element_observers(old_value)
193
+ end
194
+ (level.nil? ? super() : super(level)).tap do
195
+ each do |element|
196
+ add_element_observers(element)
197
+ end
198
+ notify_observers
199
+ end
200
+ end
201
+
202
+ def rotate!(count=1)
203
+ super(count).tap do
204
+ notify_observers
205
+ end
206
+ end
207
+
208
+ def select!(&block)
209
+ if block_given?
210
+ old_array = Array.new(self)
211
+ super(&block).tap do
212
+ (old_array - self).each do |old_value|
213
+ unregister_dependent_observers(old_value)
214
+ remove_element_observers(old_value)
215
+ end
216
+ notify_observers
217
+ end
218
+ else
219
+ super
220
+ end
221
+ end
222
+
223
+ def shuffle!(hash = nil)
224
+ (hash.nil? ? super() : super(random: hash[:random])).tap do
225
+ notify_observers
226
+ end
227
+ end
228
+
229
+ def slice!(arg1, arg2=nil)
230
+ old_array = Array.new(self)
231
+ (arg2.nil? ? super(arg1) : super(arg1, arg2)).tap do
232
+ (old_array - self).each do |old_value|
233
+ unregister_dependent_observers(old_value)
234
+ remove_element_observers(old_value)
235
+ end
236
+ notify_observers
237
+ end
238
+ end
239
+
240
+ def sort!(&block)
241
+ (block.nil? ? super() : super(&block)).tap do
242
+ notify_observers
243
+ end
244
+ end
245
+
246
+ def sort_by!(&block)
247
+ (block.nil? ? super() : super(&block)).tap do
248
+ notify_observers
249
+ end
250
+ end
251
+
252
+ def uniq!(&block)
253
+ each do |old_value|
254
+ unregister_dependent_observers(old_value)
255
+ remove_element_observers(old_value)
256
+ end
257
+ (block.nil? ? super() : super(&block)).tap do
258
+ each do |element|
259
+ add_element_observers(element)
260
+ end
261
+ notify_observers
262
+ end
263
+ end
264
+
265
+ def reject!(&block)
266
+ if block_given?
267
+ old_array = Array.new(self)
268
+ super(&block).tap do
269
+ (old_array - self).each do |old_value|
270
+ unregister_dependent_observers(old_value)
271
+ remove_element_observers(old_value)
272
+ end
273
+ notify_observers
274
+ end
275
+ else
276
+ super
72
277
  end
73
- super()
74
- notify_observers
75
278
  end
76
279
 
77
280
  def unregister_dependent_observers(old_value)
@@ -34,7 +34,7 @@ module Glimmer
34
34
  end
35
35
 
36
36
  def has_observer_for_any_property?(observer)
37
- property_observer_hash.values.map(&:to_a).sum.include?(observer)
37
+ property_observer_hash.values.map(&:to_a).reduce(:+).include?(observer)
38
38
  end
39
39
 
40
40
  def property_observer_hash
@@ -59,6 +59,7 @@ module Glimmer
59
59
  # registers observer in an observable on a property (optional)
60
60
  # observer maintains registration list to unregister later
61
61
  def register(observable, property = nil)
62
+ return if observable.nil?
62
63
  unless observable.is_a?(Observable)
63
64
  # TODO refactor code to be more smart/polymorphic/automated and honor open/closed principle
64
65
  if observable.is_a?(Array)
metadata CHANGED
@@ -1,15 +1,35 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glimmer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.1
4
+ version: 0.10.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - AndyMaleh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-27 00:00:00.000000000 Z
11
+ date: 2020-08-20 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: 1.0.2
19
+ - - "<"
20
+ - !ruby/object:Gem::Version
21
+ version: 2.0.0
22
+ name: array_include_methods
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 1.0.2
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: 2.0.0
13
33
  - !ruby/object:Gem::Dependency
14
34
  requirement: !ruby/object:Gem::Requirement
15
35
  requirements: