glimmer-dsl-swt 4.18.5.1 → 4.18.5.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e3086c3823faac7765ca33e069111da2f027462fc9d09a2a9799a2ff094d6692
4
- data.tar.gz: be7070377808b55cfa4bde48543b8a98fdff77205c9db0c07d0f4ac42078e00e
3
+ metadata.gz: 03f0ab47e7617c3d595a737c755ddc05e877074fb9139cacca042c6c31f7999e
4
+ data.tar.gz: f80117653d4ce70cfde372cbe660ab4d0a7ae181a24df76c79226fcb43c68549
5
5
  SHA512:
6
- metadata.gz: 79e966ac5b7c342d8a9b936387e59f299f4895ae93c01600f8289cc06448b4d90beb0bd6e24073728d7a379172e1513b3cdf05fb3cdd4361ee08bd337870f491
7
- data.tar.gz: 3c89781755c57a6cfc2990d85352bb37674e41a8d2f55f50c26c0d44f948ab26342b58bc98fcc9f93818cf19036ea0032a84b1565397abc7b7aa93a029b8c851
6
+ metadata.gz: a543129ea30b6a18306341b9fad1f62a36f919d83cedc27ea5b6e62c18e13827b28e05cbb01c81e0d8639d5412aeb6ba2e81de60e4c7f0ba5052b474eb07b7f3
7
+ data.tar.gz: 8d757538764f6018a381bcc68583b2d2660d23c9a2f8f1b15c90ad904b84316b1a4e61197f1f618a2bb42ad5d2114cc087e9aaebe1538514a24b330bdf8ce44f
data/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Change Log
2
2
 
3
+ ### 4.18.5.2
4
+
5
+ - Support checking if an `arc` shape accurately includes a point x,y coordinates within pie region only
6
+ - Support checking if an `oval` shape includes a point x,y coordinates in oval region only (not its rectangular region)
7
+ - Support checking if a `focus` shape includes a point x,y coordinates
8
+ - Support checking point inclusion differently in drawed vs filled Rectangle (only check the drawn border when not filled)
9
+ - Support checking point inclusion differently in drawed vs filled Oval (only check the drawn border when not filled)
10
+ - Support checking point inclusion differently in drawed vs filled Arc (only check the drawn border when not filled)
11
+ - Support `#include?(x, y)` and `#contain?(x, y)` methods in `text` shape
12
+ - Fix point inclusion check for polyline
13
+ - Fix issue with `polygon` check if it includes a point x,y coordinates (replace with available `java.awt` robust geometry algorithms)
14
+ - Fix issue with transforms not working after the latest changes
15
+
3
16
  ### 4.18.5.1
4
17
 
5
18
  - Hello, Color Dialog! Sample
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.5.1
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.5.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)
@@ -342,7 +342,7 @@ jgem install glimmer-dsl-swt
342
342
 
343
343
  Or this command if you want a specific version:
344
344
  ```
345
- jgem install glimmer-dsl-swt -v 4.18.5.1
345
+ jgem install glimmer-dsl-swt -v 4.18.5.2
346
346
  ```
347
347
 
348
348
  `jgem` is JRuby's version of `gem` command.
@@ -360,7 +360,7 @@ Note: if you're using activerecord or activesupport, keep in mind that Glimmer u
360
360
 
361
361
  Add the following to `Gemfile`:
362
362
  ```
363
- gem 'glimmer-dsl-swt', '~> 4.18.5.1'
363
+ gem 'glimmer-dsl-swt', '~> 4.18.5.2'
364
364
  ```
365
365
 
366
366
  And, then run:
@@ -404,11 +404,16 @@ Glimmer configuration may be done via the `Glimmer::Config` module.
404
404
 
405
405
  ## Samples
406
406
 
407
- See a listing of Glimmer DSL for SWT samples over here, including screenshots and explanations of what each sample demonstrates:
407
+ See a listing of samples over here, including screenshots and explanations of what each sample demonstrates:
408
408
 
409
409
  [docs/reference/GLIMMER_SAMPLES.md](docs/reference/GLIMMER_SAMPLES.md)
410
410
 
411
- Check the [samples](samples) directory in [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt) for examples on how to write Glimmer applications. To run a sample, make sure to install the `glimmer-dsl-swt` gem first and then use the `glimmer samples` command to run it (alternatively, you may clone the repo, follow [CONTRIBUTING.md](CONTRIBUTING.md) instructions, and run samples locally with development glimmer command: `bin/glimmer`).
411
+ Check the [samples](samples) directory in [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt) for examples on how to write Glimmer applications. To run a sample, make sure to install the `glimmer-dsl-swt` gem first and then run:
412
+ ```
413
+ glimmer samples
414
+ ```
415
+
416
+ (alternatively, you may clone the repo, follow [CONTRIBUTING.md](CONTRIBUTING.md) instructions, and run samples locally with development glimmer command: `bin/glimmer`)
412
417
 
413
418
  ![Glimmer Meta-Sample](/images/glimmer-meta-sample.png)
414
419
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 4.18.5.1
1
+ 4.18.5.2
@@ -1387,7 +1387,7 @@ https://help.eclipse.org/2019-12/nftopic/org.eclipse.platform.doc.isv/reference/
1387
1387
 
1388
1388
  Glimmer supports drawing graphics directly on a `canvas` widget via SWT (or any widget for that matter though `canvas` is recommended for drawing).
1389
1389
 
