glimmer-dsl-swt 4.24.2.3 → 4.24.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +21 -0
- data/README.md +6 -6
- data/VERSION +1 -1
- data/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md +98 -19
- data/docs/reference/GLIMMER_SAMPLES.md +23 -7
- data/glimmer-dsl-swt.gemspec +0 -0
- data/lib/glimmer/data_binding/table_items_binding.rb +146 -19
- data/lib/glimmer/dsl/swt/font_expression.rb +1 -1
- data/lib/glimmer/swt/custom/code_text.rb +39 -2
- data/lib/glimmer/swt/font_proxy.rb +13 -3
- data/lib/glimmer/swt/table_proxy.rb +23 -3
- data/samples/elaborate/contact_manager.rb +1 -1
- data/samples/elaborate/meta_sample/tutorials.yml +2 -0
- data/samples/elaborate/meta_sample.rb +11 -9
- data/samples/elaborate/tetris/view/high_score_dialog.rb +1 -1
- data/samples/hello/hello_custom_shape.rb +10 -10
- data/samples/hello/hello_custom_shell.rb +4 -4
- data/samples/hello/hello_table.rb +74 -14
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 89250fa7cc394da176eb7cd91a17c7ad388607c69927a7e22b6b1be62333a0b8
|
4
|
+
data.tar.gz: e7e09c62b782c682c0abdb8722001c8925268cfe4bab49b536eb58f3f32fb697
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 136c2625e94629b690a325bdc3c8669a36c612f9f651b04faa5be3dcbcc86b57ae5345c23fcce1b10656b9dca5e8a4e96a318147907785a5bff18eac3dd4b130
|
7
|
+
data.tar.gz: 6d1c069b332ccd3139cf0c6377dd64b5341ccd84cc4dda3c72f5255c0eaeff0639bbfcdea35cb6b66baa84fb9ed1093143cafb4897f6ba2b2198dd494e0033c3
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,26 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## 4.24.3.2
|
4
|
+
|
5
|
+
- Have `table` data-binding infer model attribute names from column names by convention (no need to specify `column_properties`)
|
6
|
+
- Support `table` data-binding `column_properties` mapping of column names to model attribute names via a `Hash`
|
7
|
+
- Support `table` data-binding alias of `column_attributes` in place of `column_properties` because the word 'attribute' is more Ruby-idiomatic than 'property' in the Ruby world
|
8
|
+
- Handle boundary condition of font height reaching 0 on repeated zoom out of `code_text`
|
9
|
+
- Battleship Video Tutorial in Glimmer Meta-Sample
|
10
|
+
|
11
|
+
## 4.24.3.1
|
12
|
+
|
13
|
+
- `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).
|
14
|
+
|
15
|
+
## 4.24.3.0
|
16
|
+
|
17
|
+
- 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)
|
18
|
+
- 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
|
19
|
+
- Update Hello, Table! sample to add `booked` attribute to `BaseballGame` to disable Book button when already booked
|
20
|
+
- Update Hello, Table! sample to enable booking by hitting the ENTER keyboard button
|
21
|
+
- 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)
|
22
|
+
- Update `font` keyword and `FontProxy` to support lightweight creation/caching/sharing following Flyweight Design Pattern
|
23
|
+
|
3
24
|
## 4.24.2.3
|
4
25
|
|
5
26
|
- Default `code_text` font name in Mac is changed back to `'Courier'`
|
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
|
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.2
|
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
|
24
|
+
[Glimmer DSL for SWT](https://rubygems.org/gems/glimmer-dsl-swt) 4.24.3.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.
|
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
|
341
|
+
jgem install glimmer-dsl-swt -v 4.24.3.2
|
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
|
369
|
+
gem 'glimmer-dsl-swt', '~> 4.24.3.2'
|
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
|
392
|
+
Glimmer (JRuby Desktop Development GUI Framework) - JRuby Gem: glimmer-dsl-swt v4.24.3.2
|
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
|
1
|
+
4.24.3.2
|
@@ -3996,13 +3996,13 @@ You may learn more about Glimmer's data-binding syntax by reading the code under
|
|
3996
3996
|
|
3997
3997
|
The SWT Tree widget renders a multi-column data table, such as a contact listing or a sales report.
|
3998
3998
|
|
3999
|
-
To data-bind a Table, you need the main model
|
3999
|
+
To data-bind a Table, you need the main model and the collection property. The text for each row cell will be inferred from column names as underscored model attributes. For example, for a column named "Full Name", it is assumed by convention that the model has a `full_name` attribute.
|
4000
4000
|
|
4001
|
-
|
4001
|
+
Data-binding involves using the `<=` operator (one-way data-binding) or `<=>` operator (two-way data-binding), and an optional `column_attributes` kwarg (alias: `column_properties`) that takes an array that maps table columns to model attributes or a hash that maps column name strings to model attributes.
|
4002
4002
|
|
4003
|
-
It assumes you have defined
|
4003
|
+
It assumes you have already defined table columns via the `table_column` `table`-nested widget.
|
4004
4004
|
|
4005
|
-
Example:
|
4005
|
+
Example (automatically inferring table items' [rows'] model attributes by convention from column names):
|
4006
4006
|
|
4007
4007
|
```ruby
|
4008
4008
|
shell {
|
@@ -4019,8 +4019,10 @@ shell {
|
|
4019
4019
|
text "Adult"
|
4020
4020
|
width 120
|
4021
4021
|
}
|
4022
|
-
|
4023
|
-
|
4022
|
+
|
4023
|
+
items <=> [group, :people]
|
4024
|
+
selection <=> [group, :selected_person]
|
4025
|
+
|
4024
4026
|
on_mouse_up do |event|
|
4025
4027
|
@table.edit_table_item(event.table_item, event.column_index)
|
4026
4028
|
end
|
@@ -4028,15 +4030,71 @@ shell {
|
|
4028
4030
|
}
|
4029
4031
|
```
|
4030
4032
|
|
4031
|
-
The code above includes two data-bindings:
|
4032
|
-
- Table `items`, which first
|
4033
|
-
- Table `selection`, which binds the single table item selected by the user to the attribute denoted by
|
4033
|
+
The code above includes two data-bindings and a listener:
|
4034
|
+
- Table `items`, which first data-binds to the model collection property (group.people), and then maps each column to a model attribute (name, age, adult) for displaying each table item column.
|
4035
|
+
- 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
4036
|
- 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
4037
|
|
4036
|
-
|
4038
|
+
Example (specifying `column_attributes` explicitly because some diverge from column names):
|
4039
|
+
|
4040
|
+
```ruby
|
4041
|
+
shell {
|
4042
|
+
@table = table {
|
4043
|
+
table_column {
|
4044
|
+
text "Full Name"
|
4045
|
+
width 120
|
4046
|
+
}
|
4047
|
+
table_column {
|
4048
|
+
text "Age in Years"
|
4049
|
+
width 120
|
4050
|
+
}
|
4051
|
+
table_column {
|
4052
|
+
text "Adult"
|
4053
|
+
width 120
|
4054
|
+
}
|
4055
|
+
|
4056
|
+
items <=> [group, :people, column_attributes: {'Full Name' => :name, 'Age in Years' => :age}]
|
4057
|
+
selection <=> [group, :selected_person]
|
4058
|
+
|
4059
|
+
on_mouse_up do |event|
|
4060
|
+
@table.edit_table_item(event.table_item, event.column_index)
|
4061
|
+
end
|
4062
|
+
}
|
4063
|
+
}
|
4064
|
+
```
|
4037
4065
|
|
4038
|
-
|
4039
|
-
|
4066
|
+
Example (specifying `column_attributes` explicitly because all diverge from column names):
|
4067
|
+
|
4068
|
+
```ruby
|
4069
|
+
shell {
|
4070
|
+
@table = table {
|
4071
|
+
table_column {
|
4072
|
+
text "Full Name"
|
4073
|
+
width 120
|
4074
|
+
}
|
4075
|
+
table_column {
|
4076
|
+
text "Age in Years"
|
4077
|
+
width 120
|
4078
|
+
}
|
4079
|
+
table_column {
|
4080
|
+
text "Is Adult"
|
4081
|
+
width 120
|
4082
|
+
}
|
4083
|
+
|
4084
|
+
items <=> [group, :people, column_attributes: [:name, :age, :adult]]
|
4085
|
+
selection <=> [group, :selected_person]
|
4086
|
+
|
4087
|
+
on_mouse_up do |event|
|
4088
|
+
@table.edit_table_item(event.table_item, event.column_index)
|
4089
|
+
end
|
4090
|
+
}
|
4091
|
+
}
|
4092
|
+
```
|
4093
|
+
|
4094
|
+
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.
|
4095
|
+
|
4096
|
+
The table widget in Glimmer is represented by a subclass of `Glimmer::SWT::WidgetProxy` called `Glimmer::SWT::TableProxy`.
|
4097
|
+
`Glimmer::SWT::TableProxy` includes a `search` method that takes a block to look for a table item.
|
4040
4098
|
|
4041
4099
|
Example:
|
4042
4100
|
|
@@ -4044,13 +4102,31 @@ Example:
|
|
4044
4102
|
found_array = @table.search { |table_item| table_item.getData == company.owner }
|
4045
4103
|
```
|
4046
4104
|
|
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.
|
4105
|
+
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
4106
|
|
4049
4107
|
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
4108
|
This automatically leverages the SWT TableEditor custom class behind the scenes, displaying a text widget to the user to change the selected or
|
4051
4109
|
passed table item text into something else.
|
4052
4110
|
It automatically persists the change to `items` data-bound model on ENTER/FOCUS-OUT or cancels on ESC/NO-CHANGE.
|
4053
4111
|
|
4112
|
+
##### Table Item Properties
|
4113
|
+
|
4114
|
+
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.
|
4115
|
+
|
4116
|
+
That means that if `column_attributes` 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:
|
4117
|
+
- `background` to `:name_background, :age_background, :adult_background` model attributes
|
4118
|
+
- `foreground` to `:name_foreground, :age_foreground, :adult_foreground` model attributes
|
4119
|
+
- `font` to `:name_font, :age_font, :adult_font` model attributes
|
4120
|
+
- `image` to `:name_image, :age_image, :adult_image` model attributes
|
4121
|
+
|
4122
|
+
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):
|
4123
|
+
- `background`: Standard color symbol/string (e.g. `:red`), rgb array (e.g. `[24, 21, 239]`), or rgba array (e.g. `[128, 0, 128, 50]`)
|
4124
|
+
- `foreground`: Standard color symbol/string (e.g. `:red`), rgb array (e.g. `[24, 21, 239]`), or rgba array (e.g. `[128, 0, 128, 50]`)
|
4125
|
+
- `font`: font data hash having `:name`, `:height`, and/or `:style` keys (e.g. `{name: 'Courier New', height: 25, style: [:bold, :italic]}`)
|
4126
|
+
- `image`: image URL with or without image options (e.g. `'/usr/image1.png'` or `['/usr/image1.png', width: 20, height: 20]`)
|
4127
|
+
|
4128
|
+
![Hello Table game booked rows](/images/glimmer-hello-table-game-booked-rows.png)
|
4129
|
+
|
4054
4130
|
##### Table Selection
|
4055
4131
|
|
4056
4132
|
Table Selection data-binding is simply done via the `selection` property.
|
@@ -4086,7 +4162,7 @@ shell {
|
|
4086
4162
|
text "Adult"
|
4087
4163
|
width 120
|
4088
4164
|
}
|
4089
|
-
items
|
4165
|
+
items <=> [group, :people]
|
4090
4166
|
selection bind(group, :selected_person)
|
4091
4167
|
}
|
4092
4168
|
}
|
@@ -4113,7 +4189,7 @@ shell {
|
|
4113
4189
|
width 120
|
4114
4190
|
editor :checkbox
|
4115
4191
|
}
|
4116
|
-
items
|
4192
|
+
items <=> [group, :people]
|
4117
4193
|
selection bind(group, :selected_person)
|
4118
4194
|
}
|
4119
4195
|
}
|
@@ -4152,7 +4228,7 @@ shell {
|
|
4152
4228
|
# assume there is a `Person#industry_options` property method on the model to provide items to the `combo`
|
4153
4229
|
editor :combo, :read_only # passes :ready_only SWT style to `combo` widget
|
4154
4230
|
}
|
4155
|
-
items
|
4231
|
+
items <=> [group, :people, column_attributes: {'Date of Birth' => :formatted_date}]
|
4156
4232
|
selection bind(group, :selected_person)
|
4157
4233
|
}
|
4158
4234
|
}
|
@@ -4211,7 +4287,7 @@ Example:
|
|
4211
4287
|
sort { |d1, d2| d1.to_date <=> d2.to_date }
|
4212
4288
|
}
|
4213
4289
|
additional_sort_properties :project_name, :duration_in_hours, :name
|
4214
|
-
items
|
4290
|
+
items <=> [Task, :list, column_attributes: [:name, :project_name, :duration, :priority, :start_date]]
|
4215
4291
|
# ...
|
4216
4292
|
}
|
4217
4293
|
# ...
|
@@ -4224,7 +4300,7 @@ Here is an explanation of the example above:
|
|
4224
4300
|
- Task Start Date table column has a custom sort comparator block
|
4225
4301
|
- Additional (secondary) sort properties are applied when sorting by Task, Project, or Duration in the order specified
|
4226
4302
|
|
4227
|
-
|
4303
|
+
`<= [model, :property, read_only_sort: true]` could be used with items to make sorting not propagate sorting changes to model.
|
4228
4304
|
|
4229
4305
|
#### Tree
|
4230
4306
|
|
@@ -4807,7 +4883,7 @@ You may see another example at the [Hello, Radio Group!](/docs/reference/GLIMMER
|
|
4807
4883
|
|
4808
4884
|
##### Code Text Custom Widget
|
4809
4885
|
|
4810
|
-
`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.
|
4886
|
+
`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).
|
4811
4887
|
|
4812
4888
|
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.
|
4813
4889
|
|
@@ -5133,6 +5209,9 @@ This adds some default keyboard shortcuts:
|
|
5133
5209
|
- CMD+A (CTRL+A on Windows/Linux) to select all
|
5134
5210
|
- CTRL+A on Mac to jump to beginning of line
|
5135
5211
|
- CTRL+E on Mac to jump to end of line
|
5212
|
+
- CMD+= (CTRL+= on Windows/Linux) to zoom in (bump font height up by 1)
|
5213
|
+
- CMD+- (CTRL+- on Windows/Linux) to zoom out (bump font height down by 1)
|
5214
|
+
- CMD+0 (CTRL+0 on Windows/Linux) to restore to original font height
|
5136
5215
|
- Attempts to add proper indentation upon adding a new line when hitting ENTER (currently supporting Ruby only)
|
5137
5216
|
|
5138
5217
|
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!
|
779
|
+
Hello, Table! Game Booked Rows
|
776
780
|
|
777
|
-
![Hello Table](/images/glimmer-hello-table-
|
781
|
+
![Hello Table game booked rows](/images/glimmer-hello-table-game-booked-rows.png)
|
778
782
|
|
779
783
|
#### Hello, Link!
|
780
784
|
|
@@ -816,17 +820,29 @@ Code:
|
|
816
820
|
|
817
821
|
[samples/hello/hello_code_text.rb](/samples/hello/hello_code_text.rb)
|
818
822
|
|
819
|
-
Hello, Code Text!
|
823
|
+
Hello, Code Text! HTML Language / GitHub Theme / No Line Numbers
|
820
824
|
|
821
|
-
![Hello Code Text
|
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!
|
831
|
+
Hello, Code Text! Ruby Language / Glimmer Theme / Show Line Numbers (default width of 4)
|
828
832
|
|
829
|
-
![Hello Code Text
|
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
|
|
data/glimmer-dsl-swt.gemspec
CHANGED
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,17 +35,21 @@ 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
|
39
43
|
@model_binding = model_binding
|
40
44
|
@read_only_sort = @model_binding.binding_options[:read_only_sort]
|
41
|
-
@column_properties = @model_binding.binding_options[:column_properties] || @model_binding.binding_options[:column_attributes] || column_properties
|
42
45
|
@table.editable = false if @model_binding.binding_options[:read_only]
|
43
|
-
|
44
|
-
|
46
|
+
column_properties = @model_binding.binding_options[:column_properties] || @model_binding.binding_options[:column_attributes] || column_properties
|
47
|
+
if @table.is_a?(Glimmer::SWT::TableProxy)
|
48
|
+
@table.column_properties = column_properties
|
49
|
+
@column_properties = @table.column_properties # normalized column properties
|
45
50
|
else # assume custom widget
|
46
51
|
@table.body_root.column_properties = @column_properties
|
52
|
+
@column_properties = @table.body_root.column_properties # normalized column properties
|
47
53
|
end
|
48
54
|
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
|
49
55
|
@table.swt_widget.data = @model_binding
|
@@ -56,40 +62,161 @@ module Glimmer
|
|
56
62
|
end
|
57
63
|
end
|
58
64
|
|
59
|
-
def call(
|
65
|
+
def call(*args)
|
66
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
67
|
+
internal_sort = options[:internal_sort] || false
|
68
|
+
new_model_collection = args.first
|
60
69
|
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
70
|
new_model_collection = model_binding_evaluated_property = @model_binding.evaluate_property unless internal_sort # this ensures applying converters (e.g. :on_read)
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
71
|
+
return if same_table_data?(new_model_collection)
|
72
|
+
if same_model_collection?(new_model_collection)
|
73
|
+
new_model_collection_attribute_values = model_collection_attribute_values(new_model_collection)
|
74
|
+
@table.swt_widget.items.each_with_index do |table_item, row_index|
|
75
|
+
next if new_model_collection_attribute_values[row_index] == @last_model_collection_attribute_values[row_index]
|
76
|
+
model = table_item.get_data
|
77
|
+
(0..(@column_properties.size-1)).each do |column_index|
|
78
|
+
new_model_attribute_values_for_index = model_attribute_values_for_index(new_model_collection_attribute_values[row_index], column_index)
|
79
|
+
last_model_attribute_values_for_index = model_attribute_values_for_index(@last_model_collection_attribute_values[row_index], column_index)
|
80
|
+
next if new_model_attribute_values_for_index == last_model_attribute_values_for_index
|
81
|
+
model_attribute = @column_properties[column_index]
|
82
|
+
update_table_item_properties_from_model(table_item, row_index, column_index, model, model_attribute)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
@last_model_collection_attribute_values = new_model_collection_attribute_values
|
86
|
+
else
|
87
|
+
if new_model_collection and new_model_collection.is_a?(Array)
|
88
|
+
remove_dependent(@table_observer_registration => @table_items_observer_registration) if @table_items_observer_registration
|
89
|
+
@table_items_observer_registration&.unobserve
|
90
|
+
# TODO observe and update table items piecemeal per model instead of passing @column_properties
|
91
|
+
# TODO ensure unobserving models when they are no longer part of the table
|
92
|
+
@table_items_observer_registration = observe(new_model_collection, @column_properties)
|
93
|
+
add_dependent(@table_observer_registration => @table_items_observer_registration)
|
94
|
+
@table_items_property_observer_registration ||= {}
|
95
|
+
if !same_model_collection_with_different_sort?(new_model_collection)
|
96
|
+
TABLE_ITEM_PROPERTIES.each do |table_item_property|
|
97
|
+
remove_dependent(@table_observer_registration => @table_items_property_observer_registration[table_item_property]) if @table_items_property_observer_registration[table_item_property]
|
98
|
+
@table_items_property_observer_registration[table_item_property]&.unobserve
|
99
|
+
property_properties = @column_properties.map {|property| "#{property}_#{table_item_property}" }
|
100
|
+
@table_items_property_observer_registration[table_item_property] = observe(new_model_collection, property_properties)
|
101
|
+
add_dependent(@table_observer_registration => @table_items_property_observer_registration[table_item_property])
|
102
|
+
end
|
103
|
+
end
|
104
|
+
@model_collection = new_model_collection
|
105
|
+
end
|
106
|
+
populate_table(@model_collection, @table, @column_properties, internal_sort: internal_sort)
|
70
107
|
end
|
71
|
-
populate_table(@model_collection, @table, @column_properties, internal_sort: internal_sort)
|
72
108
|
end
|
73
109
|
end
|
74
110
|
|
75
111
|
def populate_table(model_collection, parent, column_properties, internal_sort: false)
|
76
112
|
selected_table_item_models = parent.swt_widget.getSelection.map(&:get_data)
|
77
113
|
parent.finish_edit!
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
114
|
+
dispose_start_index = @last_model_collection_attribute_values &&
|
115
|
+
(model_collection.count < @last_model_collection_attribute_values.count) &&
|
116
|
+
(@last_model_collection_attribute_values.count - (@last_model_collection_attribute_values.count - model_collection.count))
|
117
|
+
if dispose_start_index
|
118
|
+
table_items_to_dispose = parent.swt_widget.items[dispose_start_index..-1]
|
119
|
+
parent.swt_widget.remove(dispose_start_index, (@last_model_collection_attribute_values.count-1))
|
120
|
+
table_items_to_dispose.each(&:dispose)
|
121
|
+
end
|
122
|
+
model_collection.each_with_index do |model, row_index|
|
123
|
+
table_item_exists = @last_model_collection_attribute_values &&
|
124
|
+
@last_model_collection_attribute_values.count > 0 &&
|
125
|
+
row_index < @last_model_collection_attribute_values.count
|
126
|
+
table_item = table_item_exists ? parent.swt_widget.items[row_index] : TableItem.new(parent.swt_widget, SWT::SWTProxy[:none])
|
127
|
+
(0..(column_properties.size-1)).each do |column_index|
|
128
|
+
model_attribute = column_properties[column_index]
|
129
|
+
update_table_item_properties_from_model(table_item, row_index, column_index, model, model_attribute)
|
84
130
|
end
|
85
131
|
table_item.set_data(model)
|
86
132
|
end
|
133
|
+
@last_model_collection_attribute_values = model_collection_attribute_values(model_collection)
|
87
134
|
selected_table_items = parent.search {|item| selected_table_item_models.include?(item.get_data) }
|
88
135
|
parent.swt_widget.setSelection(selected_table_items)
|
89
136
|
sorted_model_collection = parent.sort!(internal_sort: internal_sort)
|
90
137
|
call(sorted_model_collection, internal_sort: true) if @read_only_sort && !internal_sort && !sorted_model_collection.nil?
|
91
138
|
parent.swt_widget.redraw if parent&.swt_widget&.respond_to?(:redraw)
|
92
139
|
end
|
140
|
+
|
141
|
+
def update_table_item_properties_from_model(table_item, row_index, column_index, model, model_attribute)
|
142
|
+
Glimmer::SWT::DisplayProxy.instance.sync_exec do
|
143
|
+
old_table_item_values = @last_model_collection_attribute_values &&
|
144
|
+
@last_model_collection_attribute_values[row_index] &&
|
145
|
+
model_attribute_values_for_index(@last_model_collection_attribute_values[row_index], column_index)
|
146
|
+
text_value = model.send(model_attribute).to_s
|
147
|
+
old_table_item_value = old_table_item_values && old_table_item_values[0]
|
148
|
+
table_item.set_text(column_index, text_value) if old_table_item_value.nil? || text_value != old_table_item_value
|
149
|
+
TABLE_ITEM_PROPERTIES.each do |table_item_property|
|
150
|
+
if model.respond_to?("#{model_attribute}_#{table_item_property}")
|
151
|
+
table_item_value = model.send("#{model_attribute}_#{table_item_property}")
|
152
|
+
old_table_item_value = old_table_item_values && old_table_item_values[1 + TABLE_ITEM_PROPERTIES.index(table_item_property)]
|
153
|
+
if old_table_item_value.nil? || (table_item_value != old_table_item_value)
|
154
|
+
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)
|
155
|
+
table_item_value = Glimmer::SWT::FontProxy.create(table_item_value).swt_font if table_item_value && table_item_property.to_s == 'font'
|
156
|
+
table_item_value = Glimmer::SWT::ImageProxy.create(*table_item_value).swt_image if table_item_value && table_item_property.to_s == 'image'
|
157
|
+
table_item.send("set_#{table_item_property}", column_index, table_item_value)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def same_table_data?(new_model_collection)
|
165
|
+
(["text"] + TABLE_ITEM_PROPERTIES).all? do |table_item_property|
|
166
|
+
table_cells = @table.swt_widget.items.map do |item|
|
167
|
+
model = item.get_data
|
168
|
+
@table.column_properties.each_with_index.map do |column_property, i|
|
169
|
+
model_attribute = "#{column_property}"
|
170
|
+
model_attribute = "#{model_attribute}_#{table_item_property}" if TABLE_ITEM_PROPERTIES.include?(table_item_property)
|
171
|
+
item.send("get_#{table_item_property}", i) if model.respond_to?(model_attribute)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
model_cells = new_model_collection.to_a.map do |m|
|
175
|
+
@table.cells_for(m, table_item_property: table_item_property)
|
176
|
+
end
|
177
|
+
model_cells = model_cells.map do |row|
|
178
|
+
row.map do |model_cell|
|
179
|
+
if model_cell
|
180
|
+
if %w[background foreground].include?(table_item_property.to_s)
|
181
|
+
Glimmer::SWT::ColorProxy.create(*model_cell).swt_color
|
182
|
+
elsif table_item_property.to_s == 'font'
|
183
|
+
Glimmer::SWT::FontProxy.create(model_cell).swt_font
|
184
|
+
elsif table_item_property.to_s == 'image'
|
185
|
+
Glimmer::SWT::ImageProxy.create(*model_cell).swt_image
|
186
|
+
else
|
187
|
+
model_cell
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
table_cells == model_cells
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def same_model_collection?(new_model_collection)
|
197
|
+
new_model_collection == table_item_model_collection
|
198
|
+
end
|
199
|
+
|
200
|
+
def same_model_collection_with_different_sort?(new_model_collection)
|
201
|
+
Set.new(new_model_collection) == Set.new(table_item_model_collection)
|
202
|
+
end
|
203
|
+
|
204
|
+
def table_item_model_collection
|
205
|
+
@table.swt_widget.items.map(&:get_data)
|
206
|
+
end
|
207
|
+
|
208
|
+
def model_collection_attribute_values(model_collection)
|
209
|
+
model_collection.map do |model|
|
210
|
+
(["text"] + TABLE_ITEM_PROPERTIES).map do |table_item_property|
|
211
|
+
@table.cells_for(model, table_item_property: table_item_property)
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def model_attribute_values_for_index(model_attribute_values, index)
|
217
|
+
model_attribute_values.map {|attribute_values| attribute_values[index]}
|
218
|
+
end
|
219
|
+
|
93
220
|
end
|
94
221
|
end
|
95
222
|
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 [
|
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|
|
@@ -333,6 +340,36 @@ module Glimmer
|
|
333
340
|
@font_name ||= all_font_names.find {|font_name| font_name.downcase.include?('mono')}
|
334
341
|
@font_name
|
335
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) == 0 ? font_datum.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
|
336
373
|
end
|
337
374
|
end
|
338
375
|
end
|
@@ -36,14 +36,24 @@ module Glimmer
|
|
36
36
|
#
|
37
37
|
# Follows the Proxy Design Pattern
|
38
38
|
class FontProxy
|
39
|
-
|
40
|
-
|
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.
|
@@ -246,7 +246,8 @@ module Glimmer
|
|
246
246
|
end
|
247
247
|
|
248
248
|
attr_reader :table_editor, :table_editor_widget_proxy, :sort_property, :sort_direction, :sort_block, :sort_type, :sort_by_block, :additional_sort_properties, :editor, :editable
|
249
|
-
|
249
|
+
attr_writer :column_properties
|
250
|
+
alias column_attributes= column_properties=
|
250
251
|
alias editable? editable
|
251
252
|
|
252
253
|
def initialize(underscored_widget_name, parent, args)
|
@@ -258,6 +259,19 @@ module Glimmer
|
|
258
259
|
@table_editor.minimumHeight = 20
|
259
260
|
self.editable = editable_style
|
260
261
|
end
|
262
|
+
|
263
|
+
def column_properties
|
264
|
+
if @column_properties.nil?
|
265
|
+
swt_widget.columns.to_a.map(&:text).map(&:underscore)
|
266
|
+
elsif @column_properties.is_a?(Hash)
|
267
|
+
@column_properties = swt_widget.columns.to_a.map(&:text).map do |column_name|
|
268
|
+
@column_properties[column_name] || column_name.underscore
|
269
|
+
end
|
270
|
+
else
|
271
|
+
@column_properties
|
272
|
+
end
|
273
|
+
end
|
274
|
+
alias column_attributes column_properties
|
261
275
|
|
262
276
|
def items
|
263
277
|
auto_exec do
|
@@ -419,8 +433,14 @@ module Glimmer
|
|
419
433
|
@editor = args
|
420
434
|
end
|
421
435
|
|
422
|
-
def cells_for(model)
|
423
|
-
|
436
|
+
def cells_for(model, table_item_property: :text)
|
437
|
+
if table_item_property.to_s == 'text'
|
438
|
+
column_properties.map {|column_property| model.send(column_property)}
|
439
|
+
else
|
440
|
+
column_properties.map do |column_property|
|
441
|
+
model.send("#{column_property}_#{table_item_property}") if model.respond_to?("#{column_property}_#{table_item_property}")
|
442
|
+
end
|
443
|
+
end
|
424
444
|
end
|
425
445
|
|
426
446
|
def cells
|
@@ -144,7 +144,7 @@ class ContactManager
|
|
144
144
|
width 200
|
145
145
|
}
|
146
146
|
|
147
|
-
items <=> [@contact_manager_presenter, :results
|
147
|
+
items <=> [@contact_manager_presenter, :results]
|
148
148
|
|
149
149
|
on_mouse_up do |event|
|
150
150
|
table_proxy.edit_table_item(event.table_item, event.column_index)
|
@@ -41,9 +41,11 @@ class Sample
|
|
41
41
|
|
42
42
|
def ensure_user_glimmer_directory
|
43
43
|
unless @ensured_glimmer_directory
|
44
|
-
|
45
|
-
|
46
|
-
|
44
|
+
Thread.new do
|
45
|
+
FileUtils.rm_rf(user_glimmer_directory)
|
46
|
+
FileUtils.cp_r(glimmer_directory, user_glimmer_directory)
|
47
|
+
@ensured_glimmer_directory = true
|
48
|
+
end
|
47
49
|
end
|
48
50
|
end
|
49
51
|
|
@@ -123,11 +125,11 @@ class Sample
|
|
123
125
|
end
|
124
126
|
|
125
127
|
def file_relative_path
|
126
|
-
file.sub(
|
128
|
+
file.sub(Sample.glimmer_directory, '')
|
127
129
|
end
|
128
130
|
|
129
131
|
def user_file
|
130
|
-
File.join(
|
132
|
+
File.join(Sample.user_glimmer_directory, file_relative_path)
|
131
133
|
end
|
132
134
|
|
133
135
|
def user_file_parent_directory
|
@@ -209,10 +211,10 @@ class SampleDirectory
|
|
209
211
|
@samples.each do |sample|
|
210
212
|
observe(sample, :selected) do |new_selected_value|
|
211
213
|
if new_selected_value
|
212
|
-
|
214
|
+
SampleDirectory.all_samples.reject {|a_sample| a_sample.name == sample.name}.each do |other_sample|
|
213
215
|
other_sample.selected = false
|
214
216
|
end
|
215
|
-
|
217
|
+
SampleDirectory.selected_sample = sample
|
216
218
|
end
|
217
219
|
end
|
218
220
|
end
|
@@ -227,8 +229,8 @@ class SampleDirectory
|
|
227
229
|
def selected_sample_name=(selected_name)
|
228
230
|
@selected_sample_name = selected_name
|
229
231
|
unless selected_name.nil?
|
230
|
-
(
|
231
|
-
|
232
|
+
(SampleDirectory.sample_directories - [self]).each { |sample_dir| sample_dir.selected_sample_name = nil }
|
233
|
+
SampleDirectory.selected_sample = samples.detect { |sample| sample.name == @selected_sample_name }
|
232
234
|
end
|
233
235
|
end
|
234
236
|
|
@@ -25,17 +25,17 @@ require 'glimmer-dsl-swt'
|
|
25
25
|
class StickFigure
|
26
26
|
include Glimmer::UI::CustomShape
|
27
27
|
|
28
|
-
options :
|
28
|
+
options :figure_x, :figure_y, :figure_width, :figure_height
|
29
29
|
|
30
30
|
before_body do
|
31
|
-
@head_width =
|
32
|
-
@head_height =
|
33
|
-
@trunk_height =
|
34
|
-
@extremity_length =
|
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(
|
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::
|
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
|
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(
|
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
|
}
|
@@ -157,19 +157,19 @@ class HelloCustomShell
|
|
157
157
|
layout_data :fill, :fill, true, true
|
158
158
|
|
159
159
|
table_column {
|
160
|
-
text 'Date
|
160
|
+
text 'Date'
|
161
161
|
width 180
|
162
162
|
}
|
163
163
|
table_column {
|
164
|
-
text 'Subject
|
164
|
+
text 'Subject'
|
165
165
|
width 180
|
166
166
|
}
|
167
167
|
table_column {
|
168
|
-
text 'From
|
168
|
+
text 'From'
|
169
169
|
width 360
|
170
170
|
}
|
171
171
|
|
172
|
-
items <=> [@email_system, :emails
|
172
|
+
items <=> [@email_system, :emails]
|
173
173
|
selection <=> [@email_system, :selected_email]
|
174
174
|
|
175
175
|
on_mouse_up do |event|
|
@@ -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
|
-
|
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,28 @@ class HelloTable
|
|
246
290
|
# default text editor is used here
|
247
291
|
}
|
248
292
|
|
249
|
-
#
|
250
|
-
|
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
|
+
# automatically inferring model attributes from column names by convention
|
306
|
+
# (e.g. 'Home Team' column assumes a `home_team` attribute on models)
|
307
|
+
#
|
308
|
+
# By convention, every inferred model attribute can be accompanied by extra
|
309
|
+
# model attributes to set extra table properties with the following suffixes:
|
310
|
+
# `_background`, `_foreground`, `_font`, and `_image`
|
311
|
+
#
|
312
|
+
# For example, for :game_date, model could also implement these related properties:
|
313
|
+
# `game_date_background`, `game_date_foreground`, `game_date_font`, `game_date_image`
|
314
|
+
items <=> [BaseballGame, :schedule]
|
251
315
|
|
252
316
|
# Data-bind table selection
|
253
317
|
selection <=> [BaseballGame, :selected_game]
|
@@ -258,22 +322,16 @@ class HelloTable
|
|
258
322
|
# Sort by these additional properties after handling sort by the column the user clicked
|
259
323
|
additional_sort_properties :date, :time, :home_team, :away_team, :ballpark, :promotion
|
260
324
|
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
on_widget_selected do
|
266
|
-
book_selected_game
|
267
|
-
end
|
268
|
-
}
|
269
|
-
}
|
325
|
+
on_key_pressed do |key_event|
|
326
|
+
book_selected_game if key_event.keyCode == swt(:cr)
|
327
|
+
end
|
270
328
|
}
|
271
329
|
|
272
330
|
button {
|
273
331
|
text 'Book Selected Game'
|
274
332
|
layout_data :center, :center, true, false
|
275
333
|
font height: 14
|
276
|
-
enabled <= [BaseballGame, :
|
334
|
+
enabled <= [BaseballGame, 'selected_game.booked', on_read: ->(value) { value == false }]
|
277
335
|
|
278
336
|
on_widget_selected do
|
279
337
|
book_selected_game
|
@@ -283,6 +341,8 @@ class HelloTable
|
|
283
341
|
}
|
284
342
|
|
285
343
|
def book_selected_game
|
344
|
+
return if BaseballGame.selected_game.booked?
|
345
|
+
|
286
346
|
message_box {
|
287
347
|
text 'Baseball Game Booked!'
|
288
348
|
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
|
4
|
+
version: 4.24.3.2
|
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-
|
11
|
+
date: 2022-09-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|