glimmer-dsl-swt 4.18.5.3 → 4.18.6.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 +41 -0
- data/README.md +8 -10
- data/VERSION +1 -1
- data/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md +57 -13
- data/docs/reference/GLIMMER_PACKAGING_AND_DISTRIBUTION.md +2 -0
- data/docs/reference/GLIMMER_SAMPLES.md +32 -0
- data/glimmer-dsl-swt.gemspec +10 -3
- data/lib/glimmer/swt/color_proxy.rb +1 -1
- data/lib/glimmer/swt/custom/shape.rb +319 -76
- data/lib/glimmer/swt/custom/shape/arc.rb +22 -4
- data/lib/glimmer/swt/custom/shape/cubic.rb +118 -0
- data/lib/glimmer/swt/custom/shape/image.rb +4 -4
- data/lib/glimmer/swt/custom/shape/line.rb +80 -6
- data/lib/glimmer/swt/custom/shape/oval.rb +3 -3
- data/lib/glimmer/swt/custom/shape/path.rb +227 -0
- data/lib/glimmer/swt/custom/shape/path_segment.rb +133 -0
- data/lib/glimmer/swt/custom/shape/point.rb +41 -0
- data/lib/glimmer/swt/custom/shape/polygon.rb +63 -14
- data/lib/glimmer/swt/custom/shape/polyline.rb +41 -10
- data/lib/glimmer/swt/custom/shape/quad.rb +114 -0
- data/lib/glimmer/swt/custom/shape/rectangle.rb +3 -2
- data/lib/glimmer/swt/custom/shape/text.rb +2 -4
- data/lib/glimmer/swt/dialog_proxy.rb +4 -0
- data/lib/glimmer/swt/proxy_properties.rb +1 -1
- data/samples/elaborate/mandelbrot_fractal.rb +1 -1
- data/samples/elaborate/stock_ticker.rb +220 -0
- data/samples/hello/hello_canvas.rb +38 -21
- data/samples/hello/hello_canvas_data_binding.rb +193 -0
- data/samples/hello/hello_canvas_path.rb +120 -0
- metadata +9 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6d4f89641fcc2573b43cd52e23cf4dda45aa209e55cd49cbe751f6a4b7bc85b1
|
4
|
+
data.tar.gz: 9cf53e2b5aef11f838314b50188f63b3a69936ea31f54930da77bddfd561b08e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 355fe3aab4e45648832678ce3a2c00411129be61bbff91575f4c19b73254a82ab9fa58ce6acbac78d6dca4daf383340cd074e6ec5ea6128bcdb37df94befe125
|
7
|
+
data.tar.gz: d30171ae846dc373fb4d58426bcdc64a179579c4f86ee749d16cb0a5f3440bc542305a91a1e0d5774b796e14750a1918ae4e8d3bb33b2eaff70da4fd3a7afff1
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,46 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
### 4.18.6.2
|
4
|
+
|
5
|
+
- Hello, Canvas Data Binding! Sample
|
6
|
+
- Update Stock Ticker sample to keep stock names visible when scrolling graphs off the screen
|
7
|
+
- `rgb` keyword tolerance of nil values (converts to 0)
|
8
|
+
- Canvas Path DSL Data-Binding
|
9
|
+
- Added `Glimmer::SWT::Custom::Shape::PathSegment` `#path` and `#root_path` API methods to enable determining what path/root-path the path segment is part of.
|
10
|
+
- Fixed issues with geometry calculation of path segments (especially line)
|
11
|
+
|
12
|
+
### 4.18.6.1
|
13
|
+
|
14
|
+
- Fixed issues with Canvas Path DSL handling of connected vs non-connected path segments (including in geometry calculations)
|
15
|
+
- Optimized Canvas Path DSL redraw performance by removing extra redraws
|
16
|
+
- Fixed issues in the Hello, Canvas Path! sample and renamed to Stock Ticker
|
17
|
+
- Added a new simpler Hello, Canvas Path! sample
|
18
|
+
|
19
|
+
### 4.18.6.0
|
20
|
+
|
21
|
+
- Canvas Path DSL support (Alpha) for `path` as drawn or filled (`fill: true`) to the Canvas Shape DSL, supporting `point`, `line` (first point is auto-derived from previous point if not specified)
|
22
|
+
- Hello, Canvas Path! sample showing a Stock Ticker with line curves for multiple company stocks, animated with randomly generated data, moving to the left out of screen second by second. Has multiple tabs demonstrating different types of paths for graphing/charting of different real world business applications: point, line, quad, cubic.
|
23
|
+
- Fix issue to allow invocation of `set_min_size` off of `scrolled_composite` proxy directly (not just swt_widget), thus taking advantage of implicit `auto_exec`
|
24
|
+
- Support `Shape#content {}` method just like `WidgetProxy#content` to enable reopening and adding nested shapes at runtime after initial construction
|
25
|
+
- Support a path containing a `quad` bezier curve with `point_array` property
|
26
|
+
- Support a path containing a `cubic` bezier curve with `point_array` property
|
27
|
+
|
28
|
+
### 4.18.5.5
|
29
|
+
|
30
|
+
- Automatically recalculate default size (width/height) to accomodate nested shapes when changing x/y/width/height sticking out of parent from right or bottom.
|
31
|
+
- Support special case of centering a nested shape with default x/y within a parent with default width/height calculated from nested shape
|
32
|
+
- Consider Canvas Shape DSL support for LineAttributes `line_dash_offset` and `line_miter_limit`
|
33
|
+
- Canvas Shape DSL Polygon `include?` does an outer/inner check of edge detection only
|
34
|
+
- Ensure all Canvas Shape DSL properties are restored upon painting a shape to what they were prior to painting that shape
|
35
|
+
- Fix issue with bringing high score dialog up in Tetris caused by latest dialog changes for supporting the new `color_dialog` and `font_dialog`
|
36
|
+
|
37
|
+
### 4.18.5.4
|
38
|
+
|
39
|
+
- Support passing width, height as :default (or nil or not passed in if they are the last args) in all shapes that include other shapes to indicate they are calculated automatically from nested shapes, text/string extent, or otherwise defaulting to 0, 0
|
40
|
+
- Support [:default, width_delta], [:default, height_delta] attributes for width and height, which add/subtract from defaults used for shape
|
41
|
+
- Switch from use of `:default` with x_delta/y_delta to passing `[:default, x_delta]` or `[:default, y_delta]` (e.g. `image(file, [:default, -30], :default)` for x = default - 30 and y = default + 0)
|
42
|
+
- Support a bounding box for all shapes, implementing `#bounds` (x, y, width, and height) and `#size` (width, height) for the ones that don't receive as parameters (like polygon)
|
43
|
+
|
3
44
|
### 4.18.5.3
|
4
45
|
|
5
46
|
- Support nesting shapes within shapes, with relative positioning (meaning x, y coordinates are assumed relative to parent's x, y in nested shapes)
|
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.18.
|
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.18.6.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)
|
@@ -8,17 +8,15 @@
|
|
8
8
|
|
9
9
|
**[Contributors Wanted! (Submit a Glimmer App Sample to Get Started)](#contributing)**
|
10
10
|
|
11
|
-
[Glimmer
|
12
|
-
|
13
|
-
[Glimmer receives two updates per month](https://rubygems.org/gems/glimmer-dsl-swt/versions). You can trust [Glimmer](https://rubygems.org/gems/glimmer) with your Ruby desktop GUI development needs. Please make [Glimmer](https://rubygems.org/gems/glimmer) even better by providing feedback and [contributing](#contributing) when possible.
|
14
|
-
|
15
|
-
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.
|
16
|
-
|
17
|
-
[Glimmer DSL for SWT](https://rubygems.org/gems/glimmer-dsl-swt) versions 4.18.x.y come with [SWT 4.18](https://download.eclipse.org/eclipse/downloads/drops4/R-4.18-202012021800/), which was released on December 2, 2020.
|
11
|
+
[Glimmer](https://github.com/AndyObtiva/glimmer) DSL for SWT is a native-GUI cross-platform desktop development library written in [JRuby](https://www.jruby.org/), an OS-threaded faster JVM 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) 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 (test-first) 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) + [App Store](https://developer.apple.com/macos/distribution/), MSI/EXE files on [Windows](https://www.microsoft.com/en-ca/windows), and [Gem Packaged Shell Scripts](docs/reference/GLIMMER_COMMAND.md#packaging) on [Linux](https://www.linux.org/).
|
18
12
|
|
19
13
|
[<img src="https://covers.oreillystatic.com/images/9780596519650/lrg.jpg" width=105 /><br />
|
20
14
|
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
15
|
|
16
|
+
[Glimmer DSL for SWT](https://rubygems.org/gems/glimmer-dsl-swt) 4.18.6.2 includes [SWT 4.18](https://download.eclipse.org/eclipse/downloads/drops4/R-4.18-202012021800/), which was released on December 2, 2020. 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.
|
17
|
+
|
18
|
+
[Glimmer DSL for SWT receives two updates per month](https://rubygems.org/gems/glimmer-dsl-swt/versions). You can trust [Glimmer DSL for SWT](https://rubygems.org/gems/glimmer-dsl-swt) with your Ruby desktop GUI development needs! [Glimmer DSL for SWT](https://rubygems.org/gems/glimmer-dsl-swt) brings great ideas to the table, such as declarative programming via domain specific languages, currently under-utilized in the GUI domain. That said, it may not be feature complete enough for everybody's needs, so please help make [Glimmer DSL for SWT](https://rubygems.org/gems/glimmer-dsl-swt) even better by providing feedback and [contributing](#contributing) when possible. The project is very active, so any feature suggestions that are accepted could be implemented within weeks if not days. Also, you are welcome to [hire me](#hire-me) full-time if you want long-term development of [Glimmer DSL for SWT](https://rubygems.org/gems/glimmer-dsl-swt) for your project needs.
|
19
|
+
|
22
20
|
Glimmer DSL gems:
|
23
21
|
- [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt): Glimmer DSL for SWT (JRuby Desktop Development GUI Framework)
|
24
22
|
- [glimmer-dsl-opal](https://github.com/AndyObtiva/glimmer-dsl-opal): Glimmer DSL for Opal (Pure Ruby Web GUI and Auto-Webifier of Desktop Apps)
|
@@ -342,7 +340,7 @@ jgem install glimmer-dsl-swt
|
|
342
340
|
|
343
341
|
Or this command if you want a specific version:
|
344
342
|
```
|
345
|
-
jgem install glimmer-dsl-swt -v 4.18.
|
343
|
+
jgem install glimmer-dsl-swt -v 4.18.6.2
|
346
344
|
```
|
347
345
|
|
348
346
|
`jgem` is JRuby's version of `gem` command.
|
@@ -360,7 +358,7 @@ Note: if you're using activerecord or activesupport, keep in mind that Glimmer u
|
|
360
358
|
|
361
359
|
Add the following to `Gemfile`:
|
362
360
|
```
|
363
|
-
gem 'glimmer-dsl-swt', '~> 4.18.
|
361
|
+
gem 'glimmer-dsl-swt', '~> 4.18.6.2'
|
364
362
|
```
|
365
363
|
|
366
364
|
And, then run:
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
4.18.
|
1
|
+
4.18.6.2
|
@@ -36,10 +36,12 @@ This guide should help you get started with Glimmer DSL for SWT. For more advanc
|
|
36
36
|
- [Layouts](#layouts)
|
37
37
|
- [Layout Data](#layout-data)
|
38
38
|
- [Canvas Shape DSL](#canvas-shape-dsl)
|
39
|
+
- [Shapes inside a Shape](#shapes-inside-a-shape)
|
39
40
|
- [Shapes inside a Widget](#shapes-inside-a-widget)
|
40
41
|
- [Shapes inside an Image](#shapes-inside-an-image)
|
41
42
|
- [Canvas Shape API](#canvas-shape-api)
|
42
43
|
- [Pixel Graphics](#pixel-graphics)
|
44
|
+
- [Canvas Path DSL](#canvas-path-dsl)
|
43
45
|
- [Canvas Transform DSL](#canvas-transform-dsl)
|
44
46
|
- [Top-Level Transform Fluent Interface](#top-level-transform-fluent-interface)
|
45
47
|
- [Canvas Animation DSL](#canvas-animation-dsl)
|
@@ -1403,7 +1405,7 @@ Shape keywords and their args (including defaults) are listed below (they basica
|
|
1403
1405
|
- `rectangle(x, y, width, height, arcWidth = 60, arcHeight = 60, fill: false, round: true)` round rectangle, which can be optionally filled, and takes optional extra round angle arguments
|
1404
1406
|
- `rectangle(x, y, width, height, vertical = true, fill: true, gradient: true)` gradient rectangle, which is always filled, and takes an optional extra argument to specify true for vertical gradient (default) and false for horizontal gradient
|
1405
1407
|
- `text(string, x, y, is_transparent = true)` text with optional is_transparent to indicate if background is transparent (default is true)
|
1406
|
-
- `text(string, x, y, flags)` text with optional flags (flag format is `swt(comma_separated_flags)` where flags can be
|
1408
|
+
- `text(string, x, y, flags)` text with optional flags (flag format is `swt(comma_separated_flags)` where flags can be `:draw_delimiter` (i.e. new lines), `:draw_tab`, `:draw_mnemonic`, and `:draw_transparent` as explained in [GC API](https://help.eclipse.org/2020-12/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/graphics/GC.html))
|
1407
1409
|
|
1408
1410
|
Shape keywords that can be filled with color can take a keyword argument `fill: true`. Defaults to false when not specified unless background is set with no foreground (or foreground is set with no background), in which case a smart default is applied.
|
1409
1411
|
Smart defaults can be applied to automatically infer `gradient: true` (rectangle with both foreground and background) and `round: true` (rectangle with more than 4 args, the extra args are numeric) as well.
|
@@ -1460,7 +1462,7 @@ shell {
|
|
1460
1462
|
font height: 25, style: :bold
|
1461
1463
|
}
|
1462
1464
|
rectangle(200, 80, 108, 36) {
|
1463
|
-
foreground
|
1465
|
+
foreground rgb(0, 0, 0)
|
1464
1466
|
line_width 3
|
1465
1467
|
}
|
1466
1468
|
image(image_object, 70, 50)
|
@@ -1506,7 +1508,7 @@ shell {
|
|
1506
1508
|
font height: 25, style: :bold
|
1507
1509
|
}
|
1508
1510
|
rectangle(200, 80, 108, 36) {
|
1509
|
-
foreground
|
1511
|
+
foreground rgb(0, 0, 0)
|
1510
1512
|
line_width 3
|
1511
1513
|
}
|
1512
1514
|
image(image_object, 70, 50)
|
@@ -1541,7 +1543,7 @@ shell {
|
|
1541
1543
|
}
|
1542
1544
|
rectangle {
|
1543
1545
|
x 50
|
1544
|
-
|
1546
|
+
y 20
|
1545
1547
|
width 300
|
1546
1548
|
height 150
|
1547
1549
|
arc_width 30
|
@@ -1596,23 +1598,26 @@ shell {
|
|
1596
1598
|
minimum_size 320, 400
|
1597
1599
|
|
1598
1600
|
canvas {
|
1599
|
-
background :
|
1601
|
+
background :dark_yellow
|
1600
1602
|
|
1601
1603
|
on_paint_control { |paint_event|
|
1602
1604
|
gc = paint_event.gc
|
1603
|
-
gc.background = color(:red).swt_color
|
1604
|
-
gc.fill_rectangle(0, 0, 220, 400)
|
1605
1605
|
|
1606
|
-
gc.background = color(:
|
1607
|
-
gc.
|
1606
|
+
gc.background = color(:dark_red).swt_color
|
1607
|
+
gc.fill_rectangle(0, 0, 220, 400)
|
1608
1608
|
|
1609
|
-
gc.background = color(:
|
1610
|
-
gc.
|
1609
|
+
gc.background = color(:yellow).swt_color
|
1610
|
+
gc.fill_round_rectangle(50, 20, 300, 150, 30, 50)
|
1611
1611
|
|
1612
|
-
gc.
|
1613
|
-
gc.
|
1612
|
+
gc.background = color(:dark_red).swt_color
|
1613
|
+
gc.foreground = color(:yellow).swt_color
|
1614
|
+
gc.fill_gradient_rectangle(150, 200, 100, 70, true)
|
1614
1615
|
|
1616
|
+
gc.font = font(height: 25, style: :bold).swt_font
|
1615
1617
|
gc.foreground = color(:black).swt_color
|
1618
|
+
gc.draw_text('Glimmer', 208, 83, true)
|
1619
|
+
|
1620
|
+
gc.foreground = rgb(0, 0, 0).swt_color
|
1616
1621
|
gc.line_width = 3
|
1617
1622
|
gc.draw_rectangle(200, 80, 108, 36)
|
1618
1623
|
|
@@ -1762,6 +1767,8 @@ They are implemented with the help of the highly robust Java built-in shape geom
|
|
1762
1767
|
- `Shape#contain?(x, y)` : indicates if shape contains x, y point
|
1763
1768
|
- `Shape#include?(x, y)` : indicates if shape includes x, y point on the edge if drawn or inside if filled (include uses contain for filled shapes)
|
1764
1769
|
- `Shape#move_by(x_delta, y_delta)` : moves shape object at x, y location
|
1770
|
+
- `Shape#size` : calculated size for shape bounding box (e.g. a polygon with an irregular shape will have its bounding box width and height calculated)
|
1771
|
+
- `Shape#bounds` : calculated bounds (x, y, width, height) for shape bounding box (e.g. a polygon with an irregular shape will have its bounding box top-left x, y, width and height calculated)
|
1765
1772
|
|
1766
1773
|
Check [Hello, Canvas!](GLIMMER_SAMPLES.md#hello-canvas) for an example.
|
1767
1774
|
|
@@ -1947,6 +1954,43 @@ shell {
|
|
1947
1954
|
|
1948
1955
|
As they say, there are many ways to skin a cat! This is in line with the Ruby way of providing more ways than one. Pick and choose the right tool for the job just like true software engineers.
|
1949
1956
|
|
1957
|
+
### Canvas Path DSL
|
1958
|
+
|
1959
|
+
**(ALPHA FEATURE)**
|
1960
|
+
|
1961
|
+
Unlike common imperative GUI graphing toolkits, Glimmer enables declarative rendering of paths with the new Canvas Path DSL (Early Alpha) via the new `path { }` keyword and by nesting one of the following path segment keywords underneath:
|
1962
|
+
- `point(x1, y1)`: renders a Point (Dot) as part of a path.
|
1963
|
+
- `line(x1, y1, x2=nil, y2=nil)`: renders a Line as part of a path. If you drop x2, y2, it joins to the previous point automatically. You may repeat for a series of lines forming a curve.
|
1964
|
+
- `quad(x1, y1, x2, y2, x3=nil, y3=nil)`: renders a Quadratic Bezier Curve. If you drop x3 and y3, it joins to the previous point automatically.
|
1965
|
+
- `cubic(x1, y1, x2, y2, x3, y3, x4=nil, y4=nil)`: renders a Cubic Bezier Curve. If you drop x4 and y4, it joins to the previous point automatically.
|
1966
|
+
|
1967
|
+
Example:
|
1968
|
+
|
1969
|
+
```ruby
|
1970
|
+
include Glimmer
|
1971
|
+
|
1972
|
+
shell {
|
1973
|
+
text 'Canvas Path Example'
|
1974
|
+
minimum_size 300, 300
|
1975
|
+
|
1976
|
+
canvas {
|
1977
|
+
path {
|
1978
|
+
foreground :black
|
1979
|
+
250.times {|n|
|
1980
|
+
cubic(n + n%30, n+ n%50, 40, 40, 70, 70, n + 20 + n%30, n%30*-1 * n%50)
|
1981
|
+
}
|
1982
|
+
}
|
1983
|
+
}
|
1984
|
+
|
1985
|
+
}.open
|
1986
|
+
```
|
1987
|
+
|
1988
|
+
![Canvas Path Example](/images/glimmer-example-canvas-path.png)
|
1989
|
+
|
1990
|
+
Learn more at the [Hello, Canvas Path!](GLIMMER_SAMPLES.md#hello-canvas-path) and [Stock Ticker](GLIMMER_SAMPLES.md#stock-ticker) samples.
|
1991
|
+
|
1992
|
+
![Stock Ticker](/images/glimmer-stock-ticker.gif)
|
1993
|
+
|
1950
1994
|
### Canvas Transform DSL
|
1951
1995
|
|
1952
1996
|
**(ALPHA FEATURE)**
|
@@ -12,6 +12,8 @@ glimmer package
|
|
12
12
|
|
13
13
|
It works out of the box for any application scaffolded by [Glimmer Scaffolding](#scaffolding), generating all available packaging types on the current platform (e.g. `DMG`, `PKG`, `APP` on the Mac) and displaying a message indicating what pre-requisite setup tools are needed if not installed already (e.g. [Wix Toolset](https://wixtoolset.org/) to generate MSI files on Windows). If you install Wix, make sure it is on the system PATH by adding for example "C:\Program Files (x86)\WiX Toolset v3.11\bin" to the Windows Environment Variables.
|
14
14
|
|
15
|
+
(note: if you see this error on the Mac 'Error: Bundler "DMG Installer" (dmg) failed to produce a bundle.', ignore it as it should have produced a bundle anyways. It is a harmless issue in 3rd party dependency: javapackager.)
|
16
|
+
|
15
17
|
You may choose to generate a specific type of packaging instead by addionally passing in the `[type]` option. For example, this generates an MSI setup file on Windows:
|
16
18
|
|
17
19
|
```
|
@@ -33,6 +33,7 @@
|
|
33
33
|
- [Hello, Canvas!](#hello-canvas)
|
34
34
|
- [Hello, Canvas Animation!](#hello-canvas-animation)
|
35
35
|
- [Hello, Canvas Transform!](#hello-canvas-transform)
|
36
|
+
- [Hello, Canvas Path!](#hello-canvas-path)
|
36
37
|
- [Hello, Cursor!](#hello-cursor)
|
37
38
|
- [Hello, Progress Bar!](#hello-progress-bar)
|
38
39
|
- [Hello, Tree!](#hello-tree)
|
@@ -45,6 +46,7 @@
|
|
45
46
|
- [Contact Manager](#contact-manager)
|
46
47
|
- [Glimmer Tetris](#glimmer-tetris)
|
47
48
|
- [Mandelbrot Fractal](#mandelbrot-fractal)
|
49
|
+
- [Stock Ticker](#stock-ticker)
|
48
50
|
- [External Samples](#external-samples)
|
49
51
|
- [Glimmer Calculator](#glimmer-calculator)
|
50
52
|
- [Gladiator](#gladiator)
|
@@ -564,6 +566,10 @@ Hello, Canvas!
|
|
564
566
|
|
565
567
|
![Hello Canvas](/images/glimmer-hello-canvas.png)
|
566
568
|
|
569
|
+
Hello, Canvas! Moving Shapes and Nested Shapes via Drag'n'Drop
|
570
|
+
|
571
|
+
![Hello Canvas Moving Shapes](/images/glimmer-hello-canvas-moving-shapes.gif)
|
572
|
+
|
567
573
|
Hello, Canvas! with Moved Shapes (via Drag'n'Drop)
|
568
574
|
|
569
575
|
![Hello Canvas Moved Shapes](/images/glimmer-hello-canvas-moved-shapes.png)
|
@@ -580,6 +586,10 @@ Hello, Canvas! Colors Changed
|
|
580
586
|
|
581
587
|
![Hello Canvas Colors Changed](/images/glimmer-hello-canvas-colors-changed.png)
|
582
588
|
|
589
|
+
Hello, Canvas! Data-Binding (changing a `text` shape `string` via data-binding changes from another thread)
|
590
|
+
|
591
|
+
![Hello Canvas Data Binding](/images/glimmer-hello-canvas-data-binding.gif)
|
592
|
+
|
583
593
|
#### Hello, Canvas Animation!
|
584
594
|
|
585
595
|
This sample demonstrates the use of the `canvas` widget and [Animation DSL](#canvas-animation-dsl) in Glimmer.
|
@@ -608,6 +618,18 @@ Hello, Canvas Transform!
|
|
608
618
|
|
609
619
|
![Hello Canvas Transform](/images/glimmer-hello-canvas-transform.png)
|
610
620
|
|
621
|
+
#### Hello, Canvas Path!
|
622
|
+
|
623
|
+
This sample demonstrates the use of the `path`, `quad`, `cubic`, `line`, and `point` keywords as part of the [Canvas Path DSL](/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md#canvas-path-dsl) within the [Canvas Shape DSL](/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md#canvas-shape-dsl).
|
624
|
+
|
625
|
+
Code:
|
626
|
+
|
627
|
+
[samples/hello/hello_canvas_path.rb](/samples/hello/hello_canvas_path.rb)
|
628
|
+
|
629
|
+
Hello, Canvas Path!
|
630
|
+
|
631
|
+
![Hello Canvas Path](/images/glimmer-hello-canvas-path.png)
|
632
|
+
|
611
633
|
#### Hello, Cursor!
|
612
634
|
|
613
635
|
This sample demonstrates the use of the `cursor` property keyword to change the mouse cursor.
|
@@ -804,6 +826,16 @@ Code:
|
|
804
826
|
|
805
827
|
![Mandelbrot Fractal Help Menu](/images/glimmer-mandelbrot-menu-help.png)
|
806
828
|
|
829
|
+
#### Stock Ticker
|
830
|
+
|
831
|
+
This sample demonstrates a Stock Ticker that generates random stock price data for 4 different stocks and provides 4 different tab views of the graphed data using the [Canvas Path DSL](/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md#canvas-path-dsl). It leverages a thread that runs in the background and ticks the stocks to generate random new stock prices before amending the graphed paths with them.
|
832
|
+
|
833
|
+
Code:
|
834
|
+
|
835
|
+
[samples/elaborate/stock_ticker.rb](/samples/elaborate/stock_ticker.rb)
|
836
|
+
|
837
|
+
![Stock Ticker](/images/glimmer-stock-ticker.gif)
|
838
|
+
|
807
839
|
### External Samples
|
808
840
|
|
809
841
|
#### Glimmer Calculator
|
data/glimmer-dsl-swt.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: glimmer-dsl-swt 4.18.
|
5
|
+
# stub: glimmer-dsl-swt 4.18.6.2 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "glimmer-dsl-swt".freeze
|
9
|
-
s.version = "4.18.
|
9
|
+
s.version = "4.18.6.2"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib".freeze]
|
13
13
|
s.authors = ["AndyMaleh".freeze]
|
14
|
-
s.date = "2021-02
|
14
|
+
s.date = "2021-03-02"
|
15
15
|
s.description = "Glimmer DSL for SWT (JRuby Desktop Development GUI Framework) is a native-GUI cross-platform desktop development library written in JRuby, an OS-threaded faster JVM version of Ruby. Glimmer's main innovation is a declarative Ruby DSL that enables productive and efficient authoring of desktop application user-interfaces by relying on the robust Eclipse SWT library. Glimmer additionally innovates by having built-in 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 (test-first) afterwards. Not only does Glimmer provide a large set of GUI widgets, but it also supports drawing Canvas Graphics like Shapes and Animations. To get started quickly, Glimmer offers scaffolding options for Apps, Gems, and Custom Widgets. Glimmer also includes native-executable packaging support, sorely lacking in other libraries, thus enabling the delivery of desktop apps written in Ruby as truly native DMG/PKG/APP files on the Mac + App Store, MSI/EXE files on Windows, and Gem Packaged Shell Scripts on Linux.".freeze
|
16
16
|
s.email = "andy.am@gmail.com".freeze
|
17
17
|
s.executables = ["glimmer".freeze, "girb".freeze]
|
@@ -115,13 +115,17 @@ Gem::Specification.new do |s|
|
|
115
115
|
"lib/glimmer/swt/custom/radio_group.rb",
|
116
116
|
"lib/glimmer/swt/custom/shape.rb",
|
117
117
|
"lib/glimmer/swt/custom/shape/arc.rb",
|
118
|
+
"lib/glimmer/swt/custom/shape/cubic.rb",
|
118
119
|
"lib/glimmer/swt/custom/shape/focus.rb",
|
119
120
|
"lib/glimmer/swt/custom/shape/image.rb",
|
120
121
|
"lib/glimmer/swt/custom/shape/line.rb",
|
121
122
|
"lib/glimmer/swt/custom/shape/oval.rb",
|
123
|
+
"lib/glimmer/swt/custom/shape/path.rb",
|
124
|
+
"lib/glimmer/swt/custom/shape/path_segment.rb",
|
122
125
|
"lib/glimmer/swt/custom/shape/point.rb",
|
123
126
|
"lib/glimmer/swt/custom/shape/polygon.rb",
|
124
127
|
"lib/glimmer/swt/custom/shape/polyline.rb",
|
128
|
+
"lib/glimmer/swt/custom/shape/quad.rb",
|
125
129
|
"lib/glimmer/swt/custom/shape/rectangle.rb",
|
126
130
|
"lib/glimmer/swt/custom/shape/text.rb",
|
127
131
|
"lib/glimmer/swt/date_time_proxy.rb",
|
@@ -162,6 +166,7 @@ Gem::Specification.new do |s|
|
|
162
166
|
"samples/elaborate/login.rb",
|
163
167
|
"samples/elaborate/mandelbrot_fractal.rb",
|
164
168
|
"samples/elaborate/meta_sample.rb",
|
169
|
+
"samples/elaborate/stock_ticker.rb",
|
165
170
|
"samples/elaborate/tetris.rb",
|
166
171
|
"samples/elaborate/tetris/model/block.rb",
|
167
172
|
"samples/elaborate/tetris/model/game.rb",
|
@@ -180,6 +185,8 @@ Gem::Specification.new do |s|
|
|
180
185
|
"samples/hello/hello_button.rb",
|
181
186
|
"samples/hello/hello_canvas.rb",
|
182
187
|
"samples/hello/hello_canvas_animation.rb",
|
188
|
+
"samples/hello/hello_canvas_data_binding.rb",
|
189
|
+
"samples/hello/hello_canvas_path.rb",
|
183
190
|
"samples/hello/hello_canvas_transform.rb",
|
184
191
|
"samples/hello/hello_checkbox.rb",
|
185
192
|
"samples/hello/hello_checkbox_group.rb",
|
@@ -26,13 +26,40 @@ require 'glimmer/swt/color_proxy'
|
|
26
26
|
require 'glimmer/swt/font_proxy'
|
27
27
|
require 'glimmer/swt/transform_proxy'
|
28
28
|
|
29
|
+
class Java::OrgEclipseSwtGraphics::GC
|
30
|
+
def setLineDashOffset(value)
|
31
|
+
lineMiterLimit = getLineAttributes&.miterLimit || 999_999
|
32
|
+
setLineAttributes(Java::OrgEclipseSwtGraphics::LineAttributes.new(getLineWidth, getLineCap, getLineJoin, getLineStyle, getLineDash.map(&:to_f).to_java(:float), value, lineMiterLimit))
|
33
|
+
end
|
34
|
+
alias set_line_dash_offset setLineDashOffset
|
35
|
+
alias line_dash_offset= setLineDashOffset
|
36
|
+
|
37
|
+
def getLineDashOffset
|
38
|
+
getLineAttributes&.dashOffset
|
39
|
+
end
|
40
|
+
alias get_line_dash_offset getLineDashOffset
|
41
|
+
alias line_dash_offset getLineDashOffset
|
42
|
+
|
43
|
+
def setLineMiterLimit(value)
|
44
|
+
lineDashOffset = getLineAttributes&.dashOffset || 0
|
45
|
+
setLineAttributes(Java::OrgEclipseSwtGraphics::LineAttributes.new(getLineWidth, getLineCap, getLineJoin, getLineStyle, getLineDash.map(&:to_f).to_java(:float), lineDashOffset, value))
|
46
|
+
end
|
47
|
+
alias set_line_miter_limit setLineMiterLimit
|
48
|
+
alias line_miter_limit= setLineMiterLimit
|
49
|
+
|
50
|
+
def getLineMiterLimit
|
51
|
+
getLineAttributes&.miterLimit
|
52
|
+
end
|
53
|
+
alias get_line_miter_limit getLineMiterLimit
|
54
|
+
alias line_miter_limit getLineMiterLimit
|
55
|
+
end
|
56
|
+
|
29
57
|
module Glimmer
|
30
58
|
module SWT
|
31
59
|
module Custom
|
32
60
|
# Represents a shape (graphics) to be drawn on a control/widget/canvas/display
|
33
61
|
# That is because Shape is drawn on a parent as graphics and doesn't have an SWT widget for itself
|
34
62
|
class Shape
|
35
|
-
include Packages
|
36
63
|
include Properties
|
37
64
|
|
38
65
|
class << self
|
@@ -46,7 +73,8 @@ module Glimmer
|
|
46
73
|
end
|
47
74
|
|
48
75
|
def valid?(parent, keyword, *args, &block)
|
49
|
-
gc_instance_methods.include?(method_name(keyword, arg_options(args)))
|
76
|
+
gc_instance_methods.include?(method_name(keyword, arg_options(args))) ||
|
77
|
+
constants.include?(keyword.to_s.camelcase(:upper).to_sym)
|
50
78
|
end
|
51
79
|
|
52
80
|
def gc_instance_methods
|
@@ -99,7 +127,7 @@ module Glimmer
|
|
99
127
|
end
|
100
128
|
|
101
129
|
attr_reader :drawable, :parent, :name, :args, :options, :shapes
|
102
|
-
attr_accessor :
|
130
|
+
attr_accessor :extent
|
103
131
|
|
104
132
|
def initialize(parent, keyword, *args, &property_block)
|
105
133
|
@parent = parent
|
@@ -110,8 +138,6 @@ module Glimmer
|
|
110
138
|
@args = args
|
111
139
|
@properties = {}
|
112
140
|
@shapes = [] # nested shapes
|
113
|
-
@x_delta = 0
|
114
|
-
@y_delta = 0
|
115
141
|
@options.reject {|key, value| %w[fill gradient round].include?(key.to_s)}.each do |property, property_args|
|
116
142
|
@properties[property] = property_args
|
117
143
|
end
|
@@ -121,6 +147,7 @@ module Glimmer
|
|
121
147
|
|
122
148
|
def add_shape(shape)
|
123
149
|
@shapes << shape
|
150
|
+
calculated_args_changed_for_defaults!
|
124
151
|
end
|
125
152
|
|
126
153
|
def draw?
|
@@ -141,26 +168,44 @@ module Glimmer
|
|
141
168
|
@options[:round]
|
142
169
|
end
|
143
170
|
|
144
|
-
#
|
171
|
+
# The bounding box top-left x, y, width, height in absolute positioning
|
172
|
+
def bounds
|
173
|
+
org.eclipse.swt.graphics.Rectangle.new(absolute_x, absolute_y, calculated_width, calculated_height)
|
174
|
+
end
|
175
|
+
|
176
|
+
# The bounding box top-left x and y
|
177
|
+
def location
|
178
|
+
org.eclipse.swt.graphics.Point.new(bounds.x, bounds.y)
|
179
|
+
end
|
180
|
+
|
181
|
+
# The bounding box width and height (as a Point object with x being width and y being height)
|
182
|
+
def size
|
183
|
+
org.eclipse.swt.graphics.Point.new(calculated_width, calculated_height)
|
184
|
+
end
|
185
|
+
|
186
|
+
def extent
|
187
|
+
@extent || size
|
188
|
+
end
|
189
|
+
|
190
|
+
# Returns if shape contains a point
|
191
|
+
# Subclasses (like polygon) may override to indicate if a point x,y coordinates falls inside the shape
|
145
192
|
# some shapes may choose to provide a fuzz factor to make usage of this method for mouse clicking more user friendly
|
146
193
|
def contain?(x, y)
|
147
194
|
# assume a rectangular filled shape by default (works for several shapes like image, text, and focus)
|
148
|
-
|
149
|
-
x.between?(self.absolute_x, self.absolute_x + width) && y.between?(self.absolute_y, self.absolute_y + height)
|
150
|
-
else
|
151
|
-
false # subclasses must provide implementation
|
152
|
-
end
|
195
|
+
x.between?(self.absolute_x, self.absolute_x + calculated_width) && y.between?(self.absolute_y, self.absolute_y + calculated_height)
|
153
196
|
end
|
154
197
|
|
155
|
-
#
|
198
|
+
# Returns if shape includes a point. When the shape is filled, this is the same as contain. When the shape is drawn, it only returns true if the point lies on the edge (boundary/border)
|
199
|
+
# Subclasses (like polygon) may override to indicate if a point x,y coordinates falls on the edge of a drawn shape or inside a filled shape
|
156
200
|
# some shapes may choose to provide a fuzz factor to make usage of this method for mouse clicking more user friendly
|
157
201
|
def include?(x, y)
|
158
202
|
# assume a rectangular shape by default
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
203
|
+
contain?(x, y)
|
204
|
+
end
|
205
|
+
|
206
|
+
# Indicates if a shape's x, y, width, height differ from its bounds calculation (e.g. arc / polygon)
|
207
|
+
def irregular?
|
208
|
+
false
|
164
209
|
end
|
165
210
|
|
166
211
|
# moves by x delta and y delta. Subclasses must implement
|
@@ -168,18 +213,25 @@ module Glimmer
|
|
168
213
|
def move_by(x_delta, y_delta)
|
169
214
|
if respond_to?(:x) && respond_to?(:y) && respond_to?(:x=) && respond_to?(:y=)
|
170
215
|
if default_x?
|
171
|
-
self.
|
216
|
+
self.default_x_delta += x_delta
|
172
217
|
else
|
173
218
|
self.x += x_delta
|
174
219
|
end
|
175
220
|
if default_y?
|
176
|
-
self.
|
221
|
+
self.default_y_delta += y_delta
|
177
222
|
else
|
178
223
|
self.y += y_delta
|
179
224
|
end
|
180
225
|
end
|
181
226
|
end
|
182
227
|
|
228
|
+
def content(&block)
|
229
|
+
Glimmer::SWT::DisplayProxy.instance.auto_exec do
|
230
|
+
Glimmer::DSL::Engine.add_content(self, Glimmer::DSL::SWT::ShapeExpression.new, &block)
|
231
|
+
calculated_args_changed!(children: false)
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
183
235
|
def has_some_background?
|
184
236
|
@properties.keys.map(&:to_s).include?('background') || @properties.keys.map(&:to_s).include?('background_pattern')
|
185
237
|
end
|
@@ -189,8 +241,8 @@ module Glimmer
|
|
189
241
|
end
|
190
242
|
|
191
243
|
def post_add_content
|
192
|
-
|
193
|
-
|
244
|
+
amend_method_name_options_based_on_properties!
|
245
|
+
if !@content_added || @method_name != @original_method_name
|
194
246
|
@drawable.setup_shape_painting unless @drawable.is_a?(ImageProxy)
|
195
247
|
@content_added = true
|
196
248
|
end
|
@@ -199,14 +251,19 @@ module Glimmer
|
|
199
251
|
def apply_property_arg_conversions(method_name, property, args)
|
200
252
|
args = args.dup
|
201
253
|
the_java_method = org.eclipse.swt.graphics.GC.java_class.declared_instance_methods.detect {|m| m.name == method_name}
|
202
|
-
if the_java_method.
|
254
|
+
return args if the_java_method.nil?
|
255
|
+
if the_java_method.parameter_types.first == org.eclipse.swt.graphics.Color.java_class && args.first.is_a?(org.eclipse.swt.graphics.RGB)
|
203
256
|
args[0] = [args[0].red, args[0].green, args[0].blue]
|
204
257
|
end
|
205
258
|
if ['setBackground', 'setForeground'].include?(method_name.to_s) && args.first.is_a?(Array)
|
206
259
|
args[0] = ColorProxy.new(args[0])
|
207
260
|
end
|
261
|
+
if method_name.to_s == 'setLineDash' && args.size > 1
|
262
|
+
args[0] = args.dup
|
263
|
+
args[1..-1] = []
|
264
|
+
end
|
208
265
|
if args.first.is_a?(Symbol) || args.first.is_a?(::String)
|
209
|
-
if the_java_method.parameter_types.first == Color.java_class
|
266
|
+
if the_java_method.parameter_types.first == org.eclipse.swt.graphics.Color.java_class
|
210
267
|
args[0] = ColorProxy.new(args[0])
|
211
268
|
end
|
212
269
|
if the_java_method.parameter_types.first == Java::int.java_class
|
@@ -216,7 +273,7 @@ module Glimmer
|
|
216
273
|
if args.first.is_a?(ColorProxy)
|
217
274
|
args[0] = args[0].swt_color
|
218
275
|
end
|
219
|
-
if (args.first.is_a?(Hash) || args.first.is_a?(FontData)) && the_java_method.parameter_types.first == Font.java_class
|
276
|
+
if (args.first.is_a?(Hash) || args.first.is_a?(org.eclipse.swt.graphics.FontData)) && the_java_method.parameter_types.first == org.eclipse.swt.graphics.Font.java_class
|
220
277
|
args[0] = FontProxy.new(args[0])
|
221
278
|
end
|
222
279
|
if args.first.is_a?(FontProxy)
|
@@ -229,7 +286,7 @@ module Glimmer
|
|
229
286
|
@drawable.requires_shape_disposal = true
|
230
287
|
args = args.first if args.first.is_a?(Array)
|
231
288
|
args.each_with_index do |arg, i|
|
232
|
-
arg = ColorProxy.new(arg.red, arg.green, arg.blue) if arg.is_a?(RGB)
|
289
|
+
arg = ColorProxy.new(arg.red, arg.green, arg.blue) if arg.is_a?(org.eclipse.swt.graphics.RGB)
|
233
290
|
arg = ColorProxy.new(arg) if arg.is_a?(Symbol) || arg.is_a?(::String)
|
234
291
|
arg = arg.swt_color if arg.is_a?(ColorProxy)
|
235
292
|
args[i] = arg
|
@@ -278,20 +335,22 @@ module Glimmer
|
|
278
335
|
end
|
279
336
|
|
280
337
|
def apply_shape_arg_defaults!
|
338
|
+
self.x = :default if current_parameter_name?(:x) && x.nil?
|
339
|
+
self.y = :default if current_parameter_name?(:y) && y.nil?
|
340
|
+
self.dest_x = :default if current_parameter_name?(:dest_x) && dest_x.nil?
|
341
|
+
self.dest_y = :default if current_parameter_name?(:dest_y) && dest_y.nil?
|
342
|
+
self.width = :default if current_parameter_name?(:width) && width.nil?
|
343
|
+
self.height = :default if current_parameter_name?(:height) && height.nil?
|
281
344
|
if @name.include?('rectangle') && round? && @args.size.between?(4, 5)
|
282
345
|
(6 - @args.size).times {@args << 60}
|
283
346
|
elsif @name.include?('rectangle') && gradient? && @args.size == 4
|
284
|
-
|
285
|
-
elsif (@name.include?('text') || @name.include?('string')) && !@properties.keys.map(&:to_s).include?('background') && @args.size
|
286
|
-
|
347
|
+
set_attribute('vertical', true, redraw: false)
|
348
|
+
elsif (@name.include?('text') || @name.include?('string')) && !@properties.keys.map(&:to_s).include?('background') && @args.size < 4
|
349
|
+
set_attribute('is_transparent', true, redraw: false)
|
287
350
|
end
|
288
351
|
if @name.include?('image')
|
289
352
|
@drawable.requires_shape_disposal = true
|
290
353
|
end
|
291
|
-
self.x = :default if current_parameter_name?(:x) && x.nil?
|
292
|
-
self.y = :default if current_parameter_name?(:y) && y.nil?
|
293
|
-
self.dest_x = :default if current_parameter_name?(:dest_x) && dest_x.nil?
|
294
|
-
self.dest_y = :default if current_parameter_name?(:dest_y) && dest_y.nil?
|
295
354
|
end
|
296
355
|
|
297
356
|
# Tolerates shape extra args added by user by mistake
|
@@ -306,6 +365,7 @@ module Glimmer
|
|
306
365
|
end
|
307
366
|
|
308
367
|
def amend_method_name_options_based_on_properties!
|
368
|
+
@original_method_name = @method_name
|
309
369
|
return if @name == 'point'
|
310
370
|
if @name != 'text' && @name != 'string' && has_some_background? && !has_some_foreground?
|
311
371
|
@options[:fill] = true
|
@@ -341,11 +401,11 @@ module Glimmer
|
|
341
401
|
end
|
342
402
|
|
343
403
|
def current_parameter_name?(attribute_name)
|
344
|
-
parameter_names.
|
404
|
+
parameter_names.include?(attribute_name.to_s.to_sym)
|
345
405
|
end
|
346
406
|
|
347
407
|
def parameter_index(attribute_name)
|
348
|
-
parameter_names.
|
408
|
+
parameter_names.index(attribute_name.to_s.to_sym)
|
349
409
|
end
|
350
410
|
|
351
411
|
def set_parameter_attribute(attribute_name, *args)
|
@@ -357,9 +417,10 @@ module Glimmer
|
|
357
417
|
parameter_name?(attribute_name) or
|
358
418
|
(respond_to?(attribute_name, super: true) and respond_to?(ruby_attribute_setter(attribute_name), super: true))
|
359
419
|
end
|
360
|
-
|
420
|
+
|
361
421
|
def set_attribute(attribute_name, *args)
|
362
422
|
options = args.last if args.last.is_a?(Hash)
|
423
|
+
args.pop if !options.nil? && !options[:redraw].nil?
|
363
424
|
perform_redraw = @perform_redraw
|
364
425
|
perform_redraw = options[:redraw] if perform_redraw.nil? && !options.nil?
|
365
426
|
perform_redraw = true if perform_redraw.nil?
|
@@ -372,9 +433,19 @@ module Glimmer
|
|
372
433
|
end
|
373
434
|
if @content_added && perform_redraw && !drawable.is_disposed
|
374
435
|
@calculated_paint_args = false
|
436
|
+
if is_a?(PathSegment)
|
437
|
+
root_path&.calculated_path_args = @calculated_path_args = false
|
438
|
+
calculated_args_changed!
|
439
|
+
root_path&.calculated_args_changed!
|
440
|
+
end
|
375
441
|
attribute_name = ruby_attribute_getter(attribute_name)
|
376
|
-
|
377
|
-
|
442
|
+
if location_parameter_names.map(&:to_s).include?(attribute_name)
|
443
|
+
@calculated_args = nil
|
444
|
+
parent.calculated_args_changed_for_defaults! if parent.is_a?(Shape)
|
445
|
+
end
|
446
|
+
if ['width', 'height'].include?(attribute_name)
|
447
|
+
calculated_args_changed_for_defaults!
|
448
|
+
end
|
378
449
|
# TODO consider redrawing an image proxy's gc in the future
|
379
450
|
drawable.redraw unless drawable.is_a?(ImageProxy)
|
380
451
|
end
|
@@ -433,6 +504,7 @@ module Glimmer
|
|
433
504
|
end
|
434
505
|
|
435
506
|
def dispose(dispose_images: true, dispose_patterns: true)
|
507
|
+
shapes.each { |shape| shape.is_a?(Shape::Path) && shape.dispose }
|
436
508
|
if dispose_patterns
|
437
509
|
@background_pattern&.dispose
|
438
510
|
@background_pattern = nil
|
@@ -445,27 +517,46 @@ module Glimmer
|
|
445
517
|
end
|
446
518
|
@parent.shapes.delete(self)
|
447
519
|
end
|
448
|
-
|
520
|
+
|
449
521
|
def paint(paint_event)
|
522
|
+
# pre-paint children an extra-time first when default width/height need to be calculated for defaults
|
523
|
+
paint_children(paint_event) if default_width? || default_height?
|
524
|
+
paint_self(paint_event)
|
525
|
+
# re-paint children from scratch in the special case of pre-calculating parent width/height to re-center within new parent dimensions
|
526
|
+
shapes.each(&:calculated_args_changed!) if default_width? || default_height?
|
527
|
+
paint_children(paint_event)
|
528
|
+
rescue => e
|
529
|
+
Glimmer::Config.logger.error {"Error encountered in painting shape (#{self.inspect}) with calculated args (#{@calculated_args}) and args (#{@args})"}
|
530
|
+
Glimmer::Config.logger.error {e.full_message}
|
531
|
+
end
|
532
|
+
|
533
|
+
def paint_self(paint_event)
|
534
|
+
@painting = true
|
450
535
|
calculate_paint_args!
|
536
|
+
@original_properties_backup = {}
|
451
537
|
@properties.each do |property, args|
|
452
538
|
method_name = attribute_setter(property)
|
453
|
-
|
539
|
+
@original_properties_backup[method_name] = paint_event.gc.send(method_name.sub('set', 'get')) rescue nil
|
454
540
|
paint_event.gc.send(method_name, *args)
|
455
541
|
if property == 'transform' && args.first.is_a?(TransformProxy)
|
456
542
|
args.first.swt_transform.dispose
|
457
543
|
end
|
458
544
|
end
|
459
|
-
|
460
|
-
if !@
|
461
|
-
@
|
462
|
-
@calculated_absolute_args = true
|
545
|
+
ensure_extent(paint_event)
|
546
|
+
if !@calculated_args || parent_shape_absolute_location_changed?
|
547
|
+
@calculated_args = calculated_args
|
463
548
|
end
|
464
|
-
|
465
|
-
|
549
|
+
# paint unless parent's calculated args are not calculated yet, meaning it is about to get painted and trigger a paint on this child anyways
|
550
|
+
paint_event.gc.send(@method_name, *@calculated_args) unless parent.is_a?(Shape) && !parent.calculated_args?
|
551
|
+
@original_properties_backup.each do |method_name, value|
|
552
|
+
paint_event.gc.send(method_name, value)
|
553
|
+
end
|
554
|
+
@painting = false
|
466
555
|
rescue => e
|
467
|
-
Glimmer::Config.logger.error {"Error encountered in painting shape
|
556
|
+
Glimmer::Config.logger.error {"Error encountered in painting shape (#{self.inspect}) with calculated args (#{@calculated_args}) and args (#{@args})"}
|
468
557
|
Glimmer::Config.logger.error {e.full_message}
|
558
|
+
ensure
|
559
|
+
@painting = false
|
469
560
|
end
|
470
561
|
|
471
562
|
def paint_children(paint_event)
|
@@ -474,6 +565,21 @@ module Glimmer
|
|
474
565
|
end
|
475
566
|
end
|
476
567
|
|
568
|
+
def ensure_extent(paint_event)
|
569
|
+
old_extent = @extent
|
570
|
+
if ['text', 'string'].include?(@name)
|
571
|
+
extent_args = [string]
|
572
|
+
extent_flags = SWTProxy[:draw_transparent] if current_parameter_name?(:is_transparent) && is_transparent
|
573
|
+
extent_flags = flags if current_parameter_name?(:flags)
|
574
|
+
extent_args << extent_flags unless extent_flags.nil?
|
575
|
+
self.extent = paint_event.gc.send("#{@name}Extent", *extent_args)
|
576
|
+
end
|
577
|
+
if !@extent.nil? && (old_extent&.x != @extent&.x || old_extent&.y != @extent&.y)
|
578
|
+
calculated_args_changed!
|
579
|
+
parent.calculated_args_changed_for_defaults! if parent.is_a?(Shape)
|
580
|
+
end
|
581
|
+
end
|
582
|
+
|
477
583
|
def expanded_shapes
|
478
584
|
if shapes.to_a.any?
|
479
585
|
shapes.map do |shape|
|
@@ -487,69 +593,200 @@ module Glimmer
|
|
487
593
|
def parent_shape_absolute_location_changed?
|
488
594
|
(parent.is_a?(Shape) && (parent.absolute_x != @parent_absolute_x || parent.absolute_y != @parent_absolute_y))
|
489
595
|
end
|
596
|
+
|
597
|
+
def calculated_args_changed!(children: true)
|
598
|
+
# TODO add a children: true option to enable setting to false to avoid recalculating children args
|
599
|
+
@calculated_args = nil
|
600
|
+
shapes.each(&:calculated_args_changed!) if children
|
601
|
+
end
|
602
|
+
|
603
|
+
def calculated_args_changed_for_defaults!
|
604
|
+
has_default_dimensions = default_width? || default_height?
|
605
|
+
parent_calculated_args_changed_for_defaults = has_default_dimensions
|
606
|
+
@calculated_args = nil if default_x? || default_y? || has_default_dimensions
|
607
|
+
if has_default_dimensions && parent.is_a?(Shape)
|
608
|
+
parent.calculated_args_changed_for_defaults!
|
609
|
+
elsif @content_added && !drawable.is_disposed
|
610
|
+
# TODO consider optimizing in the future if needed by ensuring one redraw for all parents in the hierarchy at the end instead of doing one per parent that needs it
|
611
|
+
drawable.redraw if !@painting && !drawable.is_a?(ImageProxy)
|
612
|
+
end
|
613
|
+
end
|
614
|
+
|
615
|
+
def calculated_args?
|
616
|
+
!!@calculated_args
|
617
|
+
end
|
490
618
|
|
491
619
|
# args translated to absolute coordinates
|
492
|
-
def
|
493
|
-
return @args if !default_x? && !default_y? &&
|
620
|
+
def calculated_args
|
621
|
+
return @args if !default_x? && !default_y? && !default_width? && !default_height? && parent.is_a?(Drawable)
|
622
|
+
# Note: Must set x and move_by because not all shapes have a real x and some must translate all their points with move_by
|
623
|
+
# TODO change that by setting a bounding box for all shapes with a calculated top-left x, y and
|
624
|
+
# a setter that does the moving inside them instead so that I could rely on absolute_x and absolute_y
|
625
|
+
# here to get the job done of calculating absolute args
|
494
626
|
@perform_redraw = false
|
495
627
|
original_x = nil
|
496
628
|
original_y = nil
|
629
|
+
original_width = nil
|
630
|
+
original_height = nil
|
631
|
+
if parent.is_a?(Shape)
|
632
|
+
@parent_absolute_x = parent.absolute_x
|
633
|
+
@parent_absolute_y = parent.absolute_y
|
634
|
+
end
|
635
|
+
if default_width?
|
636
|
+
original_width = width
|
637
|
+
self.width = default_width + default_width_delta
|
638
|
+
end
|
639
|
+
if default_height?
|
640
|
+
original_height = height
|
641
|
+
self.height = default_height + default_height_delta
|
642
|
+
end
|
497
643
|
if default_x?
|
498
644
|
original_x = x
|
499
|
-
self.x = default_x
|
645
|
+
self.x = default_x + default_x_delta
|
500
646
|
end
|
501
647
|
if default_y?
|
502
648
|
original_y = y
|
503
|
-
self.y = default_y
|
649
|
+
self.y = default_y + default_y_delta
|
504
650
|
end
|
505
|
-
move_by(@x_delta, @y_delta)
|
506
651
|
if parent.is_a?(Shape)
|
507
|
-
@parent_absolute_x
|
508
|
-
|
509
|
-
move_by(
|
510
|
-
calculated_absolute_args = @args.clone
|
511
|
-
move_by(-1*parent.absolute_x, -1*parent.absolute_y)
|
652
|
+
move_by(@parent_absolute_x, @parent_absolute_y)
|
653
|
+
result_args = @args.clone
|
654
|
+
move_by(-1*@parent_absolute_x, -1*@parent_absolute_y)
|
512
655
|
else
|
513
|
-
|
656
|
+
result_args = @args.clone
|
514
657
|
end
|
515
|
-
move_by(-1*@x_delta, -1*@y_delta)
|
516
658
|
if original_x
|
517
659
|
self.x = original_x
|
518
660
|
end
|
519
661
|
if original_y
|
520
662
|
self.y = original_y
|
521
663
|
end
|
664
|
+
if original_width
|
665
|
+
self.width = original_width
|
666
|
+
end
|
667
|
+
if original_height
|
668
|
+
self.height = original_height
|
669
|
+
end
|
522
670
|
@perform_redraw = true
|
523
|
-
|
671
|
+
result_args
|
524
672
|
end
|
525
673
|
|
526
674
|
def default_x?
|
527
|
-
current_parameter_name?(
|
675
|
+
current_parameter_name?(:x) and
|
676
|
+
(x.nil? || x.to_s == 'default' || (x.is_a?(Array) && x.first.to_s == 'default'))
|
528
677
|
end
|
529
678
|
|
530
679
|
def default_y?
|
531
|
-
current_parameter_name?(
|
680
|
+
current_parameter_name?(:y) and
|
681
|
+
(y.nil? || y.to_s == 'default' || (y.is_a?(Array) && y.first.to_s == 'default'))
|
682
|
+
end
|
683
|
+
|
684
|
+
def default_width?
|
685
|
+
return false unless current_parameter_name?(:width)
|
686
|
+
width = self.width
|
687
|
+
(width.nil? || width == :default || width == 'default' || (width.is_a?(Array) && (width.first.to_s == :default || width.first.to_s == 'default')))
|
688
|
+
end
|
689
|
+
|
690
|
+
def default_height?
|
691
|
+
return false unless current_parameter_name?(:height)
|
692
|
+
height = self.height
|
693
|
+
(height.nil? || height == :default || height == 'default' || (height.is_a?(Array) && (height.first.to_s == :default || height.first.to_s == 'default')))
|
532
694
|
end
|
533
695
|
|
534
696
|
def default_x
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
0
|
539
|
-
end
|
697
|
+
result = ((parent.size.x - size.x) / 2)
|
698
|
+
result += parent.bounds.x - parent.absolute_x if parent.is_a?(Shape) && parent.irregular?
|
699
|
+
result
|
540
700
|
end
|
541
701
|
|
542
702
|
def default_y
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
703
|
+
result = ((parent.size.y - size.y) / 2)
|
704
|
+
result += parent.bounds.y - parent.absolute_y if parent.is_a?(Shape) && parent.irregular?
|
705
|
+
result
|
706
|
+
end
|
707
|
+
|
708
|
+
def default_width
|
709
|
+
# TODO consider caching
|
710
|
+
x_ends = shapes.map do |shape|
|
711
|
+
shape_width = shape.calculated_width.to_f
|
712
|
+
shape_x = shape.default_x? ? 0 : shape.x.to_f
|
713
|
+
shape_x + shape_width
|
714
|
+
end
|
715
|
+
x_ends.max.to_f
|
716
|
+
end
|
717
|
+
|
718
|
+
def default_height
|
719
|
+
# TODO consider caching
|
720
|
+
y_ends = shapes.map do |shape|
|
721
|
+
shape_height = shape.calculated_height.to_f
|
722
|
+
shape_y = shape.default_y? ? 0 : shape.y.to_f
|
723
|
+
shape_y + shape_height
|
547
724
|
end
|
725
|
+
y_ends.max.to_f
|
726
|
+
end
|
727
|
+
|
728
|
+
def calculated_width
|
729
|
+
default_width? ? (default_width + default_width_delta) : width
|
730
|
+
end
|
731
|
+
|
732
|
+
def calculated_height
|
733
|
+
default_height? ? (default_height + default_height_delta) : height
|
734
|
+
end
|
735
|
+
|
736
|
+
def default_x_delta
|
737
|
+
return 0 unless default_x? && x.is_a?(Array)
|
738
|
+
x[1].to_f
|
739
|
+
end
|
740
|
+
|
741
|
+
def default_y_delta
|
742
|
+
return 0 unless default_y? && y.is_a?(Array)
|
743
|
+
y[1].to_f
|
744
|
+
end
|
745
|
+
|
746
|
+
def default_width_delta
|
747
|
+
return 0 unless default_width? && width.is_a?(Array)
|
748
|
+
width[1].to_f
|
749
|
+
end
|
750
|
+
|
751
|
+
def default_height_delta
|
752
|
+
return 0 unless default_height? && height.is_a?(Array)
|
753
|
+
height[1].to_f
|
754
|
+
end
|
755
|
+
|
756
|
+
def default_x_delta=(delta)
|
757
|
+
return unless default_x?
|
758
|
+
self.x = [:default, delta]
|
759
|
+
end
|
760
|
+
|
761
|
+
def default_y_delta=(delta)
|
762
|
+
return unless default_y?
|
763
|
+
self.y = [:default, delta]
|
764
|
+
end
|
765
|
+
|
766
|
+
def default_width_delta=(delta)
|
767
|
+
return unless default_width?
|
768
|
+
self.width = [:default, delta]
|
769
|
+
end
|
770
|
+
|
771
|
+
def default_height_delta=(delta)
|
772
|
+
return unless default_height?
|
773
|
+
self.height = [:default, delta]
|
774
|
+
end
|
775
|
+
|
776
|
+
def calculated_x
|
777
|
+
result = default_x? ? default_x : self.x
|
778
|
+
result += default_x_delta
|
779
|
+
result
|
780
|
+
end
|
781
|
+
|
782
|
+
def calculated_y
|
783
|
+
result = default_y? ? default_y : self.y
|
784
|
+
result += default_y_delta
|
785
|
+
result
|
548
786
|
end
|
549
787
|
|
550
788
|
def absolute_x
|
551
|
-
x =
|
552
|
-
x += @x_delta
|
789
|
+
x = calculated_x
|
553
790
|
if parent.is_a?(Shape)
|
554
791
|
parent.absolute_x + x
|
555
792
|
else
|
@@ -558,8 +795,7 @@ module Glimmer
|
|
558
795
|
end
|
559
796
|
|
560
797
|
def absolute_y
|
561
|
-
y =
|
562
|
-
y += @y_delta
|
798
|
+
y = calculated_y
|
563
799
|
if parent.is_a?(Shape)
|
564
800
|
parent.absolute_y + y
|
565
801
|
else
|
@@ -567,12 +803,19 @@ module Glimmer
|
|
567
803
|
end
|
568
804
|
end
|
569
805
|
|
806
|
+
# Overriding inspect to avoid printing very long shape hierarchies
|
807
|
+
def inspect
|
808
|
+
"#<#{self.class.name}:0x#{self.hash.to_s(16)} args=#{@args.inspect}, properties=#{@properties.inspect}}>"
|
809
|
+
rescue => e
|
810
|
+
"#<#{self.class.name}:0x#{self.hash.to_s(16)}"
|
811
|
+
end
|
812
|
+
|
570
813
|
def calculate_paint_args!
|
571
814
|
unless @calculated_paint_args
|
572
815
|
if @name == 'pixel'
|
573
816
|
@name = 'point'
|
574
817
|
# optimized performance calculation for pixel points
|
575
|
-
if !@properties[:foreground].is_a?(Color)
|
818
|
+
if !@properties[:foreground].is_a?(org.eclipse.swt.graphics.Color)
|
576
819
|
if @properties[:foreground].is_a?(Array)
|
577
820
|
@properties[:foreground] = ColorProxy.new(@properties[:foreground], ensure_bounds: false)
|
578
821
|
end
|
@@ -589,7 +832,7 @@ module Glimmer
|
|
589
832
|
# TODO regarding alpha, make sure to reset it to parent stored alpha once we allow setting shape properties on parents directly without shapes
|
590
833
|
@properties['alpha'] ||= [255]
|
591
834
|
@properties['font'] = [@drawable.font] if @drawable.respond_to?(:font) && draw? && !@properties.keys.map(&:to_s).include?('font')
|
592
|
-
# TODO regarding transform, make sure to reset it to parent stored
|
835
|
+
# TODO regarding transform, make sure to reset it to parent stored transform once we allow setting shape properties on parents directly without shapes
|
593
836
|
# Also do that with all future-added properties
|
594
837
|
@properties['transform'] = [nil] if @drawable.respond_to?(:transform) && !@properties.keys.map(&:to_s).include?('transform')
|
595
838
|
@properties.each do |property, args|
|