glimmer-dsl-swt 4.21.2.5 → 4.22.1.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 +212 -168
- data/README.md +15 -11
- data/VERSION +1 -1
- data/docs/reference/GLIMMER_COMMAND.md +20 -6
- data/docs/reference/GLIMMER_CONFIGURATION.md +14 -3
- data/docs/reference/GLIMMER_GIRB.md +1 -1
- data/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md +774 -132
- data/docs/reference/GLIMMER_SAMPLES.md +22 -8
- data/glimmer-dsl-swt.gemspec +0 -0
- data/lib/ext/glimmer/config.rb +41 -24
- data/lib/glimmer/data_binding/observable_widget.rb +6 -6
- data/lib/glimmer/data_binding/widget_binding.rb +4 -3
- data/lib/glimmer/dsl/swt/dsl.rb +1 -1
- data/lib/glimmer/dsl/swt/observe_expression.rb +2 -1
- data/lib/glimmer/dsl/swt/shape_expression.rb +1 -0
- data/lib/glimmer/dsl/swt/shine_data_binding_expression.rb +3 -8
- data/lib/glimmer/dsl/swt/sync_call_expression.rb +38 -0
- data/lib/glimmer/dsl/swt/transform_expression.rb +1 -1
- data/lib/glimmer/launcher.rb +16 -15
- data/lib/glimmer/rake_task/package.rb +5 -3
- data/lib/glimmer/rake_task/scaffold.rb +5 -16
- data/lib/glimmer/swt/color_proxy.rb +5 -5
- data/lib/glimmer/swt/custom/drawable.rb +8 -2
- data/lib/glimmer/swt/custom/shape/line.rb +0 -1
- data/lib/glimmer/swt/custom/shape/path.rb +2 -2
- data/lib/glimmer/swt/custom/shape/path_segment.rb +2 -2
- data/lib/glimmer/swt/custom/shape/point.rb +8 -1
- data/lib/glimmer/swt/custom/shape.rb +171 -69
- data/lib/glimmer/swt/display_proxy.rb +15 -10
- data/lib/glimmer/swt/image_proxy.rb +5 -5
- data/lib/glimmer/swt/message_box_proxy.rb +5 -5
- data/lib/glimmer/swt/shape_listener_proxy.rb +55 -0
- data/lib/glimmer/swt/shell_proxy.rb +2 -1
- data/lib/glimmer/swt/transform_proxy.rb +3 -3
- data/lib/glimmer/swt/tray_proxy.rb +4 -4
- data/lib/glimmer/swt/widget_proxy.rb +14 -10
- data/lib/glimmer/ui/custom_shape.rb +34 -10
- data/lib/glimmer/ui/custom_widget.rb +7 -10
- data/lib/glimmer-dsl-swt.rb +6 -2
- data/samples/elaborate/battleship/view/cell.rb +10 -2
- data/samples/elaborate/klondike_solitaire/model/column_pile.rb +0 -1
- data/samples/elaborate/klondike_solitaire/view/column_pile.rb +3 -16
- data/samples/elaborate/klondike_solitaire/view/dealing_pile.rb +1 -1
- data/samples/elaborate/klondike_solitaire/view/dealt_pile.rb +12 -5
- data/samples/elaborate/klondike_solitaire/view/empty_playing_card.rb +2 -1
- data/samples/elaborate/klondike_solitaire/view/foundation_pile.rb +2 -2
- data/samples/elaborate/klondike_solitaire/view/hidden_playing_card.rb +2 -2
- data/samples/elaborate/klondike_solitaire/view/klondike_solitaire_menu_bar.rb +60 -0
- data/samples/elaborate/klondike_solitaire/view/playing_card.rb +3 -2
- data/samples/elaborate/klondike_solitaire.rb +13 -55
- data/samples/elaborate/mandelbrot_fractal.rb +3 -1
- data/samples/elaborate/quarto/model/game.rb +124 -0
- data/samples/elaborate/quarto/model/piece/cube.rb +31 -0
- data/samples/elaborate/quarto/model/piece/cylinder.rb +31 -0
- data/samples/elaborate/quarto/model/piece.rb +70 -0
- data/samples/elaborate/quarto/view/available_pieces_area.rb +72 -0
- data/samples/elaborate/quarto/view/board.rb +65 -0
- data/samples/elaborate/quarto/view/cell.rb +85 -0
- data/samples/elaborate/quarto/view/cube.rb +73 -0
- data/samples/elaborate/quarto/view/cylinder.rb +72 -0
- data/samples/elaborate/quarto/view/message_box_panel.rb +114 -0
- data/samples/elaborate/quarto/view/piece.rb +56 -0
- data/samples/elaborate/quarto/view/selected_piece_area.rb +69 -0
- data/samples/elaborate/quarto.rb +188 -0
- data/samples/hello/hello_canvas_data_binding.rb +7 -7
- data/samples/hello/hello_custom_widget.rb +23 -5
- data/vendor/swt/linux/swt.jar +0 -0
- data/vendor/swt/linux_aarch64/swt.jar +0 -0
- data/vendor/swt/mac/swt.jar +0 -0
- data/vendor/swt/mac_aarch64/swt.jar +0 -0
- data/vendor/swt/windows/swt.jar +0 -0
- metadata +36 -40
- data/bin/glimmer_runner.rb +0 -4
@@ -69,6 +69,7 @@ This guide should help you get started with Glimmer DSL for SWT. For more advanc
|
|
69
69
|
- [Class-Based Custom Widget Example](#class-based-custom-widget-example)
|
70
70
|
- [Custom Widget Lifecycle Hooks](#custom-widget-lifecycle-hooks)
|
71
71
|
- [Lifecycle Hooks Example](#lifecycle-hooks-example)
|
72
|
+
- [Custom Widget Listeners](#custom-widget-listeners)
|
72
73
|
- [Custom Widget API](#custom-widget-api)
|
73
74
|
- [Content/Options Example](#contentoptions-example)
|
74
75
|
- [Custom Widget Gotchas](#custom-widget-gotchas)
|
@@ -572,6 +573,10 @@ end
|
|
572
573
|
|
573
574
|
`sync_exec {}` is required by SWT when running GUI update from a thread other than the GUI thread. In Glimmer, it is automatically invoked for you so that you wouldn't have to worry about it. It works just like `async_exec` except it executes the block synchronously at the earliest opportunity possible, waiting for the block to be finished.
|
574
575
|
|
576
|
+
##### sync_call
|
577
|
+
|
578
|
+
`sync_exec {}` is required by SWT when running GUI update from a thread other than the GUI thread. In Glimmer, it is automatically invoked for you so that you wouldn't have to worry about it. It works just like `async_exec` except it executes the block synchronously at the earliest opportunity possible, waiting for the block to be finished.
|
579
|
+
|
575
580
|
##### auto_exec
|
576
581
|
|
577
582
|
`auto_exec(override_sync_exec:, override_async_exec) {}` only executes code block with `sync_exec` when necessary (running from a thread other than the GUI thread). It is used automatically all over the Glimmer DSL for SWT codebase, so you wouldn't need it unless you grab a direct handle on `swt_widget` from a widget proxy.
|
@@ -1103,6 +1108,8 @@ shell {
|
|
1103
1108
|
}.open
|
1104
1109
|
```
|
1105
1110
|
|
1111
|
+
This relies on Glimmer's [Multi-DSL Support](#multi-dsl-support) for building the HTML text using [Glimmer XML DSL](https://github.com/AndyObtiva/glimmer-dsl-xml).
|
1112
|
+
|
1106
1113
|
Learn more at the [SWT Browser widget](https://help.eclipse.org/2020-12/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/browser/Browser.html) API.
|
1107
1114
|
|
1108
1115
|
### Widget Styles
|
@@ -1586,7 +1593,15 @@ https://help.eclipse.org/2019-12/nftopic/org.eclipse.platform.doc.isv/reference/
|
|
1586
1593
|
|
1587
1594
|
**(BETA FEATURE)**
|
1588
1595
|
|
1589
|
-
While other GUI toolkits only offer a way to draw graphics imperatively (e.g.
|
1596
|
+
While other GUI toolkits only offer a way to draw graphics imperatively (e.g. draw_arc, draw_rectangle, move_to, line_to, etc...), Glimmer DSL for SWT breaks away from the mold by enabling software engineers to draw graphics declaratively. Simply declare all the shapes you want to see with their attributes, like background/foreground colors, and Glimmer DSL for SWT takes care of the rest, painting graphics on a blank `canvas` widget or amending/decorating an existing widget. This is accomplished through the Canvas Shape DSL, a sub-DSL of the Glimmer GUI DSL, which makes it possible to draw graphics declaratively with very understandable and maintainable syntax. Still, for the rare cases where imperative logic is needed, Glimmer DSL for SWT supports imperative painting of graphics through direct usage of SWT.
|
1597
|
+
|
1598
|
+
![Canvas Shape DSL Line](/images/glimmer-canvas-shape-dsl-line.png)
|
1599
|
+
![Canvas Shape DSL Rectangle](/images/glimmer-canvas-shape-dsl-rectangle.png)
|
1600
|
+
![Canvas Shape DSL Oval](/images/glimmer-canvas-shape-dsl-oval.png)
|
1601
|
+
![Canvas Shape DSL Arc](/images/glimmer-canvas-shape-dsl-arc.png)
|
1602
|
+
![Canvas Shape DSL Polyline](/images/glimmer-canvas-shape-dsl-polyline.png)
|
1603
|
+
![Canvas Shape DSL Polygon](/images/glimmer-canvas-shape-dsl-polygon.png)
|
1604
|
+
![Canvas Shape DSL Text](/images/glimmer-canvas-shape-dsl-text.png)
|
1590
1605
|
|
1591
1606
|
`canvas` has the `:double_buffered` SWT style by default on platforms that need it (Windows & Linux) to ensure flicker-free rendering. If you need to disable it for whatever reason, just pass the `:none` SWT style instead (e.g. `canvas(:none)`)
|
1592
1607
|
|
@@ -1623,171 +1638,713 @@ Here is a list of supported attributes nestable within a block under shapes:
|
|
1623
1638
|
- `foreground` sets draw color for drawable shapes (standard color symbol (e.g. `:red`), `rgb(red_integer, green_integer, blue_integer)` color, or Color/ColorProxy object directly)
|
1624
1639
|
- `foreground_pattern` sets foreground gradient/image pattern for drawable shape lines (takes the same arguments as the SWT [Pattern](https://help.eclipse.org/2020-12/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/graphics/Pattern.html) class [e.g. `foreground_pattern 2.3, 4.2, 5.4, 7.2, :red, :blue`] / note: this feature isn't extensively tested yet)
|
1625
1640
|
- `interpolation` sets the interpolation value (SWT style value of `:default`, `:none`, `:low`, `:high`)
|
1626
|
-
- `line_cap` sets line cap (SWT style value of `:cap_flat`, `:cap_round`,
|
1641
|
+
- `line_cap` sets line cap (SWT style value of `:flat`, `:round`, or `:square`, with aliases `:cap_flat`, `:cap_round`, and `:cap_square`)
|
1627
1642
|
- `line_dash` line dash float values (automatically sets `line_style` to SWT style value of `:line_custom`)
|
1628
|
-
- `line_join` line join style (SWT style value of `:join_miter`, `:join_round`, or `:join_bevel`)
|
1643
|
+
- `line_join` line join style (SWT style value of `:miter`, `:round`, and `:bevel`, with aliases `:join_miter`, `:join_round`, or `:join_bevel`)
|
1629
1644
|
- `line_style` line join style (SWT style value of `:solid`, `:dash`, `:dot`, `:dashdot`, `:dashdotdot`, or `:custom` while requiring `line_dash` attribute (or alternatively with `line_` prefix as per official SWT docs like `:line_solid` for `:solid`)
|
1630
1645
|
- `line_width` line width in integer (used in draw operations)
|
1631
1646
|
- `text_anti_alias` enables text antialiasing (SWT style value of `:default`, `:off`, `:on` whereby `:default` applies OS default, which varies per OS)
|
1632
1647
|
- `transform` sets transform object using [Canvas Transform DSL](#canvas-transform-dsl) syntax
|
1633
1648
|
|
1649
|
+
If you specify the x and y coordinates as `:default`, `nil`, or leave them out, they get calculated automatically by centering the shape within its parent `canvas`.
|
1650
|
+
|
1651
|
+
If you specify the `width` and `height` parameters as `:max`, they get calculated from the parent's size, filling the parent maximally (and they are auto-calculated on parent resize).
|
1652
|
+
|
1653
|
+
Note that you could shift a shape off its centered position within its parent `canvas` by setting `x` to `[:default, x_delta]` and `y` to `[:default, y_delta]`
|
1654
|
+
|
1634
1655
|
Keep in mind that ordering of shapes matters as it is followed in painting. For example, it is recommended you paint filled shapes first and then drawn ones.
|
1635
1656
|
|
1636
|
-
Example (you may copy/paste in [`girb`](GLIMMER_GIRB.md)):
|
1657
|
+
Example of `line` (you may copy/paste in [`girb`](GLIMMER_GIRB.md)):
|
1637
1658
|
|
1638
1659
|
```ruby
|
1639
|
-
|
1660
|
+
require 'glimmer-dsl-swt'
|
1640
1661
|
|
1641
|
-
|
1642
|
-
image_object = image(File.expand_path('./icons/scaffold_app.png'), width: 100)
|
1662
|
+
include Glimmer
|
1643
1663
|
|
1644
1664
|
shell {
|
1645
|
-
text 'Canvas
|
1646
|
-
minimum_size
|
1647
|
-
|
1665
|
+
text 'Canvas Shape DSL'
|
1666
|
+
minimum_size 200, 220
|
1667
|
+
|
1648
1668
|
canvas {
|
1649
|
-
background :
|
1650
|
-
|
1651
|
-
|
1669
|
+
background :white
|
1670
|
+
|
1671
|
+
line(30, 30, 170, 170) {
|
1672
|
+
foreground :red
|
1673
|
+
line_width 3
|
1652
1674
|
}
|
1653
|
-
|
1675
|
+
}
|
1676
|
+
}.open
|
1677
|
+
```
|
1678
|
+
|
1679
|
+
![Canvas Shape DSL Line](/images/glimmer-canvas-shape-dsl-line.png)
|
1680
|
+
|
1681
|
+
Example of `rectangle` (you may copy/paste in [`girb`](GLIMMER_GIRB.md)):
|
1682
|
+
|
1683
|
+
```ruby
|
1684
|
+
require 'glimmer-dsl-swt'
|
1685
|
+
|
1686
|
+
include Glimmer
|
1687
|
+
|
1688
|
+
shell {
|
1689
|
+
text 'Canvas Shape DSL'
|
1690
|
+
minimum_size 200, 220
|
1691
|
+
|
1692
|
+
canvas {
|
1693
|
+
background :white
|
1694
|
+
|
1695
|
+
rectangle(30, 50, 140, 100) {
|
1654
1696
|
background :yellow
|
1655
1697
|
}
|
1656
|
-
|
1657
|
-
|
1658
|
-
foreground :
|
1698
|
+
|
1699
|
+
rectangle(30, 50, 140, 100) {
|
1700
|
+
foreground :red
|
1701
|
+
line_width 3
|
1659
1702
|
}
|
1660
|
-
|
1661
|
-
|
1703
|
+
}
|
1704
|
+
}.open
|
1705
|
+
```
|
1706
|
+
|
1707
|
+
![Canvas Shape DSL Rectangle](/images/glimmer-canvas-shape-dsl-rectangle.png)
|
1708
|
+
|
1709
|
+
Example of `rectangle` with round corners having 60 degree angles by default (you may copy/paste in [`girb`](GLIMMER_GIRB.md)):
|
1710
|
+
|
1711
|
+
```ruby
|
1712
|
+
require 'glimmer-dsl-swt'
|
1713
|
+
|
1714
|
+
include Glimmer
|
1715
|
+
|
1716
|
+
shell {
|
1717
|
+
text 'Canvas Shape DSL'
|
1718
|
+
minimum_size 200, 220
|
1719
|
+
|
1720
|
+
canvas {
|
1721
|
+
background :white
|
1722
|
+
|
1723
|
+
rectangle(30, 50, 140, 100, round: true) {
|
1724
|
+
background :yellow
|
1662
1725
|
}
|
1663
|
-
|
1664
|
-
|
1726
|
+
|
1727
|
+
rectangle(30, 50, 140, 100, round: true) {
|
1728
|
+
foreground :red
|
1665
1729
|
line_width 3
|
1666
1730
|
}
|
1667
|
-
image(image_object, 70, 50)
|
1668
1731
|
}
|
1669
1732
|
}.open
|
1670
1733
|
```
|
1671
1734
|
|
1672
|
-
|
1735
|
+
![Canvas Shape DSL Rectangle Round](/images/glimmer-canvas-shape-dsl-rectangle-round.png)
|
1673
1736
|
|
1674
|
-
|
1737
|
+
Example of `rectangle` with round corners having different horizontal and vertical angles (you may copy/paste in [`girb`](GLIMMER_GIRB.md)):
|
1675
1738
|
|
1676
|
-
|
1739
|
+
```ruby
|
1740
|
+
require 'glimmer-dsl-swt'
|
1677
1741
|
|
1678
|
-
|
1742
|
+
include Glimmer
|
1679
1743
|
|
1680
|
-
|
1744
|
+
shell {
|
1745
|
+
text 'Canvas Shape DSL'
|
1746
|
+
minimum_size 200, 220
|
1747
|
+
|
1748
|
+
canvas {
|
1749
|
+
background :white
|
1750
|
+
|
1751
|
+
rectangle(30, 50, 140, 100, 40, 80) {
|
1752
|
+
background :yellow
|
1753
|
+
}
|
1754
|
+
|
1755
|
+
rectangle(30, 50, 140, 100, 40, 80) {
|
1756
|
+
foreground :red
|
1757
|
+
line_width 3
|
1758
|
+
}
|
1759
|
+
}
|
1760
|
+
}.open
|
1761
|
+
```
|
1681
1762
|
|
1682
|
-
|
1763
|
+
![Canvas Shape DSL Rectangle Round Angles](/images/glimmer-canvas-shape-dsl-rectangle-round-angles.png)
|
1683
1764
|
|
1684
|
-
Example (you may copy/paste in [`girb`](GLIMMER_GIRB.md)):
|
1765
|
+
Example of `oval` (you may copy/paste in [`girb`](GLIMMER_GIRB.md)):
|
1685
1766
|
|
1686
1767
|
```ruby
|
1687
|
-
|
1768
|
+
require 'glimmer-dsl-swt'
|
1688
1769
|
|
1689
|
-
|
1690
|
-
image_object = image(File.expand_path('./icons/scaffold_app.png'), width: 100)
|
1770
|
+
include Glimmer
|
1691
1771
|
|
1692
1772
|
shell {
|
1693
|
-
text 'Canvas
|
1694
|
-
minimum_size
|
1695
|
-
|
1773
|
+
text 'Canvas Shape DSL'
|
1774
|
+
minimum_size 200, 220
|
1775
|
+
|
1696
1776
|
canvas {
|
1697
|
-
background :
|
1698
|
-
|
1699
|
-
|
1777
|
+
background :white
|
1778
|
+
|
1779
|
+
oval(30, 50, 140, 100) {
|
1780
|
+
background :yellow
|
1781
|
+
}
|
1782
|
+
|
1783
|
+
oval(30, 50, 140, 100) {
|
1784
|
+
foreground :red
|
1785
|
+
line_width 3
|
1700
1786
|
}
|
1701
|
-
|
1787
|
+
}
|
1788
|
+
}.open
|
1789
|
+
```
|
1790
|
+
|
1791
|
+
![Canvas Shape DSL Oval](/images/glimmer-canvas-shape-dsl-oval.png)
|
1792
|
+
|
1793
|
+
Example of `arc` (you may copy/paste in [`girb`](GLIMMER_GIRB.md)):
|
1794
|
+
|
1795
|
+
```ruby
|
1796
|
+
require 'glimmer-dsl-swt'
|
1797
|
+
|
1798
|
+
include Glimmer
|
1799
|
+
|
1800
|
+
shell {
|
1801
|
+
text 'Canvas Shape DSL'
|
1802
|
+
minimum_size 200, 220
|
1803
|
+
|
1804
|
+
canvas {
|
1805
|
+
background :white
|
1806
|
+
|
1807
|
+
arc(30, 30, 140, 140, 0, 270) {
|
1702
1808
|
background :yellow
|
1703
1809
|
}
|
1704
|
-
|
1705
|
-
|
1706
|
-
foreground :
|
1810
|
+
|
1811
|
+
arc(30, 30, 140, 140, 0, 270) {
|
1812
|
+
foreground :red
|
1813
|
+
line_width 3
|
1707
1814
|
}
|
1708
|
-
|
1709
|
-
|
1815
|
+
}
|
1816
|
+
}.open
|
1817
|
+
```
|
1818
|
+
|
1819
|
+
![Canvas Shape DSL Arc](/images/glimmer-canvas-shape-dsl-arc.png)
|
1820
|
+
|
1821
|
+
Example of `polyline` (you may copy/paste in [`girb`](GLIMMER_GIRB.md)):
|
1822
|
+
|
1823
|
+
```ruby
|
1824
|
+
require 'glimmer-dsl-swt'
|
1825
|
+
|
1826
|
+
include Glimmer
|
1827
|
+
|
1828
|
+
shell {
|
1829
|
+
text 'Canvas Shape DSL'
|
1830
|
+
minimum_size 200, 220
|
1831
|
+
|
1832
|
+
canvas {
|
1833
|
+
background :white
|
1834
|
+
|
1835
|
+
polyline(30, 50, 50, 170, 70, 120, 90, 150, 110, 30, 130, 100, 150, 50, 170, 135) {
|
1836
|
+
foreground :red
|
1837
|
+
line_width 3
|
1838
|
+
}
|
1839
|
+
}
|
1840
|
+
}.open
|
1841
|
+
```
|
1842
|
+
|
1843
|
+
![Canvas Shape DSL Polyline](/images/glimmer-canvas-shape-dsl-polyline.png)
|
1844
|
+
|
1845
|
+
Example of `polygon` (you may copy/paste in [`girb`](GLIMMER_GIRB.md)):
|
1846
|
+
|
1847
|
+
```ruby
|
1848
|
+
require 'glimmer-dsl-swt'
|
1849
|
+
|
1850
|
+
include Glimmer
|
1851
|
+
|
1852
|
+
shell {
|
1853
|
+
text 'Canvas Shape DSL'
|
1854
|
+
minimum_size 200, 220
|
1855
|
+
|
1856
|
+
canvas {
|
1857
|
+
background :white
|
1858
|
+
|
1859
|
+
polygon(30, 90, 80, 20, 130, 40, 170, 90, 130, 140, 80, 170, 40, 160) {
|
1860
|
+
background :yellow
|
1710
1861
|
}
|
1711
|
-
|
1712
|
-
|
1862
|
+
|
1863
|
+
polygon(30, 90, 80, 20, 130, 40, 170, 90, 130, 140, 80, 170, 40, 160) {
|
1864
|
+
foreground :red
|
1713
1865
|
line_width 3
|
1714
1866
|
}
|
1715
|
-
image(image_object, 70, 50)
|
1716
1867
|
}
|
1717
1868
|
}.open
|
1718
1869
|
```
|
1719
1870
|
|
1720
|
-
|
1871
|
+
![Canvas Shape DSL Polygon](/images/glimmer-canvas-shape-dsl-polygon.png)
|
1721
1872
|
|
1722
|
-
|
1873
|
+
Example of `text` (you may copy/paste in [`girb`](GLIMMER_GIRB.md)):
|
1723
1874
|
|
1724
|
-
|
1875
|
+
```ruby
|
1876
|
+
require 'glimmer-dsl-swt'
|
1877
|
+
|
1878
|
+
include Glimmer
|
1879
|
+
|
1880
|
+
shell {
|
1881
|
+
text 'Canvas Shape DSL'
|
1882
|
+
minimum_size 200, 220
|
1883
|
+
|
1884
|
+
canvas {
|
1885
|
+
background :white
|
1886
|
+
|
1887
|
+
text(" This is \n rendered text ", 30, 50) {
|
1888
|
+
background :yellow
|
1889
|
+
foreground :red
|
1890
|
+
font height: 25, style: :italic
|
1891
|
+
|
1892
|
+
rectangle { # automatically scales to match text extent
|
1893
|
+
foreground :red
|
1894
|
+
line_width 3
|
1895
|
+
}
|
1896
|
+
}
|
1897
|
+
}
|
1898
|
+
}.open
|
1899
|
+
```
|
1900
|
+
|
1901
|
+
![Canvas Shape DSL Text](/images/glimmer-canvas-shape-dsl-text.png)
|
1902
|
+
|
1903
|
+
Example of `image` (you may copy/paste in [`girb`](GLIMMER_GIRB.md)):
|
1725
1904
|
|
1726
1905
|
```ruby
|
1906
|
+
require 'glimmer-dsl-swt'
|
1907
|
+
|
1727
1908
|
include Glimmer
|
1728
1909
|
|
1729
|
-
|
1730
|
-
|
1910
|
+
shell {
|
1911
|
+
text 'Canvas Shape DSL'
|
1912
|
+
minimum_size 512, 542
|
1913
|
+
|
1914
|
+
canvas {
|
1915
|
+
background :white
|
1916
|
+
|
1917
|
+
image(File.expand_path('icons/scaffold_app.png', __dir__), 0, 5)
|
1918
|
+
}
|
1919
|
+
}.open
|
1920
|
+
```
|
1921
|
+
|
1922
|
+
![Canvas Shape DSL Image](/images/glimmer-canvas-shape-dsl-image.png)
|
1923
|
+
|
1924
|
+
Example of `image` pre-built with a smaller height (you may copy/paste in [`girb`](GLIMMER_GIRB.md)):
|
1925
|
+
|
1926
|
+
```ruby
|
1927
|
+
require 'glimmer-dsl-swt'
|
1928
|
+
|
1929
|
+
include Glimmer
|
1930
|
+
|
1931
|
+
@image_object = image(File.expand_path('icons/scaffold_app.png', __dir__), height: 200)
|
1731
1932
|
|
1732
1933
|
shell {
|
1733
|
-
text 'Canvas
|
1734
|
-
minimum_size
|
1934
|
+
text 'Canvas Shape DSL'
|
1935
|
+
minimum_size 200, 230
|
1936
|
+
|
1937
|
+
canvas {
|
1938
|
+
background :white
|
1939
|
+
|
1940
|
+
image(@image_object, 0, 5)
|
1941
|
+
}
|
1942
|
+
}.open
|
1943
|
+
```
|
1944
|
+
|
1945
|
+
![Canvas Shape DSL Image](/images/glimmer-canvas-shape-dsl-image-shrunk.png)
|
1946
|
+
|
1947
|
+
Example of setting `background_pattern` attribute to a horizontal gradient (you may copy/paste in [`girb`](GLIMMER_GIRB.md)):
|
1948
|
+
|
1949
|
+
```ruby
|
1950
|
+
require 'glimmer-dsl-swt'
|
1951
|
+
|
1952
|
+
include Glimmer
|
1735
1953
|
|
1954
|
+
shell {
|
1955
|
+
text 'Canvas Shape DSL'
|
1956
|
+
minimum_size 200, 220
|
1957
|
+
|
1736
1958
|
canvas {
|
1737
|
-
background :
|
1738
|
-
|
1739
|
-
|
1740
|
-
|
1741
|
-
width 220
|
1742
|
-
height 400
|
1743
|
-
background :dark_red
|
1959
|
+
background :white
|
1960
|
+
|
1961
|
+
oval(30, 30, 140, 140) {
|
1962
|
+
background_pattern 0, 0, 200, 0, rgb(255, 255, 0), rgb(255, 0, 0)
|
1744
1963
|
}
|
1745
|
-
|
1746
|
-
|
1747
|
-
|
1748
|
-
|
1749
|
-
|
1750
|
-
|
1751
|
-
|
1964
|
+
}
|
1965
|
+
}.open
|
1966
|
+
```
|
1967
|
+
|
1968
|
+
![Canvas Shape DSL Oval Background Pattern Gradient](/images/glimmer-canvas-shape-dsl-oval-background-pattern-gradient.png)
|
1969
|
+
|
1970
|
+
Example of setting `foreground_pattern` attribute to a vertical gradient (you may copy/paste in [`girb`](GLIMMER_GIRB.md)):
|
1971
|
+
|
1972
|
+
```ruby
|
1973
|
+
require 'glimmer-dsl-swt'
|
1974
|
+
|
1975
|
+
include Glimmer
|
1976
|
+
|
1977
|
+
shell {
|
1978
|
+
text 'Canvas Shape DSL'
|
1979
|
+
minimum_size 200, 220
|
1980
|
+
|
1981
|
+
canvas {
|
1982
|
+
background :white
|
1983
|
+
|
1984
|
+
oval(30, 30, 140, 140) {
|
1985
|
+
foreground_pattern 0, 0, 0, 200, :blue, :green
|
1986
|
+
line_width 10
|
1987
|
+
}
|
1988
|
+
}
|
1989
|
+
}.open
|
1990
|
+
```
|
1991
|
+
|
1992
|
+
![Canvas Shape DSL Oval Foreground Pattern Gradient](/images/glimmer-canvas-shape-dsl-oval-foreground-pattern-gradient.png)
|
1993
|
+
|
1994
|
+
Example of setting `line_style` attribute to `:dashdot` (you may copy/paste in [`girb`](GLIMMER_GIRB.md)):
|
1995
|
+
|
1996
|
+
```ruby
|
1997
|
+
require 'glimmer-dsl-swt'
|
1998
|
+
|
1999
|
+
include Glimmer
|
2000
|
+
|
2001
|
+
shell {
|
2002
|
+
text 'Canvas Shape DSL'
|
2003
|
+
minimum_size 200, 220
|
2004
|
+
|
2005
|
+
canvas {
|
2006
|
+
background :white
|
2007
|
+
|
2008
|
+
oval(30, 50, 140, 100) {
|
1752
2009
|
background :yellow
|
1753
2010
|
}
|
1754
|
-
|
1755
|
-
|
1756
|
-
|
1757
|
-
|
1758
|
-
|
1759
|
-
vertical true
|
1760
|
-
background :dark_red
|
1761
|
-
foreground :yellow
|
2011
|
+
|
2012
|
+
oval(30, 50, 140, 100) {
|
2013
|
+
foreground :red
|
2014
|
+
line_width 3
|
2015
|
+
line_style :dashdot
|
1762
2016
|
}
|
1763
|
-
|
1764
|
-
|
1765
|
-
|
1766
|
-
|
1767
|
-
|
2017
|
+
}
|
2018
|
+
}.open
|
2019
|
+
```
|
2020
|
+
|
2021
|
+
![Canvas Shape DSL Oval](/images/glimmer-canvas-shape-dsl-oval-line-style-dashdot.png)
|
2022
|
+
|
2023
|
+
Example of setting `line_width` attribute to `10`, `line_join` attribute to `:miter` (default) and `line_cap` attribute to `:flat` (default) (you may copy/paste in [`girb`](GLIMMER_GIRB.md)):
|
2024
|
+
|
2025
|
+
```ruby
|
2026
|
+
require 'glimmer-dsl-swt'
|
2027
|
+
|
2028
|
+
include Glimmer
|
2029
|
+
|
2030
|
+
shell {
|
2031
|
+
text 'Canvas Shape DSL'
|
2032
|
+
minimum_size 200, 220
|
2033
|
+
|
2034
|
+
canvas {
|
2035
|
+
background :white
|
2036
|
+
|
2037
|
+
polyline(30, 50, 50, 170, 70, 120, 90, 150, 110, 30, 130, 100, 150, 50, 170, 135) {
|
2038
|
+
foreground :red
|
2039
|
+
line_width 10
|
2040
|
+
line_join :miter
|
2041
|
+
line_cap :flat
|
1768
2042
|
}
|
2043
|
+
}
|
2044
|
+
}.open
|
2045
|
+
```
|
2046
|
+
|
2047
|
+
![Canvas Shape DSL Polyline Line Join Miter Line Cap Flat](/images/glimmer-canvas-shape-dsl-polyline-line-join-miter-line-cap-flat.png)
|
2048
|
+
|
2049
|
+
Example of setting `line_width` attribute to `10`, `line_join` attribute to `:round` and `line_cap` attribute to `:round` (you may copy/paste in [`girb`](GLIMMER_GIRB.md)):
|
2050
|
+
|
2051
|
+
```ruby
|
2052
|
+
require 'glimmer-dsl-swt'
|
2053
|
+
|
2054
|
+
include Glimmer
|
2055
|
+
|
2056
|
+
shell {
|
2057
|
+
text 'Canvas Shape DSL'
|
2058
|
+
minimum_size 200, 220
|
2059
|
+
|
2060
|
+
canvas {
|
2061
|
+
background :white
|
2062
|
+
|
2063
|
+
polyline(30, 50, 50, 170, 70, 120, 90, 150, 110, 30, 130, 100, 150, 50, 170, 135) {
|
2064
|
+
foreground :red
|
2065
|
+
line_width 10
|
2066
|
+
line_join :round
|
2067
|
+
line_cap :round
|
2068
|
+
}
|
2069
|
+
}
|
2070
|
+
}.open
|
2071
|
+
```
|
2072
|
+
|
2073
|
+
![Canvas Shape DSL Polyline Line Join Round Line Cap Round](/images/glimmer-canvas-shape-dsl-polyline-line-join-round-line-cap-round.png)
|
2074
|
+
|
2075
|
+
Example of setting `line_width` attribute to `10`, `line_join` attribute to `:bevel` and `line_cap` attribute to `:square` (you may copy/paste in [`girb`](GLIMMER_GIRB.md)):
|
2076
|
+
|
2077
|
+
```ruby
|
2078
|
+
require 'glimmer-dsl-swt'
|
2079
|
+
|
2080
|
+
include Glimmer
|
2081
|
+
|
2082
|
+
shell {
|
2083
|
+
text 'Canvas Shape DSL'
|
2084
|
+
minimum_size 200, 220
|
2085
|
+
|
2086
|
+
canvas {
|
2087
|
+
background :white
|
2088
|
+
|
2089
|
+
polyline(30, 50, 50, 170, 70, 120, 90, 150, 110, 30, 130, 100, 150, 50, 170, 135) {
|
2090
|
+
foreground :red
|
2091
|
+
line_width 10
|
2092
|
+
line_join :bevel
|
2093
|
+
line_cap :square
|
2094
|
+
}
|
2095
|
+
}
|
2096
|
+
}.open
|
2097
|
+
```
|
2098
|
+
|
2099
|
+
![Canvas Shape DSL Polyline Line Join Miter Line Cap Flat](/images/glimmer-canvas-shape-dsl-polyline-line-join-bevel-line-cap-square.png)
|
2100
|
+
|
2101
|
+
Shape declaration parameters perfectly match the method parameters in the [SWT org.eclipse.swt.graphics.GC API](https://help.eclipse.org/2020-12/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/graphics/GC.html). This is useful for developers coming to Glimmer DSL for SWT from SWT.
|
2102
|
+
|
2103
|
+
Glimmer DSL for SWT also supports an alternative syntax for specifying shape parameters by nesting underneath the shape instead of passing as args. This syntax in fact offers the extra-benefit of [data-binding](#data-binding) for shape parameter values (meaning you could use `<=` syntax with them instead of setting values directly)
|
2104
|
+
|
2105
|
+
Example of alternative syntax for specifying shape parameters (you may copy/paste in [`girb`](GLIMMER_GIRB.md)):
|
2106
|
+
|
2107
|
+
```ruby
|
2108
|
+
require 'glimmer-dsl-swt'
|
2109
|
+
|
2110
|
+
include Glimmer
|
2111
|
+
|
2112
|
+
shell {
|
2113
|
+
text 'Canvas Shape DSL'
|
2114
|
+
minimum_size 200, 220
|
2115
|
+
|
2116
|
+
canvas {
|
2117
|
+
background :white
|
2118
|
+
|
1769
2119
|
rectangle {
|
1770
|
-
x
|
1771
|
-
y
|
1772
|
-
width
|
1773
|
-
height
|
1774
|
-
|
1775
|
-
|
2120
|
+
x 30
|
2121
|
+
y 50
|
2122
|
+
width 140
|
2123
|
+
height 100
|
2124
|
+
arc_width 40
|
2125
|
+
arc_height 80
|
2126
|
+
background :yellow
|
1776
2127
|
}
|
1777
|
-
|
1778
|
-
|
1779
|
-
x
|
2128
|
+
|
2129
|
+
rectangle {
|
2130
|
+
x 30
|
1780
2131
|
y 50
|
2132
|
+
width 140
|
2133
|
+
height 100
|
2134
|
+
arc_width 40
|
2135
|
+
arc_height 80
|
2136
|
+
foreground :red
|
2137
|
+
line_width 3
|
1781
2138
|
}
|
1782
2139
|
}
|
1783
2140
|
}.open
|
1784
2141
|
```
|
1785
2142
|
|
1786
|
-
|
2143
|
+
![Canvas Shape DSL Rectangle Round Angles](/images/glimmer-canvas-shape-dsl-rectangle-round-angles.png)
|
1787
2144
|
|
1788
|
-
|
2145
|
+
Example of canvas shape parameter data-binding (you may copy/paste in [`girb`](GLIMMER_GIRB.md)):
|
1789
2146
|
|
1790
|
-
|
2147
|
+
```ruby
|
2148
|
+
require 'glimmer-dsl-swt'
|
2149
|
+
|
2150
|
+
class HelloCanvasDataBinding
|
2151
|
+
include Glimmer::GUI::CustomWindow # alias for Glimmer::UI::CustomShell
|
2152
|
+
|
2153
|
+
CANVAS_WIDTH = 300
|
2154
|
+
CANVAS_HEIGHT = 300
|
2155
|
+
|
2156
|
+
attr_accessor :x1_value, :y1_value, :x2_value, :y2_value, :foreground_red, :foreground_green, :foreground_blue, :line_width_value, :line_style_value
|
2157
|
+
|
2158
|
+
def foreground_value
|
2159
|
+
rgb(foreground_red, foreground_green, foreground_blue)
|
2160
|
+
end
|
2161
|
+
|
2162
|
+
def line_style_value_options
|
2163
|
+
[:solid, :dash, :dot, :dashdot, :dashdotdot]
|
2164
|
+
end
|
2165
|
+
|
2166
|
+
before_body do
|
2167
|
+
self.x1_value = 0
|
2168
|
+
self.y1_value = 0
|
2169
|
+
self.x2_value = CANVAS_WIDTH
|
2170
|
+
self.y2_value = CANVAS_HEIGHT
|
2171
|
+
self.foreground_red = 28
|
2172
|
+
self.foreground_green = 128
|
2173
|
+
self.foreground_blue = 228
|
2174
|
+
self.line_width_value = 3
|
2175
|
+
self.line_style_value = :dot
|
2176
|
+
end
|
2177
|
+
|
2178
|
+
body {
|
2179
|
+
shell {
|
2180
|
+
text 'Hello, Canvas Data-Binding!'
|
2181
|
+
|
2182
|
+
tab_folder {
|
2183
|
+
tab_item {
|
2184
|
+
grid_layout(6, true) {
|
2185
|
+
margin_width 0
|
2186
|
+
margin_height 0
|
2187
|
+
horizontal_spacing 0
|
2188
|
+
vertical_spacing 0
|
2189
|
+
}
|
2190
|
+
text 'line'
|
2191
|
+
|
2192
|
+
label {
|
2193
|
+
layout_data(:fill, :center, false, false) {
|
2194
|
+
horizontal_span 3
|
2195
|
+
}
|
2196
|
+
text 'x1'
|
2197
|
+
}
|
2198
|
+
label {
|
2199
|
+
layout_data(:fill, :center, false, false) {
|
2200
|
+
horizontal_span 3
|
2201
|
+
}
|
2202
|
+
text 'y1'
|
2203
|
+
}
|
2204
|
+
spinner {
|
2205
|
+
layout_data(:fill, :center, false, false) {
|
2206
|
+
horizontal_span 3
|
2207
|
+
}
|
2208
|
+
maximum CANVAS_WIDTH
|
2209
|
+
increment 3
|
2210
|
+
selection <=> [self, :x1_value]
|
2211
|
+
}
|
2212
|
+
spinner {
|
2213
|
+
layout_data(:fill, :center, false, false) {
|
2214
|
+
horizontal_span 3
|
2215
|
+
}
|
2216
|
+
maximum CANVAS_HEIGHT
|
2217
|
+
increment 3
|
2218
|
+
selection <=> [self, :y1_value]
|
2219
|
+
}
|
2220
|
+
label {
|
2221
|
+
layout_data(:fill, :center, false, false) {
|
2222
|
+
horizontal_span 3
|
2223
|
+
}
|
2224
|
+
text 'x2'
|
2225
|
+
}
|
2226
|
+
label {
|
2227
|
+
layout_data(:fill, :center, false, false) {
|
2228
|
+
horizontal_span 3
|
2229
|
+
}
|
2230
|
+
text 'y2'
|
2231
|
+
}
|
2232
|
+
spinner {
|
2233
|
+
layout_data(:fill, :center, false, false) {
|
2234
|
+
horizontal_span 3
|
2235
|
+
}
|
2236
|
+
maximum CANVAS_WIDTH
|
2237
|
+
increment 3
|
2238
|
+
selection <=> [self, :x2_value]
|
2239
|
+
}
|
2240
|
+
spinner {
|
2241
|
+
layout_data(:fill, :center, false, false) {
|
2242
|
+
horizontal_span 3
|
2243
|
+
}
|
2244
|
+
maximum CANVAS_HEIGHT
|
2245
|
+
increment 3
|
2246
|
+
selection <=> [self, :y2_value]
|
2247
|
+
}
|
2248
|
+
label {
|
2249
|
+
layout_data(:fill, :center, false, false) {
|
2250
|
+
horizontal_span 2
|
2251
|
+
}
|
2252
|
+
text 'foreground red'
|
2253
|
+
}
|
2254
|
+
label {
|
2255
|
+
layout_data(:fill, :center, false, false) {
|
2256
|
+
horizontal_span 2
|
2257
|
+
}
|
2258
|
+
text 'foreground green'
|
2259
|
+
}
|
2260
|
+
label {
|
2261
|
+
layout_data(:fill, :center, false, false) {
|
2262
|
+
horizontal_span 2
|
2263
|
+
}
|
2264
|
+
text 'foreground blue'
|
2265
|
+
}
|
2266
|
+
spinner {
|
2267
|
+
layout_data(:fill, :center, false, false) {
|
2268
|
+
horizontal_span 2
|
2269
|
+
}
|
2270
|
+
maximum 255
|
2271
|
+
increment 10
|
2272
|
+
selection <=> [self, :foreground_red]
|
2273
|
+
}
|
2274
|
+
spinner {
|
2275
|
+
layout_data(:fill, :center, false, false) {
|
2276
|
+
horizontal_span 2
|
2277
|
+
}
|
2278
|
+
maximum 255
|
2279
|
+
increment 10
|
2280
|
+
selection <=> [self, :foreground_green]
|
2281
|
+
}
|
2282
|
+
spinner {
|
2283
|
+
layout_data(:fill, :center, false, false) {
|
2284
|
+
horizontal_span 2
|
2285
|
+
}
|
2286
|
+
maximum 255
|
2287
|
+
increment 10
|
2288
|
+
selection <=> [self, :foreground_blue]
|
2289
|
+
}
|
2290
|
+
label {
|
2291
|
+
layout_data(:fill, :center, false, false) {
|
2292
|
+
horizontal_span 3
|
2293
|
+
}
|
2294
|
+
text 'line width'
|
2295
|
+
}
|
2296
|
+
label {
|
2297
|
+
layout_data(:fill, :center, false, false) {
|
2298
|
+
horizontal_span 3
|
2299
|
+
}
|
2300
|
+
text 'line style'
|
2301
|
+
}
|
2302
|
+
spinner {
|
2303
|
+
layout_data(:fill, :center, false, false) {
|
2304
|
+
horizontal_span 3
|
2305
|
+
}
|
2306
|
+
maximum 255
|
2307
|
+
selection <=> [self, :line_width_value]
|
2308
|
+
}
|
2309
|
+
combo(:read_only) {
|
2310
|
+
layout_data(:fill, :center, false, false) {
|
2311
|
+
horizontal_span 3
|
2312
|
+
}
|
2313
|
+
selection <=> [self, :line_style_value]
|
2314
|
+
}
|
2315
|
+
canvas {
|
2316
|
+
layout_data(:center, :center, false, false) {
|
2317
|
+
horizontal_span 6
|
2318
|
+
width_hint CANVAS_WIDTH
|
2319
|
+
height_hint CANVAS_WIDTH
|
2320
|
+
}
|
2321
|
+
background :white
|
2322
|
+
|
2323
|
+
line {
|
2324
|
+
x1 <= [self, :x1_value]
|
2325
|
+
y1 <= [self, :y1_value]
|
2326
|
+
x2 <= [self, :x2_value]
|
2327
|
+
y2 <= [self, :y2_value]
|
2328
|
+
foreground <= [self, :foreground_value, computed_by: [:foreground_red, :foreground_green, :foreground_blue]]
|
2329
|
+
line_width <= [self, :line_width_value]
|
2330
|
+
line_style <= [self, :line_style_value]
|
2331
|
+
}
|
2332
|
+
}
|
2333
|
+
}
|
2334
|
+
}
|
2335
|
+
}
|
2336
|
+
}
|
2337
|
+
|
2338
|
+
end
|
2339
|
+
|
2340
|
+
HelloCanvasDataBinding.launch
|
2341
|
+
```
|
2342
|
+
|
2343
|
+
![Glimmer Example Canvas Data-Binding Line Changed](/images/glimmer-hello-canvas-data-binding-line-changed.png)
|
2344
|
+
|
2345
|
+
If you ever have special needs for optimization, you could always default to direct SWT painting via [org.eclipse.swt.graphics.GC](https://help.eclipse.org/2020-12/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/graphics/GC.html) instead. Learn more at the [SWT Graphics Guide](https://www.eclipse.org/articles/Article-SWT-graphics/SWT_graphics.html) and [SWT Image Guide](https://www.eclipse.org/articles/Article-SWT-images/graphics-resources.html#Saving%20Images).
|
2346
|
+
|
2347
|
+
Example of manual drawing without relying on the declarative Glimmer Shape DSL (you may copy/paste in [`girb`](GLIMMER_GIRB.md)):
|
1791
2348
|
|
1792
2349
|
```ruby
|
1793
2350
|
include Glimmer
|
@@ -1828,6 +2385,8 @@ shell {
|
|
1828
2385
|
}.open
|
1829
2386
|
```
|
1830
2387
|
|
2388
|
+
![Glimmer Example Canvas](/images/glimmer-example-canvas.png)
|
2389
|
+
|
1831
2390
|
#### Shapes inside a Shape
|
1832
2391
|
|
1833
2392
|
Shapes can be nested within each other. If you nest a shape within another, its coordinates are assumed to be relative to its parent.
|
@@ -2408,59 +2967,67 @@ The [Glimmer Tetris](/docs/reference/GLIMMER_SAMPLES.md#tetris) sample provides
|
|
2408
2967
|
|
2409
2968
|
### Data-Binding
|
2410
2969
|
|
2411
|
-
Data-binding is done with `bind`
|
2970
|
+
Data-binding is done with either the [Shine](#shine) syntax `<=>` (bidirectional data-binding) & `<=` (unidirectional data-binding) or via the `bind` keyword, following widget property to bind and taking model and bindable attribute as arguments.
|
2412
2971
|
|
2413
2972
|
#### General Examples
|
2414
2973
|
|
2974
|
+
`text <=> [contact, :first_name]`
|
2975
|
+
|
2976
|
+
This example binds the text property of a widget like `label` to the first name of a contact model using Shine data-binding syntax (recommended).
|
2977
|
+
|
2415
2978
|
`text bind(contact, :first_name)`
|
2416
2979
|
|
2417
|
-
This example binds the text property of a widget like `label` to the first name of a contact model.
|
2980
|
+
This example binds the text property of a widget like `label` to the first name of a contact model (older style of data-binding, not recommended).
|
2418
2981
|
|
2419
|
-
`text
|
2982
|
+
`text <=> [contact, 'address.street']`
|
2420
2983
|
|
2421
2984
|
This example binds the text property of a widget like `label` to the nested street of
|
2422
2985
|
the address of a contact. This is called nested property data binding.
|
2423
2986
|
|
2424
|
-
`text
|
2987
|
+
`text <=> [contact, 'address.street', on_read: :upcase, on_write: :downcase]`
|
2425
2988
|
|
2426
2989
|
This example adds on the one above it by specifying converters on read and write of the model property, like in the case of a `text` widget. The text widget will then displays the street upper case and the model will store it lower case. When specifying converters, read and write operations must be symmetric (to avoid an infinite update loop between the widget and the model since the widget checks first if value changed before updating)
|
2427
2990
|
|
2428
|
-
`text
|
2429
|
-
|
2430
|
-
This example forces GUI updates via [sync_exec](#sync_exec) assuming they are coming from another thread (different from the GUI thread)
|
2431
|
-
|
2432
|
-
`text bind(contact, 'address.street', async_exec: true)`
|
2433
|
-
|
2434
|
-
This example forces GUI updates via [async_exec](#async_exec) assuming they are coming from another thread (different from the GUI thread)
|
2435
|
-
|
2436
|
-
`text bind(contact, 'address.street', on_read: lambda { |s| s[0..10] })`
|
2991
|
+
`text <=> [contact, 'address.street', on_read: ->(s) { s[0..10] }]`
|
2437
2992
|
|
2438
2993
|
This example also specifies a converter on read of the model property, but via a lambda, which truncates the street to 10 characters only. Note that the read and write operations are assymetric. This is fine in the case of formatting data for a read-only widget like `label`
|
2439
2994
|
|
2440
2995
|
`text bind(contact, 'address.street') { |s| s[0..10] }`
|
2441
2996
|
|
2442
|
-
This is a block shortcut version of the syntax above it. It facilitates formatting model data for read-only widgets since it's a very common view concern. It also saves the developer from having to create a separate formatter/presenter for the model when the view can be an active view that handles common simple formatting operations directly.
|
2997
|
+
This is a block shortcut version of the syntax above it. It facilitates formatting model data for read-only widgets since it's a very common view concern. It also saves the developer from having to create a separate formatter/presenter for the model when the view can be an active view that handles common simple formatting operations directly (older style of data-binding, not recommended).
|
2443
2998
|
|
2444
|
-
`text
|
2999
|
+
`text <= [contact, 'address.street']`
|
2445
3000
|
|
2446
3001
|
This is read-ohly data-binding. It doesn't update contact.address.street when widget text property is changed.
|
2447
3002
|
|
2448
|
-
`text bind(contact, '
|
3003
|
+
`text bind(contact, 'address.street', read_only: true)`
|
3004
|
+
|
3005
|
+
This is read-ohly data-binding. It doesn't update contact.address.street when widget text property is changed (older style of data-binding, not recommended).
|
3006
|
+
|
3007
|
+
`text <=> [contact, 'addresses[1].street']`
|
2449
3008
|
|
2450
3009
|
This example binds the text property of a widget like `label` to the nested indexed address street of a contact. This is called nested indexed property data binding.
|
2451
3010
|
|
2452
|
-
`text
|
3011
|
+
`text <=> [contact, :age, computed_by: :date_of_birth]`
|
2453
3012
|
|
2454
3013
|
This example demonstrates computed value data binding whereby the value of `age` depends on changes to `date_of_birth`.
|
2455
3014
|
|
2456
|
-
`text
|
3015
|
+
`text <=> [contact, :name, computed_by: [:first_name, :last_name]]`
|
2457
3016
|
|
2458
3017
|
This example demonstrates computed value data binding whereby the value of `name` depends on changes to both `first_name` and `last_name`.
|
2459
3018
|
|
2460
|
-
`text
|
3019
|
+
`text <=> [contact, 'profiles[0].name', computed_by: ['profiles[0].first_name', 'profiles[0].last_name']]`
|
2461
3020
|
|
2462
3021
|
This example demonstrates nested indexed computed value data binding whereby the value of `profiles[0].name` depends on changes to both nested `profiles[0].first_name` and `profiles[0].last_name`.
|
2463
3022
|
|
3023
|
+
`text <=> [contact, 'address.street', sync_exec: true]`
|
3024
|
+
|
3025
|
+
This example forces GUI updates via [sync_exec](#sync_exec) assuming they are coming from another thread (different from the GUI thread)
|
3026
|
+
|
3027
|
+
`text <=> [contact, 'address.street', async_exec: true]`
|
3028
|
+
|
3029
|
+
This example forces GUI updates via [async_exec](#async_exec) assuming they are coming from another thread (different from the GUI thread)
|
3030
|
+
|
2464
3031
|
Example from [samples/hello/hello_combo.rb](samples/hello_combo.rb) sample (you may copy/paste in [`girb`](GLIMMER_GIRB.md)):
|
2465
3032
|
|
2466
3033
|
#### Shine
|
@@ -3107,7 +3674,7 @@ Approach #1 is a casual Ruby-based approach. Approach #2 is the official Glimmer
|
|
3107
3674
|
|
3108
3675
|
A developer might start with approach #1 to eliminate duplication in a view and later upgrade it to approach #2 when needing to export a custom widget to make it available in many views.
|
3109
3676
|
|
3110
|
-
Class-based Custom Widgets
|
3677
|
+
Class-based Custom Widgets offer a number of benefits over method-based custom widgets, such as built-in support for passing SWT style, nested block of extra widgets and properties, and `before_body`/`after_body` hooks.
|
3111
3678
|
|
3112
3679
|
#### Simple Example
|
3113
3680
|
|
@@ -3205,6 +3772,100 @@ Notice how `Red::Composite` became `red__composite` with double-underscore, whic
|
|
3205
3772
|
|
3206
3773
|
Keep in mind that namespaces are not needed to be specified if the Custom Widget class has a unique name, not clashing with a basic SWT widget or another custom widget name.
|
3207
3774
|
|
3775
|
+
#### Custom Widget Listeners
|
3776
|
+
|
3777
|
+
If you need to declare a custom listener on a custom widget, you must override these methods:
|
3778
|
+
- `can_handle_observation_request?(event, &block)`: returns if an event is supported or delegates to super otherwise (to ensure continued support for built-in events)
|
3779
|
+
- `handle_observation_request(event, &block)`: handles event by storing the block in a list of block handlers to invoke at the right time in the custom widget code
|
3780
|
+
|
3781
|
+
Example (you may copy/paste in [`girb`](GLIMMER_GIRB.md)):
|
3782
|
+
|
3783
|
+
```ruby
|
3784
|
+
require 'glimmer-dsl-swt'
|
3785
|
+
|
3786
|
+
# This class declares a `greeting_label` custom widget (by convention)
|
3787
|
+
class GreetingLabel
|
3788
|
+
include Glimmer::UI::CustomWidget
|
3789
|
+
|
3790
|
+
# multiple options without default values
|
3791
|
+
options :name, :colors
|
3792
|
+
|
3793
|
+
# single option with default value
|
3794
|
+
option :greeting, default: 'Hello'
|
3795
|
+
|
3796
|
+
# internal attribute (not a custom widget option)
|
3797
|
+
attr_accessor :label_color
|
3798
|
+
|
3799
|
+
def can_handle_observation_request?(event, &block)
|
3800
|
+
event.to_s == 'on_color_changed' || super
|
3801
|
+
end
|
3802
|
+
|
3803
|
+
def handle_observation_request(event, &block)
|
3804
|
+
if event.to_s == 'on_color_changed'
|
3805
|
+
@color_changed_handlers ||= []
|
3806
|
+
@color_changed_handlers << block
|
3807
|
+
else
|
3808
|
+
super
|
3809
|
+
end
|
3810
|
+
end
|
3811
|
+
|
3812
|
+
before_body do
|
3813
|
+
@font = {height: 24, style: :bold}
|
3814
|
+
@label_color = :black
|
3815
|
+
end
|
3816
|
+
|
3817
|
+
after_body do
|
3818
|
+
return if colors.nil?
|
3819
|
+
|
3820
|
+
Thread.new {
|
3821
|
+
colors.cycle { |color|
|
3822
|
+
self.label_color = color
|
3823
|
+
@color_changed_handlers&.each {|handler| handler.call(color)}
|
3824
|
+
sleep(1)
|
3825
|
+
}
|
3826
|
+
}
|
3827
|
+
end
|
3828
|
+
|
3829
|
+
body {
|
3830
|
+
# pass received swt_style through to label to customize (e.g. :center to center text)
|
3831
|
+
label(swt_style) {
|
3832
|
+
text "#{greeting}, #{name}!"
|
3833
|
+
font @font
|
3834
|
+
foreground <=> [self, :label_color]
|
3835
|
+
}
|
3836
|
+
}
|
3837
|
+
|
3838
|
+
end
|
3839
|
+
|
3840
|
+
# including Glimmer enables the Glimmer DSL syntax, including auto-discovery of the `greeting_label` custom widget
|
3841
|
+
include Glimmer
|
3842
|
+
|
3843
|
+
shell {
|
3844
|
+
fill_layout :vertical
|
3845
|
+
|
3846
|
+
minimum_size 215, 215
|
3847
|
+
text 'Hello, Custom Widget!'
|
3848
|
+
|
3849
|
+
# custom widget options are passed in a hash
|
3850
|
+
greeting_label(name: 'Sean')
|
3851
|
+
|
3852
|
+
# pass :center SWT style followed by custom widget options hash
|
3853
|
+
greeting_label(:center, name: 'Laura', greeting: 'Aloha') #
|
3854
|
+
|
3855
|
+
greeting_label(:right, name: 'Rick') {
|
3856
|
+
# you can nest attributes under custom widgets just like any standard widget
|
3857
|
+
foreground :red
|
3858
|
+
}
|
3859
|
+
|
3860
|
+
# the colors option cycles between colors for the label foreground every second
|
3861
|
+
greeting_label(:center, name: 'Mary', greeting: 'Aloha', colors: [:red, :dark_green, :blue]) {
|
3862
|
+
on_color_changed do |color|
|
3863
|
+
puts "Label color changed: #{color}"
|
3864
|
+
end
|
3865
|
+
}
|
3866
|
+
}.open
|
3867
|
+
```
|
3868
|
+
|
3208
3869
|
#### Custom Widget API
|
3209
3870
|
|
3210
3871
|
Custom Widgets have the following attributes available to call from inside the `#body` method:
|
@@ -4029,25 +4690,6 @@ You may run `glimmer` with the `--profile.graph` instead for a more detailed out
|
|
4029
4690
|
|
4030
4691
|
Learn more at the [JRuby Performance Profile WIKI page](https://github.com/jruby/jruby/wiki/Profiling-JRuby).
|
4031
4692
|
|
4032
|
-
##### SWT Browser Style Options
|
4033
|
-
|
4034
|
-
The `browser` widget can use a particular desktop browser by setting the SWT Style to:
|
4035
|
-
- `:webkit`: use the Webkit browser engine
|
4036
|
-
- `:chromium`: use the Chromium browser engine
|
4037
|
-
|
4038
|
-
Example using the Chromium browser (you may copy/paste in [`girb`](GLIMMER_GIRB.md)):
|
4039
|
-
|
4040
|
-
```ruby
|
4041
|
-
shell {
|
4042
|
-
minimum_size 1024, 860
|
4043
|
-
browser(:chromium) {
|
4044
|
-
url 'http://brightonresort.com/about'
|
4045
|
-
}
|
4046
|
-
}.open
|
4047
|
-
```
|
4048
|
-
|
4049
|
-
This relies on Glimmer's [Multi-DSL Support](#multi-dsl-support) for building the HTML text using [Glimmer XML DSL](https://github.com/AndyObtiva/glimmer-dsl-xml).
|
4050
|
-
|
4051
4693
|
## License
|
4052
4694
|
|
4053
4695
|
[MIT](LICENSE.txt)
|