glimmer 0.5.8 → 0.5.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d35080737c8d31d9ede07328113372b4a79100d5ce2269f027e389923fbf93b5
4
- data.tar.gz: c3d8e4852e4f36cb3de1adcb2552d4562c6460e68f49c33598de5c2e36c1e486
3
+ metadata.gz: d1c351e3623c60e0ae9e52ce1f33b1579b5a3bb1cfc161c1eb2b6883bfe905b6
4
+ data.tar.gz: 4bb0c04faf2a1a9c68ac58f2acb386112f3706c7fae34c2e1c7dba9c99783f60
5
5
  SHA512:
6
- metadata.gz: 7a46acf87df92892d34477af6a0e69b8ec0fe3bfdbee4c45dd94f08a0eb6098724e785d2f2109c73663c278f7a1a5141d0b45ff26f5bfa6fd07f99653d1fc419
7
- data.tar.gz: af7430e47c5d5875bf1314bbb77055be6927baffaf4435ee25241cda4955bb1bf9c5dab29d7c07a5dde158c09ad39c2bb55b46dba9fcdbe7bd86f3c4c293cf79
6
+ metadata.gz: 42f75cb443468b0b4f9487b333882c1517803b66ce326c63b28780c9c98e809b27ce6cd2ce9928c61dc9f399c9ac2bd859a4c1910040869963e912893f87ddca
7
+ data.tar.gz: 5b4bed4b26bc8aed20c996bf21b24bcc26860ea06433a053faf0ad011921fb63f84f963750a5a03e64b089602a27a28b6fcee72a08f09a21a4a5d26ed29b9575
@@ -1,4 +1,4 @@
1
- # Glimmer 0.5.8 Beta (JRuby Desktop UI DSL + Data-Binding)
1
+ # Glimmer 0.5.9 Beta (JRuby Desktop UI DSL + Data-Binding)
2
2
  [![Coverage Status](https://coveralls.io/repos/github/AndyObtiva/glimmer/badge.svg?branch=master)](https://coveralls.io/github/AndyObtiva/glimmer?branch=master)
3
3
 
4
4
  Glimmer is a native-UI cross-platform desktop development library written in Ruby. Glimmer's main innovation is a JRuby DSL that enables productive and efficient authoring of desktop application user-interfaces while relying on the robust platform-native Eclipse SWT library. Glimmer additionally innovates by having built-in data-binding support to greatly facilitate synchronizing the UI with domain models. As a result, that achieves true decoupling of object oriented components, enabling developers to solve business problems without worrying about UI concerns, or alternatively drive development UI-first, and then write clean business components test-first afterwards.
@@ -70,7 +70,7 @@ NOTE: Glimmer is in beta mode. Please help make better by adopting for small or
70
70
  ## Table of Contents
71
71
 
72
72
  <!-- TOC START min:1 max:3 link:true asterisk:false update:true -->
73
- - [Glimmer 0.5.8 Beta (JRuby Desktop UI DSL + Data-Binding)](#glimmer-058-beta-jruby-desktop-ui-dsl--data-binding)
73
+ - [Glimmer 0.5.9 Beta (JRuby Desktop UI DSL + Data-Binding)](#glimmer-058-beta-jruby-desktop-ui-dsl--data-binding)
74
74
  - [Examples](#examples)
75
75
  - [Hello World](#hello-world)
76
76
  - [Tic Tac Toe](#tic-tac-toe)
@@ -163,14 +163,14 @@ Please follow these instructions to make the `glimmer` command available on your
163
163
 
164
164
  Run this command to install directly:
165
165
  ```
166
- jgem install glimmer -v 0.5.8
166
+ jgem install glimmer -v 0.5.9
167
167
  ```
168
168
 
169
169
  ### Option 2: Bundler
170
170
 
171
171
  Add the following to `Gemfile`:
172
172
  ```
173
- gem 'glimmer', '~> 0.5.8'
173
+ gem 'glimmer', '~> 0.5.9'
174
174
  ```
175
175
 
176
176
  And, then run:
@@ -367,84 +367,27 @@ shell {
367
367
  }.open
368
368
  ```
369
369
 
370
- #### Menus
371
-
372
- Glimmer DSL provides support for SWT Menu and MenuItem widgets.
373
-
374
- There are 2 main types of menus in SWT:
375
- - Menu Bar (shows up on top)
376
- - Pop Up Menu (shows up when right-clicking a widget)
377
-
378
- Underneath both types, there can be a 3rd menu type called Drop Down.
379
-
380
- Glimmer provides special support for Drop Down menus as it automatically instantiates associated Cascade menu items and wires together with proper parenting, swt styles, and calling setMenu.
370
+ #### Display
381
371
 
382
- The ampersand symbol indicates the keyboard shortcut key for the menu item (e.g. '&Help' can be triggered on Windows by hitting ALT+H)
383
-
384
- Example [Menu Bar] (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
372
+ SWT Display is a singleton in Glimmer. It is used in SWT to represent your display device, allowing you to manage UI globally
373
+ and access available monitors.
374
+ It is automatically instantiated upon first instantiation of a `shell` widget.
375
+ Alternatively, for advanced use cases, it can be created explicitly with Glimmer `display` keyword. When a `shell` is later declared, it
376
+ automatically uses the display created earlier without having to explicitly hook it.
385
377
 
386
378
  ```ruby
387
- shell {
388
- menu_bar {
389
- menu {
390
- text "&File"
391
- menu_item {
392
- text "E&xit"
393
- }
394
- menu_item(0) {
395
- text "&New"
396
- }
397
- menu(1) {
398
- text "&Options"
399
- menu_item(:radio) {
400
- text "Option 1"
401
- }
402
- menu_item(:separator)
403
- menu_item(:check) {
404
- text "Option 3"
405
- }
406
- }
407
- }
408
- menu {
409
- text "&History"
410
- menu {
411
- text "&Recent"
412
- menu_item {
413
- text "File 1"
414
- }
415
- menu_item {
416
- text "File 2"
417
- }
418
- }
419
- }
420
- }
421
- }.open
422
- ```
423
-
424
- Example [Pop Up Menu] (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
425
-
426
- ```ruby
427
- shell {
428
- label {
429
- text 'Right-Click Me'
430
- menu {
431
- menu {
432
- text '&History'
433
- menu {
434
- text "&Recent"
435
- menu_item {
436
- text "File 1"
437
- }
438
- menu_item {
439
- text "File 2"
440
- }
441
- }
442
- }
443
- }
379
+ @display = display {
380
+ cursor_location 300, 300
381
+ on_event_keydown {
382
+ # ...
444
383
  }
445
- }.open
384
+ # ...
385
+ }
386
+ @shell = shell { # uses display created above
387
+ }
446
388
  ```
447
-
389
+ The benefit of instantiating an SWT Display explicitly is to set [Properties](#widget-properties) or [Observers](#observer).
390
+ Although SWT Display is not technically a widget, it has similar APIs in SWT and similar DSL support in Glimmer.
448
391
 
449
392
  #### SWT Proxies
450
393
 
@@ -461,7 +404,6 @@ Glimmer follows Proxy Design Pattern by having Ruby proxy wrappers for all SWT o
461
404
 
462
405
  These proxy objects have an API and provide some convenience methods, some of which are mentioned below.
463
406
 
464
-
465
407
  ##### `#content { ... }`
466
408
 
467
409
  Glimmer allows re-opening any widget and adding properties or extra content after it has been constructed already by using the `#content` method.
@@ -521,6 +463,86 @@ Shell widget proxy has extra methods specific to SWT Shell:
521
463
  - `#visible?`: Returns whether a shell is visible
522
464
  - `#opened_before?`: Returns whether a shell has been opened at least once before (additionally implying the SWT Event Loop has been started already)
523
465
  - `#visible=`: Setting to true opens/shows shell. Setting to false hides the shell.
466
+ - `#pack`: Packs contained widgets using SWT's `Shell#pack` method
467
+ - `#pack_same_size`: Packs contained widgets without changing shell's size when widget sizes change
468
+
469
+ #### Menus
470
+
471
+ Glimmer DSL provides support for SWT Menu and MenuItem widgets.
472
+
473
+ There are 2 main types of menus in SWT:
474
+ - Menu Bar (shows up on top)
475
+ - Pop Up Menu (shows up when right-clicking a widget)
476
+
477
+ Underneath both types, there can be a 3rd menu type called Drop Down.
478
+
479
+ Glimmer provides special support for Drop Down menus as it automatically instantiates associated Cascade menu items and wires together with proper parenting, swt styles, and calling setMenu.
480
+
481
+ The ampersand symbol indicates the keyboard shortcut key for the menu item (e.g. '&Help' can be triggered on Windows by hitting ALT+H)
482
+
483
+ Example [Menu Bar] (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
484
+
485
+ ```ruby
486
+ shell {
487
+ menu_bar {
488
+ menu {
489
+ text "&File"
490
+ menu_item {
491
+ text "E&xit"
492
+ }
493
+ menu_item(0) {
494
+ text "&New"
495
+ }
496
+ menu(1) {
497
+ text "&Options"
498
+ menu_item(:radio) {
499
+ text "Option 1"
500
+ }
501
+ menu_item(:separator)
502
+ menu_item(:check) {
503
+ text "Option 3"
504
+ }
505
+ }
506
+ }
507
+ menu {
508
+ text "&History"
509
+ menu {
510
+ text "&Recent"
511
+ menu_item {
512
+ text "File 1"
513
+ }
514
+ menu_item {
515
+ text "File 2"
516
+ }
517
+ }
518
+ }
519
+ }
520
+ }.open
521
+ ```
522
+
523
+ Example [Pop Up Menu] (you may copy/paste in [`girb`](#girb-glimmer-irb-command)):
524
+
525
+ ```ruby
526
+ shell {
527
+ label {
528
+ text 'Right-Click Me'
529
+ menu {
530
+ menu {
531
+ text '&History'
532
+ menu {
533
+ text "&Recent"
534
+ menu_item {
535
+ text "File 1"
536
+ }
537
+ menu_item {
538
+ text "File 2"
539
+ }
540
+ }
541
+ }
542
+ }
543
+ }
544
+ }.open
545
+ ```
524
546
 
525
547
  ### Widget Styles
526
548
 
@@ -1064,7 +1086,9 @@ Glimmer supports observing widgets with two main types of events:
1064
1086
  1. `on_{swt-listener-method-name}`: where {swt-listener-method-name} is replaced with the lowercase underscored event method name on an SWT listener class (e.g. `on_verify_text` for `org.eclipse.swt.events.VerifyListener#verifyText`).
1065
1087
  2. `on_event_{swt-event-constant}`: where {swt-event-constant} is replaced with an `org.eclipse.swt.SWT` event constant (e.g. `on_event_show` for `SWT.Show` to observe when widget becomes visible)
1066
1088
 
1067
- Additionally, the `shell` widget supports a 3rd type on the Mac, application menu item observers (`on_about` and `on_preferences`), which you can read about under [Miscellaneous](#miscellaneous).
1089
+ Additionally, there are two more types of events:
1090
+ - SWT `display` supports global listeners called filters that run on any widget. They are hooked via `on_event_{swt-event-constant}`
1091
+ - the `shell` widget supports Mac application menu item observers (`on_about` and `on_preferences`), which you can read about under [Miscellaneous](#miscellaneous).
1068
1092
 
1069
1093
  Number 1 is more commonly used in SWT applications, so make it your starting point. Number 2 covers events not found in number 1, so look into it if you don't find an SWT listener you need in number 1.
1070
1094
 
@@ -1651,21 +1675,51 @@ shell {
1651
1675
 
1652
1676
  Check the [samples](samples) directory for examples on how to write Glimmer applications. To run a sample, make sure to install the `glimmer` gem first and then use the `glimmer` command to run it (alternatively, you may clone the repo, follow [CONTRIBUTING.md](CONTRIBUTING.md) instructions, and run samples locally with development glimmer command: `bin/glimmer`).
1653
1677
 
1654
- Examples:
1678
+ If you cloned the project and followed [CONTRIBUTING.md](CONTRIBUTING.md) instructions, you may run all samples at once via `samples/launch` command:
1655
1679
 
1656
1680
  ```
1681
+ samples/launch
1682
+ ```
1683
+
1684
+ ### Hello Samples
1685
+
1686
+ For "Hello, World!" type samples, check the following:
1687
+
1688
+ ```
1689
+ glimmer samples/hello_world.rb
1690
+ glimmer samples/hello_browser.rb
1657
1691
  glimmer samples/hello_tab.rb
1658
1692
  glimmer samples/hello_combo.rb
1659
1693
  glimmer samples/hello_list_single_selection.rb
1660
1694
  glimmer samples/hello_list_multi_selection.rb
1661
- glimmer samples/contactmanager/contact_manager.rb
1695
+ glimmer samples/hellocomputed/hello_computed.rb
1696
+ glimmer samples/video/hello_video.rb
1697
+ glimmer samples/video/hello_looped_video_with_black_background.rb
1698
+ glimmer samples/video/hello_video_observers.rb
1699
+ ```
1700
+
1701
+ ### Elaborate Samples
1702
+
1703
+ For more elaborate samples, check the following:
1704
+
1662
1705
  ```
1706
+ glimmer samples/login.rb # demonstrates basic data-binding
1707
+ glimmer samples/contactmanager/contact_manager.rb # demonstrates table data-binding
1708
+ glimmer samples/tictactoe/tic_tac_toe.rb # demonstrates a full MVC application
1709
+ glimmer samples/gladiator.rb # demonstrates a text editor with tree/list data-binding
1710
+ ```
1711
+
1712
+ ![Gladiator](images/glimmer-gladiator.png)
1663
1713
 
1664
- The last example (`contact_manager.rb`) is a good sample about how to build tables with Glimmer including data-binding, filtering, and sorting. It even comes with specs in `spec/samples/contactmanager/contact_manager_presenter_spec.rb` to demonstrate how Glimmer facilitates TDD (test-driven development) with the Model View Presenter pattern (a variation on MVC) by separating testable presentation logic from the view layer with data-binding.
1714
+ Gladiator (short for Glimmer Editor) is an on-going sample project with continuous development.
1715
+ It is also used as the main text editor for coding Glimmer.
1716
+ As such, it has been made available in [Glimmer's gem](https://rubygems.org/gems/glimmer) via the `gladiator` command should others find useful too.
1717
+ If you cloned this project and followed [CONTRIBUTING.md](CONTRIBUTING.md) instructions, you may invoke via `bin/gladiator` instead.
1665
1718
 
1666
- For a more elaborate project built with Glimmer, check out this educational game:
1719
+ ## In Production
1667
1720
 
1668
- [Math Bowling](https://github.com/AndyObtiva/MathBowling)
1721
+ The following production apps have been built with Glimmer:
1722
+ - [Math Bowling](https://github.com/AndyObtiva/MathBowling): an educational math game for elementary level kids
1669
1723
 
1670
1724
  ## SWT Reference
1671
1725
 
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative '../lib/glimmer/launcher'
4
+
5
+ gladiator = File.expand_path('../../samples/gladiator.rb', __FILE__)
6
+ Glimmer::Launcher.new([gladiator, '-J-Xrs'] + ARGV).launch
@@ -84,3 +84,4 @@ require 'glimmer/swt/packages'
84
84
  require 'glimmer/dsl'
85
85
  require 'glimmer/error'
86
86
  require 'glimmer/invalid_keyword_error'
87
+ require 'glimmer/ui/video'
@@ -44,7 +44,7 @@ module Glimmer
44
44
  end
45
45
 
46
46
  def evaluate_property
47
- selection_array = @widget_proxy.swt_widget.send('selection').to_a
47
+ selection_array = @widget_proxy.swt_widget.send('selection').to_a #TODO refactor send('selection') into proper method invocation
48
48
  PROPERTY_EVALUATORS[@property_type].call(selection_array)
49
49
  end
50
50
  end
@@ -1,33 +1,33 @@
1
- require 'glimmer'
2
- require_relative 'observable'
3
- require_relative 'observer'
4
-
5
- module Glimmer
6
- module DataBinding
7
- class WidgetBinding
8
- include Glimmer
9
- include Observable
10
- include Observer
11
-
12
- attr_reader :widget, :property
13
- def initialize(model, property, translator = nil)
14
- @widget = model
15
- @property = property
16
- @translator = translator || proc {|value| value}
17
-
18
- if @widget.respond_to?(:dispose)
19
- @widget.on_widget_disposed do |dispose_event|
20
- unregister_all_observables
21
- end
22
- end
23
- end
24
- def call(value)
25
- converted_value = translated_value = @translator.call(value)
26
- @widget.set_attribute(@property, converted_value) unless evaluate_property == converted_value
27
- end
28
- def evaluate_property
29
- @widget.get_attribute(@property)
30
- end
31
- end
32
- end
33
- end
1
+ require 'glimmer'
2
+ require_relative 'observable'
3
+ require_relative 'observer'
4
+
5
+ module Glimmer
6
+ module DataBinding
7
+ class WidgetBinding
8
+ include Glimmer
9
+ include Observable
10
+ include Observer
11
+
12
+ attr_reader :widget, :property
13
+ def initialize(model, property, translator = nil)
14
+ @widget = model
15
+ @property = property
16
+ @translator = translator || proc {|value| value}
17
+
18
+ if @widget.respond_to?(:dispose)
19
+ @widget.on_widget_disposed do |dispose_event|
20
+ unregister_all_observables
21
+ end
22
+ end
23
+ end
24
+ def call(value)
25
+ converted_value = translated_value = @translator.call(value)
26
+ @widget.set_attribute(@property, converted_value) unless evaluate_property == converted_value
27
+ end
28
+ def evaluate_property
29
+ @widget.get_attribute(@property)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -3,7 +3,6 @@ require 'glimmer/dsl/expression'
3
3
  require 'glimmer/dsl/parent_expression'
4
4
  require 'glimmer/ui/custom_widget'
5
5
  require 'glimmer/ui/custom_shell'
6
- require 'glimmer/ui/video' # this is interpreted here since it's a custom widget
7
6
 
8
7
  module Glimmer
9
8
  module DSL
@@ -1,9 +1,11 @@
1
1
  require 'glimmer/dsl/static_expression'
2
+ require 'glimmer/dsl/parent_expression'
2
3
  require 'glimmer/swt/display_proxy'
3
4
 
4
5
  module Glimmer
5
6
  module DSL
6
7
  class DisplayExpression < StaticExpression
8
+ include ParentExpression
7
9
  def interpret(parent, keyword, *args, &block)
8
10
  SWT::DisplayProxy.instance(*args)
9
11
  end
@@ -8,16 +8,15 @@ module Glimmer
8
8
  include_package 'org.eclipse.swt.widgets'
9
9
 
10
10
  def can_interpret?(parent, keyword, *args, &block)
11
- keyword == "items" and
12
- block.nil? and
13
- widget?(parent) and
14
- parent.swt_widget.is_a?(Tree) and
15
- args.size == 2 and
16
- args[0].is_a?(DataBinding::ModelBinding) and
17
- !args[0].evaluate_property.is_a?(Array) and
18
- args[1].is_a?(Array) and
19
- !args[1].empty? and
20
- args[1].first.is_a?(Hash)
11
+ initial_condition = ((keyword == "items") and block.nil? and widget?(parent) and parent.swt_widget.is_a?(Tree))
12
+ return false unless initial_condition
13
+ raise Glimmer::Error, 'Tree items args must be 2' unless args.size == 2
14
+ raise Glimmer::Error, 'Tree items first arg must be a bind expression' unless args[0].is_a?(DataBinding::ModelBinding)
15
+ raise Glimmer::Error, 'Tree items data-binding initial value must not be an array yet a single item representing tree root' unless !args[0].evaluate_property.is_a?(Array)
16
+ raise Glimmer::Error, 'Tree items second arg must be an array' unless args[1].is_a?(Array)
17
+ raise Glimmer::Error, 'Tree items second arg must not be empty' unless !args[1].empty?
18
+ raise Glimmer::Error, 'Tree items second arg array elements must be of type hash' unless args[1].first.is_a?(Hash)
19
+ true
21
20
  end
22
21
 
23
22
  def interpret(parent, keyword, *args, &block)
@@ -1,4 +1,5 @@
1
1
  require 'glimmer/dsl/expression'
2
+ require 'glimmer/swt/display_proxy'
2
3
 
3
4
  module Glimmer
4
5
  module DSL
@@ -8,9 +9,9 @@ module Glimmer
8
9
  def can_interpret?(parent, keyword, *args, &block)
9
10
  Glimmer.logger&.debug "keyword starts with on_: #{keyword.start_with?('on_')}"
10
11
  return false unless keyword.start_with?('on_')
11
- widget_parentage = widget?(parent)
12
- Glimmer.logger&.debug "parent is a widget: #{widget_parentage}"
13
- return false unless widget_parentage
12
+ widget_or_display_parentage = widget?(parent) || parent.is_a?(SWT::DisplayProxy)
13
+ Glimmer.logger&.debug "parent is a widget or display: #{widget_or_display_parentage}"
14
+ return false unless widget_or_display_parentage
14
15
  Glimmer.logger&.debug "block exists?: #{!block.nil?}"
15
16
  raise Glimmer::Error, "Listener is missing block for keyword: #{keyword}" unless block_given?
16
17
  Glimmer.logger&.debug "args are empty?: #{args.empty?}"