1390
- `canvas` has the `:double_buffered` SWT style by default 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)`)
1390
+ `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)`)
1391
1391
 
1392
1392
  This is accomplished via the Shape DSL a sub-DSL of the Glimmer GUI DSL, which makes it possible to draw graphics declaratively with very understandable and maintainable syntax.
1393
1393
 
@@ -1404,9 +1404,10 @@ Shape keywords and their args (including defaults) are listed below (they basica
1404
1404
  - `rectangle(x, y, width, height, fill: false)` standard rectangle, which can be optionally filled
1405
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
1406
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
1407
- - `text(string, x, y, flags = nil)` 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
+ - `text(string, x, y, is_transparent = true)` text with optional is_transparent to indicate if background is transparent (default is true)
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))
1408
1409
 
1409
- Shape keywords that can be filled with color can take an 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.
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.
1410
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.
1411
1412
 
1412
1413
  Optionally, a shape keyword takes a block that can set any attributes from [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) (methods starting with `set`), which enable setting the `background` for filling and `foreground` for drawing.
@@ -1473,6 +1474,110 @@ Screenshot:
1473
1474
 
1474
1475
  ![Canvas Animation Example](/images/glimmer-example-canvas.png)
1475
1476
 
1477
+ The round and gradient options could be dropped since Glimmer DSL for SWT supports auto-inference of them based on shape parameters.
1478
+
1479
+ Example (you may copy/paste in [`girb`](GLIMMER_GIRB.md)):
1480
+
1481
+ ```ruby
1482
+ include Glimmer
1483
+
1484
+ # image object has to be declared outside the canvas and shell to avoid confusing with canvas image property
1485
+ image_object = image(File.expand_path('./icons/scaffold_app.png'), width: 100)
1486
+
1487
+ shell {
1488
+ text 'Canvas Example'
1489
+ minimum_size 320, 400
1490
+
1491
+ canvas {
1492
+ background :dark_yellow
1493
+ rectangle(0, 0, 220, 400) {
1494
+ background :dark_red
1495
+ }
1496
+ rectangle(50, 20, 300, 150, 30, 50) {
1497
+ background :yellow
1498
+ }
1499
+ rectangle(150, 200, 100, 70, true) {
1500
+ background :dark_red
1501
+ foreground :yellow
1502
+ }
1503
+ text('Glimmer', 208, 83) {
1504
+ font height: 25, style: :bold
1505
+ }
1506
+ rectangle(200, 80, 108, 36) {
1507
+ foreground :black
1508
+ line_width 3
1509
+ }
1510
+ image(image_object, 70, 50)
1511
+ }
1512
+ }.open
1513
+ ```
1514
+
1515
+ Notice how the 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.
1516
+
1517
+ Of course, Glimmer DSL for SWT still supports an alternative syntax that is more declarative and consistent with the rest of the Glimmer GUI DSL syntax. This syntax in fact offers the extra-benefit of data-binding for shape parameter values (meaning you could use `bind(...)` syntax with them instead of setting values directly)
1518
+
1519
+ Example (you may copy/paste in [`girb`](GLIMMER_GIRB.md)):
1520
+
1521
+ ```ruby
1522
+ include Glimmer
1523
+
1524
+ # image object has to be declared outside the canvas and shell to avoid confusing with canvas image property
1525
+ image_object = image(File.expand_path('./icons/scaffold_app.png'), width: 100)
1526
+
1527
+ shell {
1528
+ text 'Canvas Example'
1529
+ minimum_size 320, 400
1530
+
1531
+ canvas {
1532
+ background :dark_yellow
1533
+ rectangle {
1534
+ x 0
1535
+ y 0
1536
+ width 220
1537
+ height 400
1538
+ background :dark_red
1539
+ }
1540
+ rectangle {
1541
+ x 50
1542
+ x 20
1543
+ width 300
1544
+ height 150
1545
+ arc_width 30
1546
+ arc_height 50
1547
+ background :yellow
1548
+ }
1549
+ rectangle {
1550
+ x 150
1551
+ y 200
1552
+ width 100
1553
+ height 70
1554
+ vertical true
1555
+ background :dark_red
1556
+ foreground :yellow
1557
+ }
1558
+ text {
1559
+ string 'Glimmer'
1560
+ x 208
1561
+ y 83
1562
+ font height: 25, style: :bold
1563
+ }
1564
+ rectangle {
1565
+ x 200
1566
+ y 80
1567
+ width 108
1568
+ height 36
1569
+ foreground :black
1570
+ line_width 3
1571
+ }
1572
+ image {
1573
+ image image_object
1574
+ x 70
1575
+ y 50
1576
+ }
1577
+ }
1578
+ }.open
1579
+ ```
1580
+
1476
1581
  Learn more at the [Hello, Canvas! Sample](GLIMMER_SAMPLES.md#hello-canvas).
1477
1582
 
1478
1583
  If you ever have special needs or optimizations, 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).
@@ -1619,8 +1724,11 @@ shell {
1619
1724
 
1620
1725
  These Canvas Shape API methods help with manipulating shapes upon user interaction, such as mouse clicking a specific shape.
1621
1726
 
1727
+ They are implemented with the help of the highly robust Java built-in shape geometry algorithms.
1728
+
1622
1729
  - `WidgetProxy#shape_at_location(x, y)` : returns shape object at x, y location from a widget proxy like canvas
1623
- - `Shape#include?(x, y)` : indicates if shape includes x, y point (`arc` and `oval` shapes currently include their entire rectangular region in their checks, `text` shapes always return false)
1730
+ - `Shape#contain?(x, y)` : indicates if shape contains x, y point
1731
+ - `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)
1624
1732
  - `Shape#move_by(x_delta, y_delta)` : moves shape object at x, y location
1625
1733
 
1626
1734
  Check [Hello, Canvas!](GLIMMER_SAMPLES.md#hello-canvas) for an example.
@@ -1963,7 +2071,7 @@ If there is anything missing you would like added to the Glimmer Animation DSL t
1963
2071
 
1964
2072
  Animation could be alternatively implemented without the `animation` keyword through a loop that invokes model methods inside `sync_exec {}` (or `async_exec {}`), which indirectly cause updates to the GUI via data-binding.
1965
2073
 
1966
- The [Glimmer Tetris](#tetris) sample provides a good example of that.
2074
+ The [Glimmer Tetris](GLIMMER_SAMPLES.md#tetris) sample provides a good example of that.
1967
2075
 
1968
2076
  ### Data-Binding
1969
2077
 
@@ -2324,7 +2432,7 @@ shell {
2324
2432
  }
2325
2433
  ```
2326
2434
 
2327
- Check out [Hello, Table!](#hello-table) for an actual example including table editors.
2435
+ Check out [Hello, Table!](GLIMMER_SAMPLES.md#hello-table) for an actual example including table editors.
2328
2436
 
2329
2437
  [Are We There Yet?](#are-we-there-yet) is an actual production Glimmer application that takes full advantage of table capabilities, storing model data in a database via ActiveRecord. As such, it's an excellent demonstration of how to use Glimmer DSL for SWT with a database.
2330
2438
 
@@ -2332,7 +2440,7 @@ Check out [Hello, Table!](#hello-table) for an actual example including table ed
2332
2440
 
2333
2441
  Glimmer automatically adds sorting support to the SWT `Table` widget.
2334
2442
 
2335
- Check out the [Contact Manager](#contact-manager) sample for an example.
2443
+ Check out the [Contact Manager](GLIMMER_SAMPLES.md#contact-manager) sample for an example.
2336
2444
  You may click on any column and it will sort by ascending order first and descending if you click again.
2337
2445
 
2338
2446
  Glimmer automatic table sorting supports `String`, `Integer`, and `Float` columns out of the box as well as any column data that is comparable.
@@ -2454,7 +2562,7 @@ You can data-bind any of these properties:
2454
2562
  - `minutes bind(model, :property)`: produces an integer
2455
2563
  - `seconds bind(model, :property)`: produces an integer
2456
2564
 
2457
- Learn more at the [Hello, Date Time!](#hello-date-time) sample.
2565
+ Learn more at the [Hello, Date Time!](GLIMMER_SAMPLES.md#hello-date-time) sample.
2458
2566
 
2459
2567
  If you need a better widget with the ability to customize the date format pattern, check out the [Nebula CDateTime Glimmer Custom Widget](https://github.com/AndyObtiva/glimmer-cw-cdatetime-nebula)
2460
2568
 
@@ -2840,7 +2948,7 @@ The `checkboxes` property returns the list of nested `checkbox` widgets.
2840
2948
 
2841
2949
  When data-binding `selection`, the model property should have a matching property with `_options` suffix (e.g. `activities_options` for `activities`) to provide an `Array` of `String` objects for `checkbox` buttons.
2842
2950
 
2843
- You may see an example at the [Hello, Checkbox Group!](#hello-checkbox-group) sample.
2951
+ You may see an example at the [Hello, Checkbox Group!](GLIMMER_SAMPLES.md#hello-checkbox-group) sample.
2844
2952
 
2845
2953
  ![Hello Checkbox Group](/images/glimmer-hello-checkbox-group.png)
2846
2954
 
@@ -2875,7 +2983,7 @@ radio_group { |radio_group_proxy|
2875
2983
  # ...
2876
2984
  ```
2877
2985
 
2878
- You may see another example at the [Hello, Radio Group!](#hello-radio-group) sample.
2986
+ You may see another example at the [Hello, Radio Group!](GLIMMER_SAMPLES.md#hello-radio-group) sample.
2879
2987
 
2880
2988
  ##### Code Text Custom Widget
2881
2989
 
@@ -3147,7 +3255,7 @@ This adds some default keyboard shortcuts:
3147
3255
 
3148
3256
  If you prefer it to be vanilla with no default key event listeners, then pass the `default_behavior: false` option.
3149
3257
 
3150
- Learn more at [Hello, Code Text!](#hello-code-text)
3258
+ Learn more at [Hello, Code Text!](GLIMMER_SAMPLES.md#hello-code-text)
3151
3259
 
3152
3260
  ##### Video Custom Custom Widget
3153
3261
 
@@ -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.1 ruby lib
5
+ # stub: glimmer-dsl-swt 4.18.5.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.5.1"
9
+ s.version = "4.18.5.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-23"
14
+ s.date = "2021-02-24"
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]
@@ -32,7 +32,7 @@ module Glimmer
32
32
  include ParentExpression
33
33
 
34
34
  def can_interpret?(parent, keyword, *args, &block)
35
- parent.is_a?(Glimmer::SWT::Custom::Drawable) and
35
+ (parent.is_a?(Glimmer::SWT::Custom::Drawable) or parent.is_a?(Glimmer::SWT::Custom::Shape)) and
36
36
  Glimmer::SWT::Custom::Shape.valid?(parent, keyword, *args, &block)
37
37
  end
38
38
 
@@ -38,6 +38,13 @@ module Glimmer
38
38
  @image_buffered_shapes ||= []
39
39
  end
40
40
 
41
+ # Returns shapes expanded with regards to nested shapes
42
+ def expand_shapes(shapes)
43
+ # TODO
44
+ end
45
+
46
+ # TODO add a method like shapes that specifies drawable_properties to be able to adjust properties like transform in between shapes
47
+
41
48
  def shape_at_location(x, y)
42
49
  shapes.reverse.detect {|shape| shape.include?(x, y)}
43
50
  end
@@ -34,8 +34,6 @@ module Glimmer
34
34
  class Shape
35
35
  include Packages
36
36
  include Properties
37
- # TODO support textExtent sized shapes nested within text/string
38
- # TODO support a Pattern DSL for methods that take Pattern arguments
39
37
 
40
38
  class << self
41
39
  def create(parent, keyword, *args, &property_block)
@@ -100,15 +98,17 @@ module Glimmer
100
98
  end
101
99
  end
102
100
 
103
- attr_reader :parent, :name, :args, :options
101
+ attr_reader :drawable, :parent, :name, :args, :options, :shapes
104
102
 
105
103
  def initialize(parent, keyword, *args, &property_block)
106
104
  @parent = parent
105
+ @drawable = @parent.is_a?(Drawable) ? @parent : @parent.drawable
107
106
  @name = keyword
108
107
  @options = self.class.arg_options(args, extract: true)
109
108
  @method_name = self.class.method_name(keyword, @options)
110
109
  @args = args
111
110
  @properties = {}
111
+ @shapes = [] # nested shapes
112
112
  @options.reject {|key, value| %w[fill gradient round].include?(key.to_s)}.each do |property, property_args|
113
113
  @properties[property] = property_args
114
114
  end
@@ -116,13 +116,19 @@ module Glimmer
116
116
  post_add_content if property_block.nil?
117
117
  end
118
118
 
119
+ def add_shape(shape)
120
+ @shapes << shape
121
+ end
122
+
119
123
  def draw?
120
124
  !fill?
121
125
  end
126
+ alias drawn? draw?
122
127
 
123
128
  def fill?
124
129
  @options[:fill]
125
130
  end
131
+ alias filled? fill?
126
132
 
127
133
  def gradient?
128
134
  @options[:gradient]
@@ -132,24 +138,32 @@ module Glimmer
132
138
  @options[:round]
133
139
  end
134
140
 
135
- # subclasses (like polygon) may override to indicate if a point x,y coordinates fall inside the shape
136
- # has a default implementation for rectangle and oval
141
+ # subclasses (like polygon) may override to indicate if a point x,y coordinates falls inside the shape
142
+ # some shapes may choose to provide a fuzz factor to make usage of this method for mouse clicking more user friendly
143
+ def contain?(x, y)
144
+ # assume a rectangular filled shape by default (works for several shapes like image, text, and focus)
145
+ if respond_to?(:x) && respond_to?(:y) && respond_to?(:width) && respond_to?(:height) && self.x && self.y && width && height
146
+ x.between?(self.x, self.x + width) && y.between?(self.y, self.y + height)
147
+ else
148
+ false # subclasses must provide implementation
149
+ end
150
+ end
151
+
152
+ # 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
153
+ # some shapes may choose to provide a fuzz factor to make usage of this method for mouse clicking more user friendly
137
154
  def include?(x, y)
138
- case @name
139
- when 'rectangle', 'oval', 'arc'
140
- self_x = self.x
141
- self_y = self.y
142
- width = self.width
143
- height = self.height
144
- x.between?(self_x, self_x + width) && y.between?(self_y, self_y + height)
155
+ # assume a rectangular shape by default
156
+ if respond_to?(:x) && respond_to?(:y) && respond_to?(:width) && respond_to?(:height)
157
+ contain?(x, y)
145
158
  else
146
- false
159
+ false # subclasses must provide implementation
147
160
  end
148
161
  end
149
162
 
163
+ # moves by x delta and y delta. Subclasses must implement
164
+ # provdies a default implementation that assumes moving x and y is sufficient by default (not for polygons though, which must override)
150
165
  def move_by(x_delta, y_delta)
151
- case @name
152
- when 'rectangle', 'oval', 'arc'
166
+ if respond_to?(:x) && respond_to?(:y) && x && y
153
167
  self.x += x_delta
154
168
  self.y += y_delta
155
169
  end
@@ -166,7 +180,7 @@ module Glimmer
166
180
  def post_add_content
167
181
  unless @content_added
168
182
  amend_method_name_options_based_on_properties!
169
- @parent.setup_shape_painting unless @parent.is_a?(ImageProxy)
183
+ @drawable.setup_shape_painting unless @drawable.is_a?(ImageProxy)
170
184
  @content_added = true
171
185
  end
172
186
  end
@@ -180,7 +194,7 @@ module Glimmer
180
194
  if ['setBackground', 'setForeground'].include?(method_name.to_s) && args.first.is_a?(Array)
181
195
  args[0] = ColorProxy.new(args[0])
182
196
  end
183
- if args.first.is_a?(Symbol) || args.first.is_a?(String)
197
+ if args.first.is_a?(Symbol) || args.first.is_a?(::String)
184
198
  if the_java_method.parameter_types.first == Color.java_class
185
199
  args[0] = ColorProxy.new(args[0])
186
200
  end
@@ -201,11 +215,11 @@ module Glimmer
201
215
  args[0] = args[0].swt_transform
202
216
  end
203
217
  if ['setBackgroundPattern', 'setForegroundPattern'].include?(method_name.to_s)
204
- @parent.requires_shape_disposal = true
218
+ @drawable.requires_shape_disposal = true
205
219
  args = args.first if args.first.is_a?(Array)
206
220
  args.each_with_index do |arg, i|
207
221
  arg = ColorProxy.new(arg.red, arg.green, arg.blue) if arg.is_a?(RGB)
208
- arg = ColorProxy.new(arg) if arg.is_a?(Symbol) || arg.is_a?(String)
222
+ arg = ColorProxy.new(arg) if arg.is_a?(Symbol) || arg.is_a?(::String)
209
223
  arg = arg.swt_color if arg.is_a?(ColorProxy)
210
224
  args[i] = arg
211
225
  end
@@ -229,7 +243,7 @@ module Glimmer
229
243
  @args[1..-1] = []
230
244
  end
231
245
  if @name == 'image'
232
- if @args.first.is_a?(String)
246
+ if @args.first.is_a?(::String)
233
247
  @args[0] = ImageProxy.new(@args[0])
234
248
  end
235
249
  if @args.first.is_a?(ImageProxy)
@@ -240,7 +254,7 @@ module Glimmer
240
254
  end
241
255
  end
242
256
  if @name == 'text'
243
- if @args[3].is_a?(Symbol) || @args[3].is_a?(String)
257
+ if @args[3].is_a?(Symbol) || @args[3].is_a?(::String)
244
258
  @args[3] = [@args[3]]
245
259
  end
246
260
  if @args[3].is_a?(Array)
@@ -256,12 +270,12 @@ module Glimmer
256
270
  if @name.include?('rectangle') && round? && @args.size.between?(4, 5)
257
271
  (6 - @args.size).times {@args << 60}
258
272
  elsif @name.include?('rectangle') && gradient? && @args.size == 4
259
- @args << true
260
- elsif (@name.include?('text') || @name.include?('String')) && !@properties.keys.map(&:to_s).include?('background') && @args.size == 3
261
- @args << true
273
+ @args << true # vertical is true by default
274
+ elsif (@name.include?('text') || @name.include?('string')) && !@properties.keys.map(&:to_s).include?('background') && @args.size == 3
275
+ @args << true # is_transparent is true by default
262
276
  end
263
277
  if @name.include?('image')
264
- @parent.requires_shape_disposal = true
278
+ @drawable.requires_shape_disposal = true
265
279
  if @args.size == 1
266
280
  @args[1] = 0
267
281
  @args[2] = 0
@@ -282,7 +296,7 @@ module Glimmer
282
296
 
283
297
  def amend_method_name_options_based_on_properties!
284
298
  return if @name == 'point'
285
- if @name != 'text' && has_some_background? && !has_some_foreground?
299
+ if @name != 'text' && @name != 'string' && has_some_background? && !has_some_foreground?
286
300
  @options[:fill] = true
287
301
  elsif !has_some_background? && has_some_foreground?
288
302
  @options[:fill] = false
@@ -328,15 +342,16 @@ module Glimmer
328
342
  else
329
343
  @properties[ruby_attribute_getter(attribute_name)] = args
330
344
  end
331
- if @content_added && !@parent.is_disposed
345
+ if @content_added && !@drawable.is_disposed
332
346
  @calculated_paint_args = false
333
- @parent.redraw
347
+ @drawable.redraw
334
348
  end
335
349
  end
336
350
 
337
351
  def get_attribute(attribute_name)
338
352
  if parameter_name?(attribute_name)
339
- @args[parameter_index(attribute_name)]
353
+ arg_index = parameter_index(attribute_name)
354
+ @args[arg_index] if arg_index
340
355
  else
341
356
  @properties.symbolize_keys[attribute_name.to_s.to_sym]
342
357
  end
@@ -405,6 +420,7 @@ module Glimmer
405
420
  args.first.swt_transform.dispose
406
421
  end
407
422
  end
423
+ self.extent = paint_event.gc.send("#{@name}Extent", *(([string, flags] if respond_to?(:flags)).compact)) if ['text', 'string'].include?(@name)
408
424
  paint_event.gc.send(@method_name, *@args)
409
425
  rescue => e
410
426
  Glimmer::Config.logger.error {"Error encountered in painting shape: #{self.inspect}"}
@@ -420,7 +436,7 @@ module Glimmer
420
436
  if @properties[:foreground].is_a?(Array)
421
437
  @properties[:foreground] = ColorProxy.new(@properties[:foreground], ensure_bounds: false)
422
438
  end
423
- if @properties[:foreground].is_a?(Symbol) || @properties[:foreground].is_a?(String)
439
+ if @properties[:foreground].is_a?(Symbol) || @properties[:foreground].is_a?(::String)
424
440
  @properties[:foreground] = ColorProxy.new(@properties[:foreground], ensure_bounds: false)
425
441
  end
426
442
  if @properties[:foreground].is_a?(ColorProxy)
@@ -428,14 +444,14 @@ module Glimmer
428
444
  end
429
445
  end
430
446
  else
431
- @properties['background'] = [@parent.background] if fill? && !has_some_background?
432
- @properties['foreground'] = [@parent.foreground] if @parent.respond_to?(:foreground) && draw? && !has_some_foreground?
447
+ @properties['background'] = [@drawable.background] if fill? && !has_some_background?
448
+ @properties['foreground'] = [@drawable.foreground] if @drawable.respond_to?(:foreground) && draw? && !has_some_foreground?
433
449
  # TODO regarding alpha, make sure to reset it to parent stored alpha once we allow setting shape properties on parents directly without shapes
434
450
  @properties['alpha'] ||= [255]
435
- @properties['font'] = [@parent.font] if @parent.respond_to?(:font) && draw? && !@properties.keys.map(&:to_s).include?('font')
451
+ @properties['font'] = [@drawable.font] if @drawable.respond_to?(:font) && draw? && !@properties.keys.map(&:to_s).include?('font')
436
452
  # TODO regarding transform, make sure to reset it to parent stored alpha once we allow setting shape properties on parents directly without shapes
437
453
  # Also do that with all future-added properties
438
- @properties['transform'] = [nil] if @parent.respond_to?(:transform) && !@properties.keys.map(&:to_s).include?('transform')
454
+ @properties['transform'] = [nil] if @drawable.respond_to?(:transform) && !@properties.keys.map(&:to_s).include?('transform')
439
455
  @properties.each do |property, args|
440
456
  method_name = attribute_setter(property)
441
457
  converted_args = apply_property_arg_conversions(method_name, property, args)
@@ -36,6 +36,23 @@ module Glimmer
36
36
  def parameter_names
37
37
  [:x, :y, :width, :height, :start_angle, :arc_angle]
38
38
  end
39
+
40
+ # checks if shape contains the point denoted by x and y
41
+ def contain?(x, y)
42
+ shape_geometry = java.awt.geom.Arc2D::Double.new(self.x, self.y, width, height, start_angle, arc_angle, java.awt.geom.Arc2D::PIE)
43
+ shape_geometry.contains(x, y)
44
+ end
45
+
46
+ def include?(x, y)
47
+ if filled?
48
+ contain?(x, y)
49
+ else
50
+ # give it some fuzz to allow a larger region around the drawn oval to accept including a point (helps with mouse clickability on a shape)
51
+ outer_shape_geometry = java.awt.geom.Arc2D::Double.new(self.x, self.y, width + 3, height + 3, start_angle, arc_angle, java.awt.geom.Arc2D::PIE)
52
+ inner_shape_geometry = java.awt.geom.Arc2D::Double.new(self.x, self.y, width - 3, height - 3, start_angle, arc_angle, java.awt.geom.Arc2D::PIE)
53
+ outer_shape_geometry.contains(x, y) && !inner_shape_geometry.contains(x, y)
54
+ end
55
+ end
39
56
  end
40
57
  end
41
58
  end
@@ -29,9 +29,9 @@ require 'glimmer/swt/transform_proxy'
29
29
  module Glimmer
30
30
  module SWT
31
31
  module Custom
32
- # Represents a shape (graphics) to be drawn on a control/widget/canvas/display
33
- # That is because Shape is drawn on a parent as graphics and doesn't have an SWT widget for itself
34
32
  class Shape
33
+ # Represents a focus shape to be drawn on a control/widget/canvas/display
34
+ # Helps highlight focus on another selected shape
35
35
  class Focus < Shape
36
36
  def parameter_names
37
37
  [:x, :y, :width, :height]
@@ -62,13 +62,26 @@ module Glimmer
62
62
  end
63
63
  end
64
64
 
65
+ def x
66
+ dest_x || get_attribute('x')
67
+ end
68
+
69
+ def y
70
+ dest_y || get_attribute('y')
71
+ end
72
+
73
+ def width
74
+ dest_width || image.bounds.width
75
+ end
76
+
77
+ def height
78
+ dest_height || image.bounds.height
79
+ end
80
+
65
81
  def include?(x, y)
66
- self_x = dest_x || self.x
67
- self_y = dest_y || self.y
68
- width = dest_width || image.bounds.width
69
- height = dest_height || image.bounds.height
70
- x.between?(self_x, self_x + width) && y.between?(self_y, self_y + height)
82
+ x.between?(self.x, self.x + width) && y.between?(self.y, self.y + height)
71
83
  end
84
+ alias contain? include?
72
85
 
73
86
  def move_by(x_delta, y_delta)
74
87
  if dest_x
@@ -33,17 +33,24 @@ module Glimmer
33
33
  # That is because Shape is drawn on a parent as graphics and doesn't have an SWT widget for itself
34
34
  class Shape
35
35
  class Line < Shape
36
+ class << self
37
+ def include?(x1, y1, x2, y2, x, y)
38
+ distance1 = Math.sqrt((x - x1)**2 + (y - y1)**2)
39
+ distance2 = Math.sqrt((x2 - x)**2 + (y2 - y)**2)
40
+ distance = Math.sqrt((x2 - x1)**2 + (y2 - y1)**2)
41
+ (distance1 + distance2).to_i == distance.to_i
42
+ end
43
+ end
44
+
36
45
  def parameter_names
37
46
  [:x1, :y1, :x2, :y2]
38
47
  end
39
48
 
40
49
  def include?(x, y)
41
50
  # TODO must account for line width
42
- distance1 = Math.sqrt((x - x1)**2 + (y - y1)**2)
43
- distance2 = Math.sqrt((x2 - x)**2 + (y2 - y)**2)
44
- distance = Math.sqrt((x2 - x1)**2 + (y2 - y1)**2)
45
- (distance1 + distance2).to_i == distance.to_i
51
+ Line.include?(x1, y1, x2, y2, x, y)
46
52
  end
53
+ alias contain? include?
47
54
 
48
55
  def move_by(x_delta, y_delta)
49
56
  self.x1 += x_delta
@@ -36,6 +36,24 @@ module Glimmer
36
36
  def parameter_names
37
37
  [:x, :y, :width, :height]
38
38
  end
39
+
40
+ # checks if shape contains the point denoted by x and y
41
+ def contain?(x, y)
42
+ shape_geometry = java.awt.geom.Ellipse2D::Double.new(self.x, self.y, width, height)
43
+ shape_geometry.contains(x, y)
44
+ end
45
+
46
+ # checks if drawn or filled oval includes the point denoted by x and y (if drawn, it only returns true if point lies on the edge)
47
+ def include?(x, y)
48
+ if filled?
49
+ contain?(x, y)
50
+ else
51
+ # give it some fuzz to allow a larger region around the drawn oval to accept including a point (helps with mouse clickability on a shape)
52
+ outer_shape_geometry = java.awt.geom.Ellipse2D::Double.new(self.x - 3, self.y - 3, width + 6, height + 6)
53
+ inner_shape_geometry = java.awt.geom.Ellipse2D::Double.new(self.x + 3, self.y + 3, width - 6, height - 6)
54
+ outer_shape_geometry.contains(x, y) && !inner_shape_geometry.contains(x, y)
55
+ end
56
+ end
39
57
  end
40
58
  end
41
59
  end
@@ -38,8 +38,10 @@ module Glimmer
38
38
  end
39
39
 
40
40
  def include?(x, y)
41
+ # give it some fuzz (helps makes mouse clicking easier)
41
42
  x.to_i.between?(self.x.to_i - 2, self.x.to_i + 2) && y.to_i.between?(self.y.to_i - 2, self.y.to_i + 2)
42
43
  end
44
+ alias contain? include?
43
45
 
44
46
  def move_by(x_delta, y_delta)
45
47
  self.x += x_delta
@@ -37,30 +37,30 @@ module Glimmer
37
37
  [:point_array]
38
38
  end
39
39
 
40
- def size
41
- point_array.size / 2
40
+ def point_count
41
+ point_array.count / 2
42
42
  end
43
43
 
44
44
  def [](index)
45
- index = 0 if index == size
45
+ index = 0 if index == point_count
46
46
  org.eclipse.swt.graphics.Point.new(point_array[index * 2], point_array[index * 2 + 1])
47
47
  end
48
48
 
49
+ def x_array
50
+ point_array.each_with_index.select {|pair| pair.last.even?}.map(&:first)
51
+ end
52
+
53
+ def y_array
54
+ point_array.each_with_index.select {|pair| pair.last.odd?}.map(&:first)
55
+ end
56
+
57
+ def point_xy_array
58
+ x_array.zip(y_array)
59
+ end
60
+
49
61
  def include?(x, y)
50
- c = false
51
- i = -1
52
- j = self.size
53
- while (i += 1) < (self.size + 1)
54
- if ((self[i].y <= y && y < self[j].y) ||
55
- (self[j].y <= y && y < self[i].y))
56
- if (x < (self[j].x - self[i].x) * (y - self[i].y) /
57
- (self[j].y - self[i].y) + self[i].x)
58
- c = !c
59
- end
60
- j = i
61
- end
62
- end
63
- c
62
+ shape_geometry = java.awt.Polygon.new(x_array.to_java(:int), y_array.to_java(:int), point_count)
63
+ shape_geometry.contains(x, y)
64
64
  end
65
65
 
66
66
  def move_by(x_delta, y_delta)
@@ -37,30 +37,31 @@ module Glimmer
37
37
  [:point_array]
38
38
  end
39
39
 
40
- def size
41
- point_array.size / 2
40
+ def point_count
41
+ point_array.count / 2
42
+ end
43
+
44
+ def x_array
45
+ point_array.each_with_index.select {|pair| pair.last.even?}.map(&:first)
46
+ end
47
+
48
+ def y_array
49
+ point_array.each_with_index.select {|pair| pair.last.odd?}.map(&:first)
50
+ end
51
+
52
+ def point_xy_array
53
+ x_array.zip(y_array)
42
54
  end
43
55
 
44
56
  def [](index)
45
- index = 0 if index == size
57
+ index = 0 if index == point_count
46
58
  org.eclipse.swt.graphics.Point.new(point_array[index * 2], point_array[index * 2 + 1])
47
59
  end
48
60
 
49
61
  def include?(x, y)
50
- c = false
51
- i = -1
52
- j = self.size
53
- while (i += 1) < (self.size + 1)
54
- if ((self[i].y <= y && y < self[j].y) ||
55
- (self[j].y <= y && y < self[i].y))
56
- if (x < (self[j].x - self[i].x) * (y - self[i].y) /
57
- (self[j].y - self[i].y) + self[i].x)
58
- c = !c
59
- end
60
- j = i
61
- end
62
- end
63
- c
62
+ comparison_lines = point_xy_array.zip(point_xy_array.rotate(1))
63
+ comparison_lines.pop # ignore last pair since you don't want to compare last point with first point
64
+ comparison_lines.any? {|line| Line.include?(line.first.first, line.first.last, line.last.first, line.last.last, x, y)}
64
65
  end
65
66
 
66
67
  def move_by(x_delta, y_delta)
@@ -80,6 +80,20 @@ module Glimmer
80
80
  end
81
81
  end
82
82
 
83
+ def point_xy_array
84
+ [[x, y], [x + width, y], [x + width, y + height], [x, y + height]]
85
+ end
86
+
87
+ # checks if drawn or filled rectangle includes the point denoted by x and y (if drawn, it only returns true if point lies on the edge)
88
+ def include?(x, y)
89
+ if filled?
90
+ contain?(x, y)
91
+ else
92
+ comparison_lines = point_xy_array.zip(point_xy_array.rotate(1))
93
+ comparison_lines.any? {|line| Line.include?(line.first.first, line.first.last, line.last.first, line.last.last, x, y)}
94
+ end
95
+ end
96
+
83
97
  end
84
98
  end
85
99
  end
@@ -33,6 +33,8 @@ module Glimmer
33
33
  # That is because Shape is drawn on a parent as graphics and doesn't have an SWT widget for itself
34
34
  class Shape
35
35
  class Text < Shape
36
+ attr_accessor :extent
37
+
36
38
  def parameter_names
37
39
  @parameter_names || text_parameter_names
38
40
  end
@@ -43,15 +45,15 @@ module Glimmer
43
45
  end
44
46
 
45
47
  def text_parameter_names
46
- [:text, :x, :y]
48
+ [:string, :x, :y]
47
49
  end
48
50
 
49
51
  def text_transparent_parameter_names
50
- [:text, :x, :y, :is_transparent]
52
+ [:string, :x, :y, :is_transparent]
51
53
  end
52
54
 
53
55
  def text_flags_parameter_names
54
- [:text, :x, :y, :flags]
56
+ [:string, :x, :y, :flags]
55
57
  end
56
58
 
57
59
  def set_parameter_attribute(attribute_name, *args)
@@ -66,7 +68,17 @@ module Glimmer
66
68
  super
67
69
  end
68
70
 
71
+ def width
72
+ extent&.x
73
+ end
74
+
75
+ def height
76
+ extent&.y
77
+ end
78
+
69
79
  end
80
+
81
+ String = Text
70
82
  end
71
83
  end
72
84
  end
@@ -20,7 +20,7 @@
20
20
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
21
 
22
22
  require 'glimmer/swt/display_proxy'
23
- require 'glimmer/swt/properties'
23
+ require 'glimmer/swt/proxy_properties'
24
24
  require 'glimmer/swt/custom/shape'
25
25
 
26
26
  module Glimmer
@@ -29,7 +29,7 @@ module Glimmer
29
29
  #
30
30
  # Follows the Proxy Design Pattern
31
31
  class TransformProxy
32
- include Properties
32
+ include ProxyProperties
33
33
 
34
34
  include_package 'org.eclipse.swt.graphics'
35
35
  include_package 'org.eclipse.swt.widgets'
@@ -80,12 +80,28 @@ module Glimmer
80
80
  @swt_transform
81
81
  end
82
82
 
83
+ def has_attribute?(attribute_name, *args)
84
+ Glimmer::SWT::DisplayProxy.instance.auto_exec { @swt_transform.respond_to?(attribute_name) } || super
85
+ end
86
+
87
+ def set_attribute(attribute_name, *args)
88
+ if @swt_transform.respond_to?(attribute_name)
89
+ Glimmer::SWT::DisplayProxy.instance.auto_exec { @swt_transform.send(attribute_name, *args) }
90
+ else
91
+ super
92
+ end
93
+ end
94
+
83
95
  def method_missing(method_name, *args, &block)
84
96
  result = Glimmer::SWT::DisplayProxy.instance.auto_exec { @swt_transform.send(method_name, *args, &block) }
85
97
  result.nil? ? self : result
86
98
  rescue => e
87
- Glimmer::Config.logger.debug {"Neither MessageBoxProxy nor #{@swt_transform.class.name} can handle the method ##{method}"}
88
- super
99
+ begin
100
+ super
101
+ rescue Exception => inner_e
102
+ Glimmer::Config.logger.error {"Neither TransformProxy nor #{@swt_transform.class.name} can handle the method ##{method}"}
103
+ Glimmer::Config.logger.error {e.full_message}
104
+ end
89
105
  end
90
106
 
91
107
  def respond_to?(method, *args, &block)
@@ -50,7 +50,7 @@ module Glimmer
50
50
  DEFAULT_STYLES = {
51
51
  'arrow' => [:arrow],
52
52
  'button' => [:push],
53
- 'canvas' => ([:double_buffered] if OS.windows?),
53
+ 'canvas' => ([:double_buffered] unless OS.mac?),
54
54
  'checkbox' => [:check],
55
55
  'check' => [:check],
56
56
  'drag_source' => [:drop_copy],
@@ -36,8 +36,6 @@ class HelloCanvas
36
36
  @canvas = canvas {
37
37
  background :yellow
38
38
  rectangle(0, 0, 220, 400) {
39
- transform {
40
- }
41
39
  background :red
42
40
  }
43
41
  rectangle(50, 20, 300, 150, 30, 50) {
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glimmer-dsl-swt
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.18.5.1
4
+ version: 4.18.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - AndyMaleh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-02-23 00:00:00.000000000 Z
11
+ date: 2021-02-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement