glimmer-dsl-swt 4.24.2.2 → 4.24.3.1

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: bec603d1fc189735e3334702098253e83b93e389785bc94305b174aa1d444219
4
- data.tar.gz: c817d85d69f9118cd475fb331fc7fbc2ff7c318008d02ec9ee7667f8cc18a633
3
+ metadata.gz: 44c7406f9588caef592b17f889b509db88771e545300a916f44ea1a928a89937
4
+ data.tar.gz: 2933dfdf3e5e1479849793cec5bbfdf3558768bb34b4c828847339c95559242a
5
5
  SHA512:
6
- metadata.gz: ab1d611fad1cabafbd7cd2071aa0cb0603bd90e29a5796573e77b762ad4969b9b5add2da4306b89afb7d9b86393534bf514a2e54f1409d68319224d563592581
7
- data.tar.gz: 66d6572c4d931df7c52fa5623bd4d0523eee7d906932a537e0936a27849e137269005db210609fbcd3c2d0e7726a4ff8d2b35dc315da1bfd019fee231366077a
6
+ metadata.gz: 6d13f0eaa866f47c449caa5ce3e3ae652025940769b8f419c0b4b66df0e1e67b3a4e3494ab539cb81d21de79ac44d81e3982f59083c9bd0453201e1231073ee0
7
+ data.tar.gz: 53fe039d009a4d3476bbc2a5d96f11ca3ab4fdb442b790bafd0b9bc920943bb4cc6bc475522f1f040d355da8029cd693a76179d4e247fa9e4bd59fcd2637fe80
data/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # Change Log
2
2
 
3
+ ## 4.24.3.1
4
+
5
+ - `code_text` default behavior support of zoom in (CMD+= on Mac, CTRL+= on Win/Linux), zoom out (CMD+- on Mac, CTRL+- on Win/Linux), and restore original font height (CMD+0 on Mac, CTRL+0 on Win/Linux).
6
+
7
+ ## 4.24.3.0
8
+
9
+ - Support `table` `items` data-binding of table row cell `background`, `foreground`, `font`, `image` to model attributes by convention based on specified `column_properties` (e.g. for `column_properties` model `name` attribute, automatically assume model `name_background` provides `[r, g, b]` array of color)
10
+ - Update Hello, Table! sample to demonstrate data-binding `table` `items` `background`, `foreground`, `font`, `image` to model attributes by convention, and to add `booked` attribute on `BaseballGame` to disable Book button when already booked
11
+ - Update Hello, Table! sample to add `booked` attribute to `BaseballGame` to disable Book button when already booked
12
+ - Update Hello, Table! sample to enable booking by hitting the ENTER keyboard button
13
+ - Optimize `table` data-binding performance by not recreating table-items when the table grows or stays at the same size, and by not updating a table item (row) when no changes have occurred (detect through diffing)
14
+ - Update `font` keyword and `FontProxy` to support lightweight creation/caching/sharing following Flyweight Design Pattern
15
+
16
+ ## 4.24.2.3
17
+
18
+ - Default `code_text` font name in Mac is changed back to `'Courier'`
19
+
3
20
  ## 4.24.2.2
4
21
 
5
22
  - Upgrade to jruby-9.3.7.0
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.24.2.2
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.24.3.1
2
2
  ## JRuby Desktop Development GUI Framework
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)
@@ -12,7 +12,7 @@
12
12
 
13
13
  ![Glimmer DSL for SWT Demo of Hello, World!](/images/glimmer-dsl-swt-demo-hello-world.gif)
14
14
 
15
- [Glimmer](https://github.com/AndyObtiva/glimmer) DSL for [SWT](https://www.eclipse.org/swt/) is a native GUI (Graphical User Interface) cross-platform desktop development library written in [JRuby](https://www.jruby.org/), an OS-threaded faster [JVM](https://www.java.com/en/download/help/whatis_java.html) version of [Ruby](https://www.ruby-lang.org/en/). [Glimmer](https://github.com/AndyObtiva/glimmer)'s main innovation is a declarative [Ruby DSL](docs/reference/GLIMMER_GUI_DSL_SYNTAX.md#glimmer-dsl-syntax) (Domain Specific Language) that enables productive and efficient authoring of desktop application user-interfaces by 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](docs/reference/GLIMMER_GUI_DSL_SYNTAX.md#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, or alternatively drive development GUI-first, and then write clean business models afterwards. Not only does Glimmer provide a large set of GUI [widgets](docs/reference/GLIMMER_GUI_DSL_SYNTAX.md#widgets), but it also supports drawing Canvas Graphics like [Shapes](docs/reference/GLIMMER_GUI_DSL_SYNTAX.md#canvas-shape-dsl) and [Animations](docs/reference/GLIMMER_GUI_DSL_SYNTAX.md#canvas-animation-dsl). To get started quickly, [Glimmer](https://rubygems.org/gems/glimmer) offers [scaffolding](docs/reference/GLIMMER_COMMAND.md#scaffolding) options for [Apps](#in-production), [Gems](docs/reference/GLIMMER_COMMAND.md#custom-shell-gem), and [Custom Widgets](docs/reference/GLIMMER_GUI_DSL_SYNTAX.md#custom-widgets). [Glimmer](https://rubygems.org/gems/glimmer) also includes native-executable [packaging](docs/reference/GLIMMER_PACKAGING_AND_DISTRIBUTION.md) 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), MSI/EXE files on [Windows](https://www.microsoft.com/en-ca/windows), and DEB/RPM files on [Linux](https://www.linux.org/). [Glimmer](https://github.com/AndyObtiva/glimmer) was the [first Ruby gem](https://rubygems.org/gems/glimmer) to bring [SWT](https://www.eclipse.org/swt/) (Standard Widget Toolkit) to [Ruby](https://www.ruby-lang.org/en/), thanks to creator [Andy Maleh](https://andymaleh.blogspot.com/), EclipseCon/EclipseWorld/RubyConf speaker.
15
+ [Glimmer](https://github.com/AndyObtiva/glimmer) DSL for [SWT](https://www.eclipse.org/swt/) (formerly [Glimmer](https://github.com/AndyObtiva/glimmer)) is a native GUI (Graphical User Interface) cross-platform desktop development library written in [JRuby](https://www.jruby.org/), an OS-threaded faster [JVM](https://www.java.com/en/download/help/whatis_java.html) version of [Ruby](https://www.ruby-lang.org/en/). [Glimmer](https://github.com/AndyObtiva/glimmer)'s main innovation is a declarative [Ruby DSL](docs/reference/GLIMMER_GUI_DSL_SYNTAX.md#glimmer-dsl-syntax) (Domain Specific Language) that enables productive and efficient authoring of desktop application user-interfaces by 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](docs/reference/GLIMMER_GUI_DSL_SYNTAX.md#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, or alternatively drive development GUI-first, and then write clean business models afterwards. Not only does Glimmer provide a large set of GUI [widgets](docs/reference/GLIMMER_GUI_DSL_SYNTAX.md#widgets), but it also supports drawing Canvas Graphics like [Shapes](docs/reference/GLIMMER_GUI_DSL_SYNTAX.md#canvas-shape-dsl) and [Animations](docs/reference/GLIMMER_GUI_DSL_SYNTAX.md#canvas-animation-dsl). To get started quickly, [Glimmer](https://rubygems.org/gems/glimmer) offers [scaffolding](docs/reference/GLIMMER_COMMAND.md#scaffolding) options for [Apps](#in-production), [Gems](docs/reference/GLIMMER_COMMAND.md#custom-shell-gem), and [Custom Widgets](docs/reference/GLIMMER_GUI_DSL_SYNTAX.md#custom-widgets). [Glimmer](https://rubygems.org/gems/glimmer) also includes native-executable [packaging](docs/reference/GLIMMER_PACKAGING_AND_DISTRIBUTION.md) 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), MSI/EXE files on [Windows](https://www.microsoft.com/en-ca/windows), and DEB/RPM files on [Linux](https://www.linux.org/). [Glimmer](https://github.com/AndyObtiva/glimmer) was the [first Ruby gem](https://rubygems.org/gems/glimmer) to bring [SWT](https://www.eclipse.org/swt/) (Standard Widget Toolkit) to [Ruby](https://www.ruby-lang.org/en/), thanks to creator [Andy Maleh](https://andymaleh.blogspot.com/), EclipseCon/EclipseWorld/RubyConf speaker.
16
16
 
17
17
  [<img src="https://covers.oreillystatic.com/images/9780596519650/lrg.jpg" width=105 /><br />
18
18
  Featured in JRuby Cookbook](http://shop.oreilly.com/product/9780596519650.do) and [Chalmers/Gothenburg University Software Engineering Master's Lecture Material](http://www.cse.chalmers.se/~bergert/slides/guest_lecture_DSLs.pdf)
@@ -21,7 +21,7 @@ Featured in JRuby Cookbook](http://shop.oreilly.com/product/9780596519650.do) an
21
21
 
22
22
  ![Eclipse SWT RCP NASA Mars Rover](/images/glimmer-eclipse-swt-rcp-nasa-mars-rover.png)
23
23
 
24
- [Glimmer DSL for SWT](https://rubygems.org/gems/glimmer-dsl-swt) 4.24.2.2 includes [SWT 4.24](https://download.eclipse.org/eclipse/downloads/drops4/R-4.24-202206070700/), which was released on June 7, 2022. 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.
24
+ [Glimmer DSL for SWT](https://rubygems.org/gems/glimmer-dsl-swt) 4.24.3.1 includes [SWT 4.24](https://download.eclipse.org/eclipse/downloads/drops4/R-4.24-202206070700/), which was released on June 7, 2022. 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.
25
25
 
26
26
  **Starting in version 4.20.0.0, [Glimmer DSL for SWT](https://rubygems.org/gems/glimmer-dsl-swt) comes with the new [***Shine***](/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md#shine) syntax** for highly intuitive and visually expressive View/Model Attribute Mapping, relying on `<=>` for bidirectional (two-way) data-binding and `<=` for unidirectional (one-way) data-binding, providing an alternative to the `bind` keyword. That was [originally conceived back in 2007](https://andymaleh.blogspot.com/2007/12/data-shining-in-glimmer.html).
27
27
 
@@ -338,7 +338,7 @@ jgem install glimmer-dsl-swt
338
338
 
339
339
  Or this command if you want a specific version:
340
340
  ```
341
- jgem install glimmer-dsl-swt -v 4.24.2.2
341
+ jgem install glimmer-dsl-swt -v 4.24.3.1
342
342
  ```
343
343
 
344
344
  `jgem` is JRuby's version of `gem` command.
@@ -366,7 +366,7 @@ Note: if you're using activerecord or activesupport, keep in mind that Glimmer u
366
366
 
367
367
  Add the following to `Gemfile`:
368
368
  ```
369
- gem 'glimmer-dsl-swt', '~> 4.24.2.2'
369
+ gem 'glimmer-dsl-swt', '~> 4.24.3.1'
370
370
  ```
371
371
 
372
372
  And, then run:
@@ -389,7 +389,7 @@ glimmer
389
389
  ```
390
390
 
391
391
  ```
392
- Glimmer (JRuby Desktop Development GUI Framework) - JRuby Gem: glimmer-dsl-swt v4.24.2.2
392
+ Glimmer (JRuby Desktop Development GUI Framework) - JRuby Gem: glimmer-dsl-swt v4.24.3.1
393
393
 
394
394
  Usage: glimmer [--bundler] [--pd] [--quiet] [--debug] [--log-level=VALUE] [[ENV_VAR=VALUE]...] [[-jruby-option]...] (application.rb or task[task_args]) [[application2.rb]...]
395
395
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 4.24.2.2
1
+ 4.24.3.1
@@ -3998,9 +3998,9 @@ The SWT Tree widget renders a multi-column data table, such as a contact listing
3998
3998
 
3999
3999
  To data-bind a Table, you need the main model, the collection property, and the text display attribute for each table column.
4000
4000
 
4001
- This involves using the `bind` keyword mentioned above in addition to a special `column_properties` keyword that takes the table column text attribute methods.
4001
+ This involves using the `<=>` operator in addition to a special `column_properties` kwarg that takes an array that maps table columns to model attributes.
4002
4002
 
4003
- It assumes you have defined the table columns via `table_column` widget.
4003
+ It assumes you have already defined table columns via the `table_column` `table`-nested widget.
4004
4004
 
4005
4005
  Example:
4006
4006
 
@@ -4019,8 +4019,8 @@ shell {
4019
4019
  text "Adult"
4020
4020
  width 120
4021
4021
  }
4022
- items bind(group, :people), column_properties(:name, :age, :adult)
4023
- selection bind(group, :selected_person)
4022
+ items <=> [group, :people, column_properties: [:name, :age, :adult]]
4023
+ selection <=> [group, :selected_person]
4024
4024
  on_mouse_up do |event|
4025
4025
  @table.edit_table_item(event.table_item, event.column_index)
4026
4026
  end
@@ -4029,11 +4029,11 @@ shell {
4029
4029
  ```
4030
4030
 
4031
4031
  The code above includes two data-bindings:
4032
- - Table `items`, which first bind to the model collection property (group.people), and then maps each column property (name, age, adult) for displaying each table item column.
4033
- - Table `selection`, which binds the single table item selected by the user to the attribute denoted by the `bind` keyword (or binds multiple table items selected for a table with `:multi` SWT style)
4032
+ - Table `items`, which first data-binds to the model collection property (group.people), and then maps each column property (name, age, adult) for displaying each table item column.
4033
+ - Table `selection`, which data-binds the single table item (row) selected by the user to the model attribute denoted by `<=>` (or data-binds multiple table items to a model attribute array value for a table with `:multi` SWT style)
4034
4034
  - The `on_mouse_up` event handler invokes `@table.edit_table_item(event.table_item, event.column_index)` to start edit mode on the clicked table item cell, and then saves or cancel depending on whether the user hits ENTER or ESC once done editing (or focus-out after either making a change or not making any changes.)
4035
4035
 
4036
- Additionally, Table `items` data-binding automatically stores each node model unto the SWT TableItem object via `setData` method. This enables things like searchability.
4036
+ Additionally, Table `items` data-binding automatically stores each row model in the [SWT `TableItem`](https://help.eclipse.org/latest/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/widgets/TableItem.html) object representing it, by using the `set_data` method. This enables things like searchability.
4037
4037
 
4038
4038
  The table widget in Glimmer is represented by a subclass of `WidgetProxy` called `TableProxy`.
4039
4039
  TableProxy includes a `search` method that takes a block to look for a table item.
@@ -4044,13 +4044,31 @@ Example:
4044
4044
  found_array = @table.search { |table_item| table_item.getData == company.owner }
4045
4045
  ```
4046
4046
 
4047
- This finds a person. The array is a Java array. This enables easy passing of it to SWT `Table#setSelection` method, which expects a Java array of `TableItem` objects.
4047
+ This finds a person. The array is a Java array. This enables easy passing of it to SWT `Table#setSelection` method, which expects a Java array of [`TableItem`](https://help.eclipse.org/latest/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/widgets/TableItem.html) objects.
4048
4048
 
4049
4049
  To edit a table, you must invoke `TableProxy#edit_selected_table_item(column_index, before_write: nil, after_write: nil, after_cancel: nil)` or `TableProxy#edit_table_item(table_item, column_index, before_write: nil, after_write: nil, after_cancel: nil)`.
4050
4050
  This automatically leverages the SWT TableEditor custom class behind the scenes, displaying a text widget to the user to change the selected or
4051
4051
  passed table item text into something else.
4052
4052
  It automatically persists the change to `items` data-bound model on ENTER/FOCUS-OUT or cancels on ESC/NO-CHANGE.
4053
4053
 
4054
+ ##### Table Item Properties
4055
+
4056
+ When data-binding a `table`'s `items`, extra [`TableItem` properties](https://help.eclipse.org/latest/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/widgets/TableItem.html) are data-bound automatically by convention for `background` color, `foreground` color, `font`, and `image` if corresponding properties (attributes) are available on the model.
4057
+
4058
+ That means that if `column_properties` were `[:name, :age, :adult]`, then the following [`TableItem` properties](https://help.eclipse.org/latest/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/widgets/TableItem.html) are also data-bound by convention:
4059
+ - `background` to `:name_background, :age_background, :adult_background` model attributes
4060
+ - `foreground` to `:name_foreground, :age_foreground, :adult_foreground` model attributes
4061
+ - `font` to `:name_font, :age_font, :adult_font` model attributes
4062
+ - `image` to `:name_image, :age_image, :adult_image` model attributes
4063
+
4064
+ Here are the expected values for each [`TableItem` property](https://help.eclipse.org/latest/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/widgets/TableItem.html):
4065
+ - `background`: Standard color symbol/string (e.g. `:red`), rgb array (e.g. `[24, 21, 239]`), or rgba array (e.g. `[128, 0, 128, 50]`)
4066
+ - `foreground`: Standard color symbol/string (e.g. `:red`), rgb array (e.g. `[24, 21, 239]`), or rgba array (e.g. `[128, 0, 128, 50]`)
4067
+ - `font`: font data hash having `:name`, `:height`, and/or `:style` keys (e.g. `{name: 'Courier New', height: 25, style: [:bold, :italic]}`)
4068
+ - `image`: image URL with or without image options (e.g. `'/usr/image1.png'` or `['/usr/image1.png', width: 20, height: 20]`)
4069
+
4070
+ ![Hello Table game booked rows](/images/glimmer-hello-table-game-booked-rows.png)
4071
+
4054
4072
  ##### Table Selection
4055
4073
 
4056
4074
  Table Selection data-binding is simply done via the `selection` property.
@@ -4807,32 +4825,93 @@ You may see another example at the [Hello, Radio Group!](/docs/reference/GLIMMER
4807
4825
 
4808
4826
  ##### Code Text Custom Widget
4809
4827
 
4810
- `code_text` is a Glimmer built-in custom widget that displays syntax highlighted Ruby code in a customized SWT [StyledText](https://help.eclipse.org/2020-09/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/custom/StyledText.html) widget.
4828
+ `code_text` is a Glimmer built-in custom widget that displays syntax highlighted code (e.g. Ruby/JavaScript/HTML code) for 204 languages (see [options](#code-text-options) for the full list) by automating customizations for the SWT [StyledText](https://help.eclipse.org/2020-09/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/custom/StyledText.html) widget, including ability to zoom font in and out, or restore original font height (more details below).
4829
+
4830
+ To utilize, simply use `code_text` in place of the multi-line `text` and `styled_text` widgets. If you set the `code_text` `text` property value to multi-line code content (e.g. Ruby/JavaScript/HTML code), it automatically styles it with syntax highlighting.
4811
4831
 
4812
- It attempts to use a monospace font if available, seeking fonts in the following order:
4813
- 1. Consolas
4814
- 2. Courier
4815
- 3. Any font that contains the word "Mono"
4816
- 4. Default system font (if no other font is found)
4832
+ `code_text` attempts to use a monospace font if available, seeking font names in the following order (specified in `Glimmer::SWT::Custom::CodeText::FONT_NAMES_PREFERRED`):
4833
+ 1. `'Consolas'`
4834
+ 2. `'Courier'`
4835
+ 3. `'Monospace'`
4836
+ 4. `'Liberation Mono'`
4837
+ 5. First available font that contains the word `mono` (case-insensitive)
4838
+ 6. Default system font (if no other font in the list is found)
4817
4839
 
4818
4840
  It is used in the [Glimmer Meta-Sample (The Sample of Samples)](#samples):
4819
4841
 
4820
4842
  ![Glimmer Meta-Sample](/images/glimmer-meta-sample.png)
4821
4843
 
4822
- Glimmer Meta-Sample Code Example:
4844
+ Dark Mode:
4845
+
4846
+ ![Glimmer Meta-Sample](/images/glimmer-meta-sample-dark-mode.png)
4847
+
4848
+ Code Text Simple Example (default language is Ruby):
4823
4849
 
4824
4850
  ```ruby
4825
- # ...
4826
- @code_text = code_text {
4851
+ code_text {
4827
4852
  text bind(SampleDirectory, 'selected_sample.code', read_only: true)
4828
4853
  editable bind(SampleDirectory, 'selected_sample.editable')
4829
4854
  }
4830
- # ...
4831
4855
  ```
4832
4856
 
4833
- To use, simply use `code_text` in place of the `text` or `styled_text` widget. If you set its `text` value to Ruby code, it automatically styles it with syntax highlighting.
4857
+ Code Text Specified Language Example:
4858
+
4859
+ ```ruby
4860
+ code_text(language: 'html') {
4861
+ text bind(SampleDirectory, 'selected_sample.code', read_only: true)
4862
+ editable bind(SampleDirectory, 'selected_sample.editable')
4863
+ }
4864
+ ```
4865
+
4866
+ Code Text Lines and Margins Example:
4867
+
4868
+ ```ruby
4869
+ code_text(lines: true) {
4870
+ text <=> [SampleDirectory, 'selected_sample.code']
4871
+ editable <= [SampleDirectory, 'selected_sample.editable']
4872
+ left_margin 7
4873
+ right_margin 7
4874
+ }
4875
+ ```
4876
+
4877
+ Code Text Customized Lines Width and Background Example:
4878
+
4879
+ ```ruby
4880
+ code_text(lines: {width: 3}) {
4881
+ line_numbers {
4882
+ background Display.system_dark_theme? ? :black : :white
4883
+ }
4884
+ text <=> [SampleDirectory, 'selected_sample.code']
4885
+ editable <= [SampleDirectory, 'selected_sample.editable']
4886
+ left_margin 7
4887
+ right_margin 7
4888
+ }
4889
+ ```
4890
+
4891
+ Code Text Customized Root Composite Margins/Spacing Background Example:
4892
+
4893
+ ```ruby
4894
+ code_text(lines: true) {
4895
+ root {
4896
+ grid_layout(2, false) {
4897
+ horizontal_spacing 0
4898
+ margin_left 0
4899
+ margin_right 0
4900
+ margin_top 0
4901
+ margin_bottom 0
4902
+ }
4903
+ }
4904
+ line_numbers {
4905
+ background Display.system_dark_theme? ? :black : :white
4906
+ }
4907
+ text <=> [SampleDirectory, 'selected_sample.code']
4908
+ editable <= [SampleDirectory, 'selected_sample.editable']
4909
+ left_margin 7
4910
+ right_margin 7
4911
+ }
4912
+ ```
4834
4913
 
4835
- ###### Options
4914
+ ###### Code Text Options
4836
4915
 
4837
4916
  **lines**
4838
4917
  (default: `false`)
@@ -5072,6 +5151,9 @@ This adds some default keyboard shortcuts:
5072
5151
  - CMD+A (CTRL+A on Windows/Linux) to select all
5073
5152
  - CTRL+A on Mac to jump to beginning of line
5074
5153
  - CTRL+E on Mac to jump to end of line
5154
+ - CMD+= (CTRL+= on Windows/Linux) to zoom in (bump font height up by 1)
5155
+ - CMD+- (CTRL+- on Windows/Linux) to zoom out (bump font height down by 1)
5156
+ - CMD+0 (CTRL+0 on Windows/Linux) to restore to original font height
5075
5157
  - Attempts to add proper indentation upon adding a new line when hitting ENTER (currently supporting Ruby only)
5076
5158
 
5077
5159
  If you prefer it to be vanilla with no default key event listeners, then pass the `default_behavior: false` option.
@@ -730,7 +730,7 @@ Hello, Spinner!
730
730
 
731
731
  #### Hello, Table!
732
732
 
733
- This sample demonstrates the use of [table](#table) widget in Glimmer, including data-binding, multi-type editing, sorting, and filtering.
733
+ This sample demonstrates the use of [table](/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md#table) widget in Glimmer, including data-binding, multi-type editing, sorting, and filtering.
734
734
 
735
735
  Code:
736
736
 
@@ -768,13 +768,17 @@ Hello, Table! Playoff Type Changed
768
768
 
769
769
  ![Hello Table](/images/glimmer-hello-table-playoff-type-changed.png)
770
770
 
771
+ Hello, Table! Context Menu
772
+
773
+ ![Hello Table](/images/glimmer-hello-table-context-menu.png)
774
+
771
775
  Hello, Table! Game Booked
772
776
 
773
777
  ![Hello Table](/images/glimmer-hello-table-game-booked.png)
774
778
 
775
- Hello, Table! Context Menu
779
+ Hello, Table! Game Booked Rows
776
780
 
777
- ![Hello Table](/images/glimmer-hello-table-context-menu.png)
781
+ ![Hello Table game booked rows](/images/glimmer-hello-table-game-booked-rows.png)
778
782
 
779
783
  #### Hello, Link!
780
784
 
@@ -810,23 +814,35 @@ Hello, Dialog! Open Dialog
810
814
 
811
815
  #### Hello, Code Text!
812
816
 
813
- This sample demonstrates the Glimmer Built-In [Code Text Custom Widget](#code-text-custom-widget).
817
+ This sample demonstrates the Glimmer Built-In [Code Text Custom Widget](/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md#code-text-custom-widget).
814
818
 
815
819
  Code:
816
820
 
817
821
  [samples/hello/hello_code_text.rb](/samples/hello/hello_code_text.rb)
818
822
 
819
- Hello, Code Text! Ruby Language / Glimmer Theme / Show Line Numbers (default width of 4)
823
+ Hello, Code Text! HTML Language / GitHub Theme / No Line Numbers
820
824
 
821
- ![Hello Code Text Ruby](/images/glimmer-hello-code-text-ruby.png)
825
+ ![Hello Code Text HTML](/images/glimmer-hello-code-text-html.png)
822
826
 
823
827
  Hello, Code Text! JavaScript Language / Pastie Theme / Show Line Numbers (custom width of 2)
824
828
 
825
829
  ![Hello Code Text JavaScript](/images/glimmer-hello-code-text-javascript.png)
826
830
 
827
- Hello, Code Text! HTML Language / GitHub Theme / No Line Numbers
831
+ Hello, Code Text! Ruby Language / Glimmer Theme / Show Line Numbers (default width of 4)
828
832
 
829
- ![Hello Code Text HTML](/images/glimmer-hello-code-text-html.png)
833
+ ![Hello Code Text Ruby](/images/glimmer-hello-code-text-ruby.png)
834
+
835
+ Hello, Code Text! Zoom In (via keyboard shortcut CMD+= on Mac, CTRL+= on Win/Linux)
836
+
837
+ ![Hello Code Text Zoom In](/images/glimmer-hello-code-text-zoom-in.png)
838
+
839
+ Hello, Code Text! Zoom Out (via keyboard shortcut CMD+- on Mac, CTRL+- on Win/Linux)
840
+
841
+ ![Hello Code Text Zoom Out](/images/glimmer-hello-code-text-zoom-out.png)
842
+
843
+ Hello, Code Text! Restore Original Font Height (via keyboard shortcut CMD+0 on Mac, CTRL+0 on Win/Linux)
844
+
845
+ ![Hello Code Text Restore Original Font Height](/images/glimmer-hello-code-text-ruby.png)
830
846
 
831
847
  #### Hello, Canvas!
832
848
 
Binary file
@@ -19,6 +19,8 @@
19
19
  # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
20
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
21
 
22
+ require 'set'
23
+
22
24
  require 'glimmer/data_binding/observable_array'
23
25
  require 'glimmer/data_binding/observable_model'
24
26
  require 'glimmer/data_binding/observable'
@@ -33,6 +35,8 @@ module Glimmer
33
35
  include DataBinding::Observer
34
36
  include_package 'org.eclipse.swt'
35
37
  include_package 'org.eclipse.swt.widgets'
38
+
39
+ TABLE_ITEM_PROPERTIES = %w[background foreground font image]
36
40
 
37
41
  def initialize(parent, model_binding, column_properties = nil)
38
42
  @table = parent
@@ -56,40 +60,161 @@ module Glimmer
56
60
  end
57
61
  end
58
62
 
59
- def call(new_model_collection=nil, internal_sort: false)
63
+ def call(*args)
64
+ options = args.last.is_a?(Hash) ? args.pop : {}
65
+ internal_sort = options[:internal_sort] || false
66
+ new_model_collection = args.first
60
67
  Glimmer::SWT::DisplayProxy.instance.auto_exec(override_sync_exec: @model_binding.binding_options[:sync_exec], override_async_exec: @model_binding.binding_options[:async_exec]) do
61
68
  new_model_collection = model_binding_evaluated_property = @model_binding.evaluate_property unless internal_sort # this ensures applying converters (e.g. :on_read)
62
- table_cells = @table.swt_widget.items.map {|item| @table.column_properties.size.times.map {|i| item.get_text(i)} }
63
- model_cells = new_model_collection.to_a.map {|m| @table.cells_for(m)}
64
- return if table_cells == model_cells
65
- if new_model_collection and new_model_collection.is_a?(Array)
66
- @table_items_observer_registration&.unobserve
67
- @table_items_observer_registration = observe(new_model_collection, @column_properties)
68
- add_dependent(@table_observer_registration => @table_items_observer_registration)
69
- @model_collection = new_model_collection
69
+ return if same_table_data?(new_model_collection)
70
+ if same_model_collection?(new_model_collection)
71
+ new_model_collection_attribute_values = model_collection_attribute_values(new_model_collection)
72
+ @table.swt_widget.items.each_with_index do |table_item, row_index|
73
+ next if new_model_collection_attribute_values[row_index] == @last_model_collection_attribute_values[row_index]
74
+ model = table_item.get_data
75
+ (0..(@column_properties.size-1)).each do |column_index|
76
+ new_model_attribute_values_for_index = model_attribute_values_for_index(new_model_collection_attribute_values[row_index], column_index)
77
+ last_model_attribute_values_for_index = model_attribute_values_for_index(@last_model_collection_attribute_values[row_index], column_index)
78
+ next if new_model_attribute_values_for_index == last_model_attribute_values_for_index
79
+ model_attribute = @column_properties[column_index]
80
+ update_table_item_properties_from_model(table_item, row_index, column_index, model, model_attribute)
81
+ end
82
+ end
83
+ @last_model_collection_attribute_values = new_model_collection_attribute_values
84
+ else
85
+ if new_model_collection and new_model_collection.is_a?(Array)
86
+ remove_dependent(@table_observer_registration => @table_items_observer_registration) if @table_items_observer_registration
87
+ @table_items_observer_registration&.unobserve
88
+ # TODO observe and update table items piecemeal per model instead of passing @column_properties
89
+ # TODO ensure unobserving models when they are no longer part of the table
90
+ @table_items_observer_registration = observe(new_model_collection, @column_properties)
91
+ add_dependent(@table_observer_registration => @table_items_observer_registration)
92
+ @table_items_property_observer_registration ||= {}
93
+ if !same_model_collection_with_different_sort?(new_model_collection)
94
+ TABLE_ITEM_PROPERTIES.each do |table_item_property|
95
+ remove_dependent(@table_observer_registration => @table_items_property_observer_registration[table_item_property]) if @table_items_property_observer_registration[table_item_property]
96
+ @table_items_property_observer_registration[table_item_property]&.unobserve
97
+ property_properties = @column_properties.map {|property| "#{property}_#{table_item_property}" }
98
+ @table_items_property_observer_registration[table_item_property] = observe(new_model_collection, property_properties)
99
+ add_dependent(@table_observer_registration => @table_items_property_observer_registration[table_item_property])
100
+ end
101
+ end
102
+ @model_collection = new_model_collection
103
+ end
104
+ populate_table(@model_collection, @table, @column_properties, internal_sort: internal_sort)
70
105
  end
71
- populate_table(@model_collection, @table, @column_properties, internal_sort: internal_sort)
72
106
  end
73
107
  end
74
108
 
75
109
  def populate_table(model_collection, parent, column_properties, internal_sort: false)
76
110
  selected_table_item_models = parent.swt_widget.getSelection.map(&:get_data)
77
111
  parent.finish_edit!
78
- parent.swt_widget.items.each(&:dispose)
79
- parent.swt_widget.removeAll
80
- model_collection.each do |model|
81
- table_item = TableItem.new(parent.swt_widget, SWT::SWTProxy[:none])
82
- for index in 0..(column_properties.size-1)
83
- table_item.setText(index, model.send(column_properties[index]).to_s)
112
+ dispose_start_index = @last_model_collection_attribute_values &&
113
+ (model_collection.count < @last_model_collection_attribute_values.count) &&
114
+ (@last_model_collection_attribute_values.count - (@last_model_collection_attribute_values.count - model_collection.count))
115
+ if dispose_start_index
116
+ table_items_to_dispose = parent.swt_widget.items[dispose_start_index..-1]
117
+ parent.swt_widget.remove(dispose_start_index, (@last_model_collection_attribute_values.count-1))
118
+ table_items_to_dispose.each(&:dispose)
119
+ end
120
+ model_collection.each_with_index do |model, row_index|
121
+ table_item_exists = @last_model_collection_attribute_values &&
122
+ @last_model_collection_attribute_values.count > 0 &&
123
+ row_index < @last_model_collection_attribute_values.count
124
+ table_item = table_item_exists ? parent.swt_widget.items[row_index] : TableItem.new(parent.swt_widget, SWT::SWTProxy[:none])
125
+ (0..(column_properties.size-1)).each do |column_index|
126
+ model_attribute = column_properties[column_index]
127
+ update_table_item_properties_from_model(table_item, row_index, column_index, model, model_attribute)
84
128
  end
85
129
  table_item.set_data(model)
86
130
  end
131
+ @last_model_collection_attribute_values = model_collection_attribute_values(model_collection)
87
132
  selected_table_items = parent.search {|item| selected_table_item_models.include?(item.get_data) }
88
133
  parent.swt_widget.setSelection(selected_table_items)
89
134
  sorted_model_collection = parent.sort!(internal_sort: internal_sort)
90
135
  call(sorted_model_collection, internal_sort: true) if @read_only_sort && !internal_sort && !sorted_model_collection.nil?
91
136
  parent.swt_widget.redraw if parent&.swt_widget&.respond_to?(:redraw)
92
137
  end
138
+
139
+ def update_table_item_properties_from_model(table_item, row_index, column_index, model, model_attribute)
140
+ Glimmer::SWT::DisplayProxy.instance.sync_exec do
141
+ old_table_item_values = @last_model_collection_attribute_values &&
142
+ @last_model_collection_attribute_values[row_index] &&
143
+ model_attribute_values_for_index(@last_model_collection_attribute_values[row_index], column_index)
144
+ text_value = model.send(model_attribute).to_s
145
+ old_table_item_value = old_table_item_values && old_table_item_values[0]
146
+ table_item.set_text(column_index, text_value) if old_table_item_value.nil? || text_value != old_table_item_value
147
+ TABLE_ITEM_PROPERTIES.each do |table_item_property|
148
+ if model.respond_to?("#{model_attribute}_#{table_item_property}")
149
+ table_item_value = model.send("#{model_attribute}_#{table_item_property}")
150
+ old_table_item_value = old_table_item_values && old_table_item_values[1 + TABLE_ITEM_PROPERTIES.index(table_item_property)]
151
+ if old_table_item_value.nil? || (table_item_value != old_table_item_value)
152
+ table_item_value = Glimmer::SWT::ColorProxy.create(*table_item_value).swt_color if table_item_value && %w[background foreground].include?(table_item_property.to_s)
153
+ table_item_value = Glimmer::SWT::FontProxy.create(table_item_value).swt_font if table_item_value && table_item_property.to_s == 'font'
154
+ table_item_value = Glimmer::SWT::ImageProxy.create(*table_item_value).swt_image if table_item_value && table_item_property.to_s == 'image'
155
+ table_item.send("set_#{table_item_property}", column_index, table_item_value)
156
+ end
157
+ end
158
+ end
159
+ end
160
+ end
161
+
162
+ def same_table_data?(new_model_collection)
163
+ (["text"] + TABLE_ITEM_PROPERTIES).all? do |table_item_property|
164
+ table_cells = @table.swt_widget.items.map do |item|
165
+ model = item.get_data
166
+ @table.column_properties.each_with_index.map do |column_property, i|
167
+ model_attribute = "#{column_property}"
168
+ model_attribute = "#{model_attribute}_#{table_item_property}" if TABLE_ITEM_PROPERTIES.include?(table_item_property)
169
+ item.send("get_#{table_item_property}", i) if model.respond_to?(model_attribute)
170
+ end
171
+ end
172
+ model_cells = new_model_collection.to_a.map do |m|
173
+ @table.cells_for(m, table_item_property: table_item_property)
174
+ end
175
+ model_cells = model_cells.map do |row|
176
+ row.map do |model_cell|
177
+ if model_cell
178
+ if %w[background foreground].include?(table_item_property.to_s)
179
+ Glimmer::SWT::ColorProxy.create(*model_cell).swt_color
180
+ elsif table_item_property.to_s == 'font'
181
+ Glimmer::SWT::FontProxy.create(model_cell).swt_font
182
+ elsif table_item_property.to_s == 'image'
183
+ Glimmer::SWT::ImageProxy.create(*model_cell).swt_image
184
+ else
185
+ model_cell
186
+ end
187
+ end
188
+ end
189
+ end
190
+ table_cells == model_cells
191
+ end
192
+ end
193
+
194
+ def same_model_collection?(new_model_collection)
195
+ new_model_collection == table_item_model_collection
196
+ end
197
+
198
+ def same_model_collection_with_different_sort?(new_model_collection)
199
+ Set.new(new_model_collection) == Set.new(table_item_model_collection)
200
+ end
201
+
202
+ def table_item_model_collection
203
+ @table.swt_widget.items.map(&:get_data)
204
+ end
205
+
206
+ def model_collection_attribute_values(model_collection)
207
+ model_collection.map do |model|
208
+ (["text"] + TABLE_ITEM_PROPERTIES).map do |table_item_property|
209
+ @table.cells_for(model, table_item_property: table_item_property)
210
+ end
211
+ end
212
+ end
213
+
214
+ def model_attribute_values_for_index(model_attribute_values, index)
215
+ model_attribute_values.map {|attribute_values| attribute_values[index]}
216
+ end
217
+
93
218
  end
94
219
  end
95
220
  end
@@ -41,7 +41,7 @@ module Glimmer
41
41
  end
42
42
 
43
43
  def interpret(parent, keyword, *args, &block)
44
- Glimmer::SWT::FontProxy.new(*args)
44
+ Glimmer::SWT::FontProxy.create(*args)
45
45
  end
46
46
  end
47
47
  end
@@ -42,6 +42,7 @@ module Glimmer
42
42
 
43
43
  REGEX_COLOR_HEX6 = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/
44
44
  FONT_NAMES_PREFERRED = ['Consolas', 'Courier', 'Monospace', 'Liberation Mono']
45
+ SHORTCUT_KEY_COMMAND = OS.mac? ? :command : :ctrl
45
46
 
46
47
  # TODO support auto language detection
47
48
 
@@ -145,7 +146,7 @@ module Glimmer
145
146
 
146
147
  body {
147
148
  if lines
148
- composite {
149
+ @composite = composite {
149
150
  grid_layout(2, false)
150
151
 
151
152
  @line_numbers_styled_text_proxy = styled_text(swt(swt(swt_style), :h_scroll!, :v_scroll!)) {
@@ -204,12 +205,18 @@ module Glimmer
204
205
  on_key_pressed { |event|
205
206
  character = event.keyCode.chr rescue nil
206
207
  case [event.stateMask, character]
207
- when [(OS.mac? ? swt(:command) : swt(:ctrl)), 'a']
208
+ when [swt(SHORTCUT_KEY_COMMAND), 'a']
208
209
  @styled_text_proxy.selectAll
209
210
  when [(swt(:ctrl) if OS.mac?), 'a']
210
211
  jump_to_beginning_of_line
211
212
  when [(swt(:ctrl) if OS.mac?), 'e']
212
213
  jump_to_end_of_line
214
+ when [swt(SHORTCUT_KEY_COMMAND), '=']
215
+ bump_font_height_up
216
+ when [swt(SHORTCUT_KEY_COMMAND), '-']
217
+ bump_font_height_down
218
+ when [swt(SHORTCUT_KEY_COMMAND), '0']
219
+ restore_font_height
213
220
  end
214
221
  }
215
222
  on_verify_text { |verify_event|
@@ -326,12 +333,43 @@ module Glimmer
326
333
 
327
334
  def select_best_font_name
328
335
  all_font_names = display.get_font_list(nil, true).map(&:name)
336
+ @font_name = 'Courier' if OS.mac?
329
337
  FONT_NAMES_PREFERRED.each do |font_name|
330
338
  @font_name ||= font_name if all_font_names.include?(font_name)
331
339
  end
332
340
  @font_name ||= all_font_names.find {|font_name| font_name.downcase.include?('mono')}
333
341
  @font_name
334
342
  end
343
+
344
+ def bump_font_height_up
345
+ @original_font_height ||= font_datum.height
346
+ new_font_height = font_datum.height + 1
347
+ update_font_height(new_font_height)
348
+ end
349
+
350
+ def bump_font_height_down
351
+ @original_font_height ||= font_datum.height
352
+ new_font_height = font_datum.height - 1
353
+ update_font_height(new_font_height)
354
+ end
355
+
356
+ def restore_font_height
357
+ return if @original_font_height.nil?
358
+ update_font_height(@original_font_height)
359
+ @original_font_height = nil
360
+ end
361
+
362
+ def update_font_height(new_font_height)
363
+ return if new_font_height.nil?
364
+ @styled_text_proxy.font = {name: font_datum.name, height: new_font_height, style: font_datum.style}
365
+ @line_numbers_styled_text_proxy&.font = {name: font_datum.name, height: new_font_height, style: font_datum.style}
366
+ @body_root.shell_proxy.layout(true, true)
367
+ @body_root.shell_proxy.pack_same_size
368
+ end
369
+
370
+ def font_datum
371
+ @styled_text_proxy.font.font_data.first
372
+ end
335
373
  end
336
374
  end
337
375
  end
@@ -36,14 +36,24 @@ module Glimmer
36
36
  #
37
37
  # Follows the Proxy Design Pattern
38
38
  class FontProxy
39
- ERROR_INVALID_FONT_STYLE = " is an invalid font style! Valid values are :normal, :bold, and :italic"
40
- FONT_STYLES = [:normal, :bold, :italic]
39
+ class << self
40
+ def create(*args)
41
+ flyweight_font_proxies[args] ||= new(*args)
42
+ end
43
+
44
+ # Flyweight Design Pattern memoization cache. Can be cleared if memory is needed.
45
+ def flyweight_font_proxies
46
+ @flyweight_font_proxies ||= {}
47
+ end
48
+ end
41
49
 
42
50
  include_package 'org.eclipse.swt.graphics'
51
+
52
+ ERROR_INVALID_FONT_STYLE = " is an invalid font style! Valid values are :normal, :bold, and :italic"
53
+ FONT_STYLES = [:normal, :bold, :italic]
43
54
 
44
55
  attr_reader :widget_proxy, :swt_font, :font_properties
45
56
 
46
-
47
57
  # Builds a new font proxy from passed in widget_proxy and font_properties hash,
48
58
  #
49
59
  # It begins with existing SWT widget font and amends it with font properties.
@@ -419,8 +419,14 @@ module Glimmer
419
419
  @editor = args
420
420
  end
421
421
 
422
- def cells_for(model)
423
- column_properties.map {|property| model.send(property)}
422
+ def cells_for(model, table_item_property: :text)
423
+ if table_item_property.to_s == 'text'
424
+ column_properties.map {|column_property| model.send(column_property)}
425
+ else
426
+ column_properties.map do |column_property|
427
+ model.send("#{column_property}_#{table_item_property}") if model.respond_to?("#{column_property}_#{table_item_property}")
428
+ end
429
+ end
424
430
  end
425
431
 
426
432
  def cells
@@ -28,3 +28,4 @@ Hello, Canvas Transform!: ePIAF5EMsE0
28
28
  Parking: kw-6icVgDR4
29
29
  Hello, Custom Widget!: aJHLo5yLDZc
30
30
  Hello, Custom Shell!: c8Eb8GWM_XQ
31
+ Hello, Custom Shape!: H3J8ecp30Ak
@@ -25,17 +25,17 @@ require 'glimmer-dsl-swt'
25
25
  class StickFigure
26
26
  include Glimmer::UI::CustomShape
27
27
 
28
- options :x, :y, :width, :height
28
+ options :figure_x, :figure_y, :figure_width, :figure_height
29
29
 
30
30
  before_body do
31
- @head_width = width*0.2
32
- @head_height = height*0.2
33
- @trunk_height = height*0.4
34
- @extremity_length = height*0.4
31
+ @head_width = figure_width*0.2
32
+ @head_height = figure_height*0.2
33
+ @trunk_height = figure_height*0.4
34
+ @extremity_length = figure_height*0.4
35
35
  end
36
36
 
37
37
  body {
38
- shape(x + @head_width/2.0 + @extremity_length, y) {
38
+ shape(figure_x + @head_width/2.0 + @extremity_length, figure_y) {
39
39
  oval(0, 0, @head_width, @head_height)
40
40
  line(@head_width/2.0, @head_height, @head_width/2.0, @head_height + @trunk_height)
41
41
  line(@head_width/2.0, @head_height + @trunk_height, @head_width/2.0 + @extremity_length, @head_height + @trunk_height + @extremity_length)
@@ -47,7 +47,7 @@ class StickFigure
47
47
  end
48
48
 
49
49
  class HelloCustomShape
50
- include Glimmer::UI::CustomShell
50
+ include Glimmer::UI::Application
51
51
 
52
52
  WIDTH = 220
53
53
  HEIGHT = 235
@@ -60,12 +60,12 @@ class HelloCustomShape
60
60
  @canvas = canvas {
61
61
  background :white
62
62
 
63
- 15.times { |n|
63
+ 15.times do |n|
64
64
  x_location = (rand*WIDTH/2).to_i%WIDTH + (rand*15).to_i
65
65
  y_location = (rand*HEIGHT/2).to_i%HEIGHT + (rand*15).to_i
66
66
  foreground_color = rgb(rand*255, rand*255, rand*255)
67
67
 
68
- a_stick_figure = stick_figure(x: x_location, y: y_location, width: 35+n*2, height: 35+n*2) {
68
+ a_stick_figure = stick_figure(figure_x: x_location, figure_y: y_location, figure_width: 35+n*2, figure_height: 35+n*2) {
69
69
  foreground foreground_color
70
70
  drag_and_move true
71
71
 
@@ -74,7 +74,7 @@ class HelloCustomShape
74
74
  a_stick_figure.foreground = rgb(rand*255, rand*255, rand*255)
75
75
  end
76
76
  }
77
- }
77
+ end
78
78
  }
79
79
  }
80
80
  }
@@ -89,6 +89,7 @@ class HelloTable
89
89
  def playoff_type=(new_playoff_type)
90
90
  @playoff_type = new_playoff_type
91
91
  self.schedule=(all_playoff_games[@playoff_type])
92
+ self.selected_game = schedule.first unless selected_game.nil?
92
93
  end
93
94
 
94
95
  def playoff_type_options
@@ -118,15 +119,24 @@ class HelloTable
118
119
  'St Louis Cardinals' => 'Busch Stadium',
119
120
  }
120
121
 
121
- attr_accessor :date_time, :home_team, :away_team, :ballpark, :promotion
122
+ ATTRIBUTES = [:game_date, :game_time, :home_team, :away_team, :ballpark, :promotion]
123
+ ATTRIBUTES_BACKGROUND = ATTRIBUTES.map {|attribute| "#{attribute}_background"}
124
+ ATTRIBUTES_FOREGROUND = ATTRIBUTES.map {|attribute| "#{attribute}_foreground"}
125
+ ATTRIBUTES_FONT = ATTRIBUTES.map {|attribute| "#{attribute}_font"}
126
+ ATTRIBUTES_IMAGE = ATTRIBUTES.map {|attribute| "#{attribute}_image"}
122
127
 
128
+ attr_accessor *([:booked, :date_time] + ATTRIBUTES + ATTRIBUTES_BACKGROUND + ATTRIBUTES_FOREGROUND + ATTRIBUTES_FONT + ATTRIBUTES_IMAGE)
129
+ alias booked? booked
130
+
123
131
  def initialize(date_time, home_team, away_team, promotion = 'N/A')
124
132
  self.date_time = date_time
125
133
  self.home_team = home_team
126
134
  self.away_team = away_team
127
135
  self.promotion = promotion
136
+ self.ballpark_image = [File.expand_path('hello_table/baseball_park.png', __dir__), width: 20, height: 20]
137
+ self.booked = false
138
+
128
139
  observe(self, :date_time) do |new_value|
129
- notify_observers(:game_date)
130
140
  notify_observers(:game_time)
131
141
  end
132
142
  end
@@ -177,8 +187,42 @@ class HelloTable
177
187
  end
178
188
 
179
189
  def book!
190
+ self.booked = true
191
+ self.background = :dark_green
192
+ self.foreground = :white
193
+ self.font = {style: :italic}
180
194
  "Thank you for booking #{to_s}"
181
195
  end
196
+
197
+ # Sets background for all attributes
198
+ def background=(color)
199
+ self.game_date_background = color
200
+ self.game_time_background = color
201
+ self.home_team_background = color
202
+ self.away_team_background = color
203
+ self.ballpark_background = color
204
+ self.promotion_background = color
205
+ end
206
+
207
+ # Sets foreground for all attributes
208
+ def foreground=(color)
209
+ self.game_date_foreground = color
210
+ self.game_time_foreground = color
211
+ self.home_team_foreground = color
212
+ self.away_team_foreground = color
213
+ self.ballpark_foreground = color
214
+ self.promotion_foreground = color
215
+ end
216
+
217
+ # Sets font for all attributes
218
+ def font=(font_properties)
219
+ self.game_date_font = font_properties
220
+ self.game_time_font = font_properties
221
+ self.home_team_font = font_properties
222
+ self.away_team_font = font_properties
223
+ self.ballpark_font = font_properties
224
+ self.promotion_font = font_properties
225
+ end
182
226
  end
183
227
 
184
228
  include Glimmer::UI::CustomShell
@@ -246,8 +290,27 @@ class HelloTable
246
290
  # default text editor is used here
247
291
  }
248
292
 
249
- # Data-bind table items (rows) to a model collection property, specifying column properties ordering per nested model
250
- items <=> [BaseballGame, :schedule, column_properties: [:game_date, :game_time, :ballpark, :home_team, :away_team, :promotion]]
293
+ # This is a contextual pop up menu that shows up when right-clicking table rows
294
+ menu {
295
+ menu_item {
296
+ text 'Book'
297
+
298
+ on_widget_selected do
299
+ book_selected_game
300
+ end
301
+ }
302
+ }
303
+
304
+ # Data-bind table items (rows) to a model collection (BaseballGame.schedule),
305
+ # mapping columns in declaration order to row model properties (attributes)
306
+ # By convention, every column property can be accompanied by extra properties
307
+ # with the following suffixes: `_background`, `_foreground`, `_font`, and `_image`
308
+ # For example, for `game_date`, model could also implement these related properties:
309
+ # `game_date_background`, `game_date_foreground`, `game_date_font`, `game_date_image`
310
+ # That is done in order to let the table widget set extra properties if needed.
311
+ items <=> [BaseballGame, :schedule,
312
+ column_properties: [:game_date, :game_time, :ballpark, :home_team, :away_team, :promotion]
313
+ ]
251
314
 
252
315
  # Data-bind table selection
253
316
  selection <=> [BaseballGame, :selected_game]
@@ -258,22 +321,16 @@ class HelloTable
258
321
  # Sort by these additional properties after handling sort by the column the user clicked
259
322
  additional_sort_properties :date, :time, :home_team, :away_team, :ballpark, :promotion
260
323
 
261
- menu {
262
- menu_item {
263
- text 'Book'
264
-
265
- on_widget_selected do
266
- book_selected_game
267
- end
268
- }
269
- }
324
+ on_key_pressed do |key_event|
325
+ book_selected_game if key_event.keyCode == swt(:cr)
326
+ end
270
327
  }
271
328
 
272
329
  button {
273
330
  text 'Book Selected Game'
274
331
  layout_data :center, :center, true, false
275
332
  font height: 14
276
- enabled <= [BaseballGame, :selected_game]
333
+ enabled <= [BaseballGame, 'selected_game.booked', on_read: ->(value) { value == false }]
277
334
 
278
335
  on_widget_selected do
279
336
  book_selected_game
@@ -283,6 +340,8 @@ class HelloTable
283
340
  }
284
341
 
285
342
  def book_selected_game
343
+ return if BaseballGame.selected_game.booked?
344
+
286
345
  message_box {
287
346
  text 'Baseball Game Booked!'
288
347
  message BaseballGame.selected_game.book!
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glimmer-dsl-swt
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.24.2.2
4
+ version: 4.24.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Maleh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-08-21 00:00:00.000000000 Z
11
+ date: 2022-08-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement