glimmer-dsl-swt 4.18.5.5 → 4.18.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/README.md +4 -4
- data/VERSION +1 -1
- data/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md +35 -0
- data/glimmer-dsl-swt.gemspec +8 -3
- data/lib/glimmer/swt/custom/shape.rb +14 -4
- data/lib/glimmer/swt/custom/shape/cubic.rb +108 -0
- data/lib/glimmer/swt/custom/shape/line.rb +37 -4
- data/lib/glimmer/swt/custom/shape/path.rb +197 -0
- data/lib/glimmer/swt/custom/shape/path_segment.rb +86 -0
- data/lib/glimmer/swt/custom/shape/point.rb +33 -0
- data/lib/glimmer/swt/custom/shape/polygon.rb +2 -2
- data/lib/glimmer/swt/custom/shape/quad.rb +104 -0
- data/lib/glimmer/swt/proxy_properties.rb +1 -1
- data/samples/elaborate/mandelbrot_fractal.rb +1 -1
- data/samples/hello/hello_canvas_path.rb +223 -0
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2b3fe4c65726425f091b0660bbf4dd4c55543c5c515bed56487aacb7e1458b7e
|
4
|
+
data.tar.gz: 71580957a753685f1eac22fb60ea13c2e2f289bb47017293980d4d06d78d5eec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 974be0abde39dbacdabe5d560c319a049907791e280f03aa6192e945b64057f814cbc57346f51cead9627ee98db52276367f4ca1f8f497b2882846d280a7f103
|
7
|
+
data.tar.gz: 7b9c169a4705c8bfa390ef440e31100e40560eabca4f204d18d8e5197174d9834827fd9f76907384c2d8e3873f968c11b94f6a985c3a43eda0bbf9b8fc7b8bc9
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
### 4.18.6.0
|
4
|
+
|
5
|
+
- 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)
|
6
|
+
- 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.
|
7
|
+
- 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`
|
8
|
+
- Support `Shape#content {}` method just like `WidgetProxy#content` to enable reopening and adding nested shapes at runtime after initial construction
|
9
|
+
- Support a path containing a `quad` bezier curve with `point_array` property
|
10
|
+
- Support a path containing a `cubic` bezier curve with `point_array` property
|
11
|
+
|
3
12
|
### 4.18.5.5
|
4
13
|
|
5
14
|
- Automatically recalculate default size (width/height) to accomodate nested shapes when changing x/y/width/height sticking out of parent from right or bottom.
|
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.0
|
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)
|
@@ -13,7 +13,7 @@
|
|
13
13
|
[<img src="https://covers.oreillystatic.com/images/9780596519650/lrg.jpg" width=105 /><br />
|
14
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)
|
15
15
|
|
16
|
-
[Glimmer DSL for SWT](https://rubygems.org/gems/glimmer-dsl-swt) 4.18.
|
16
|
+
[Glimmer DSL for SWT](https://rubygems.org/gems/glimmer-dsl-swt) 4.18.6.0 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
17
|
|
18
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
19
|
|
@@ -340,7 +340,7 @@ jgem install glimmer-dsl-swt
|
|
340
340
|
|
341
341
|
Or this command if you want a specific version:
|
342
342
|
```
|
343
|
-
jgem install glimmer-dsl-swt -v 4.18.
|
343
|
+
jgem install glimmer-dsl-swt -v 4.18.6.0
|
344
344
|
```
|
345
345
|
|
346
346
|
`jgem` is JRuby's version of `gem` command.
|
@@ -358,7 +358,7 @@ Note: if you're using activerecord or activesupport, keep in mind that Glimmer u
|
|
358
358
|
|
359
359
|
Add the following to `Gemfile`:
|
360
360
|
```
|
361
|
-
gem 'glimmer-dsl-swt', '~> 4.18.
|
361
|
+
gem 'glimmer-dsl-swt', '~> 4.18.6.0'
|
362
362
|
```
|
363
363
|
|
364
364
|
And, then run:
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
4.18.
|
1
|
+
4.18.6.0
|
@@ -41,6 +41,7 @@ This guide should help you get started with Glimmer DSL for SWT. For more advanc
|
|
41
41
|
- [Shapes inside an Image](#shapes-inside-an-image)
|
42
42
|
- [Canvas Shape API](#canvas-shape-api)
|
43
43
|
- [Pixel Graphics](#pixel-graphics)
|
44
|
+
- [Canvas Path DSL](#canvas-path-dsl)
|
44
45
|
- [Canvas Transform DSL](#canvas-transform-dsl)
|
45
46
|
- [Top-Level Transform Fluent Interface](#top-level-transform-fluent-interface)
|
46
47
|
- [Canvas Animation DSL](#canvas-animation-dsl)
|
@@ -1953,6 +1954,40 @@ shell {
|
|
1953
1954
|
|
1954
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.
|
1955
1956
|
|
1957
|
+
### Canvas Path DSL
|
1958
|
+
|
1959
|
+
**(EARLY ALPHA FEATURE)**
|
1960
|
+
|
1961
|
+
Unlike common imperative GUI charting 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 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
|
+
shell {
|
1971
|
+
text 'Canvas Path DSL Example'
|
1972
|
+
minimum_size 300, 300
|
1973
|
+
|
1974
|
+
canvas {
|
1975
|
+
path {
|
1976
|
+
foreground :black
|
1977
|
+
point(0, 0)
|
1978
|
+
250.times {|n|
|
1979
|
+
cubic(n + n%30, n+ n%50, 40, 40, 70, 70, n + 20 + n%30, n%30*-1 * n%50)
|
1980
|
+
}
|
1981
|
+
}
|
1982
|
+
}
|
1983
|
+
|
1984
|
+
}.open
|
1985
|
+
```
|
1986
|
+
|
1987
|
+
Learn more at the [Hello, Canvas Path! Sample](/samples/hello/hello_canvas_path.rb).
|
1988
|
+
|
1989
|
+
![Hello Canvas Path Sample](/images/glimmer-hello-canvas-path.gif)
|
1990
|
+
|
1956
1991
|
### Canvas Transform DSL
|
1957
1992
|
|
1958
1993
|
**(ALPHA FEATURE)**
|
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.0 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.0"
|
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-02-28"
|
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",
|
@@ -180,6 +184,7 @@ Gem::Specification.new do |s|
|
|
180
184
|
"samples/hello/hello_button.rb",
|
181
185
|
"samples/hello/hello_canvas.rb",
|
182
186
|
"samples/hello/hello_canvas_animation.rb",
|
187
|
+
"samples/hello/hello_canvas_path.rb",
|
183
188
|
"samples/hello/hello_canvas_transform.rb",
|
184
189
|
"samples/hello/hello_checkbox.rb",
|
185
190
|
"samples/hello/hello_checkbox_group.rb",
|
@@ -74,7 +74,8 @@ module Glimmer
|
|
74
74
|
end
|
75
75
|
|
76
76
|
def valid?(parent, keyword, *args, &block)
|
77
|
-
gc_instance_methods.include?(method_name(keyword, arg_options(args)))
|
77
|
+
gc_instance_methods.include?(method_name(keyword, arg_options(args))) ||
|
78
|
+
constants.include?(keyword.to_s.camelcase(:upper).to_sym)
|
78
79
|
end
|
79
80
|
|
80
81
|
def gc_instance_methods
|
@@ -225,6 +226,14 @@ module Glimmer
|
|
225
226
|
end
|
226
227
|
end
|
227
228
|
|
229
|
+
def content(&block)
|
230
|
+
Glimmer::SWT::DisplayProxy.instance.auto_exec do
|
231
|
+
Glimmer::DSL::Engine.add_content(self, Glimmer::DSL::SWT::ShapeExpression.new, &block)
|
232
|
+
calculated_args_changed!(children: false)
|
233
|
+
drawable.redraw unless drawable.is_a?(ImageProxy)
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
228
237
|
def has_some_background?
|
229
238
|
@properties.keys.map(&:to_s).include?('background') || @properties.keys.map(&:to_s).include?('background_pattern')
|
230
239
|
end
|
@@ -234,11 +243,11 @@ module Glimmer
|
|
234
243
|
end
|
235
244
|
|
236
245
|
def post_add_content
|
237
|
-
|
246
|
+
# unless @content_added # TODO delete if no longer needed
|
238
247
|
amend_method_name_options_based_on_properties!
|
239
248
|
@drawable.setup_shape_painting unless @drawable.is_a?(ImageProxy)
|
240
249
|
@content_added = true
|
241
|
-
|
250
|
+
# end
|
242
251
|
end
|
243
252
|
|
244
253
|
def apply_property_arg_conversions(method_name, property, args)
|
@@ -491,6 +500,7 @@ module Glimmer
|
|
491
500
|
end
|
492
501
|
|
493
502
|
def dispose(dispose_images: true, dispose_patterns: true)
|
503
|
+
shapes.each { |shape| shape.is_a?(Shape::Path) && shape.dispose }
|
494
504
|
if dispose_patterns
|
495
505
|
@background_pattern&.dispose
|
496
506
|
@background_pattern = nil
|
@@ -818,7 +828,7 @@ module Glimmer
|
|
818
828
|
# TODO regarding alpha, make sure to reset it to parent stored alpha once we allow setting shape properties on parents directly without shapes
|
819
829
|
@properties['alpha'] ||= [255]
|
820
830
|
@properties['font'] = [@drawable.font] if @drawable.respond_to?(:font) && draw? && !@properties.keys.map(&:to_s).include?('font')
|
821
|
-
# TODO regarding transform, make sure to reset it to parent stored
|
831
|
+
# TODO regarding transform, make sure to reset it to parent stored transform once we allow setting shape properties on parents directly without shapes
|
822
832
|
# Also do that with all future-added properties
|
823
833
|
@properties['transform'] = [nil] if @drawable.respond_to?(:transform) && !@properties.keys.map(&:to_s).include?('transform')
|
824
834
|
@properties.each do |property, args|
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# Copyright (c) 2007-2021 Andy Maleh
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
# a copy of this software and associated documentation files (the
|
5
|
+
# "Software"), to deal in the Software without restriction, including
|
6
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
# the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be
|
12
|
+
# included in all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
22
|
+
require 'glimmer/swt/custom/shape'
|
23
|
+
require 'glimmer/swt/custom/shape/path_segment'
|
24
|
+
require 'glimmer/swt/swt_proxy'
|
25
|
+
require 'glimmer/swt/display_proxy'
|
26
|
+
require 'glimmer/swt/color_proxy'
|
27
|
+
require 'glimmer/swt/font_proxy'
|
28
|
+
require 'glimmer/swt/transform_proxy'
|
29
|
+
|
30
|
+
module Glimmer
|
31
|
+
module SWT
|
32
|
+
module Custom
|
33
|
+
# Represents a shape (graphics) to be drawn on a control/widget/canvas/display
|
34
|
+
# That is because Shape is drawn on a parent as graphics and doesn't have an SWT widget for itself
|
35
|
+
class Shape
|
36
|
+
class Cubic < Path
|
37
|
+
def parameter_names
|
38
|
+
[:point_array]
|
39
|
+
end
|
40
|
+
|
41
|
+
def geometry
|
42
|
+
if @point_array != @geometry_point_array
|
43
|
+
@geometry_point_array = @point_array
|
44
|
+
@geometry = Java::JavaAwtGeom::Path2D::Double.new
|
45
|
+
@geometry.send(path_segment_geometry_method_name, *path_segment_geometry_args)
|
46
|
+
end
|
47
|
+
@geometry
|
48
|
+
end
|
49
|
+
|
50
|
+
def contain?(x, y)
|
51
|
+
include?(x, y, filled: true)
|
52
|
+
end
|
53
|
+
|
54
|
+
# 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)
|
55
|
+
def include?(x, y, filled: nil)
|
56
|
+
filled = filled? if filled.nil?
|
57
|
+
makeshift_gc = org.eclipse.swt.graphics.GC.new(Glimmer::SWT::DisplayProxy.instance.swt_display)
|
58
|
+
swt_path = org.eclipse.swt.graphics.Path.new(Glimmer::SWT::DisplayProxy.instance.swt_display)
|
59
|
+
the_path_segment_args = path_segment_args.dup
|
60
|
+
if previous_point_connected?
|
61
|
+
the_previous_path_segment = previous_path_segment
|
62
|
+
swt_path.moveTo(the_previous_path_segment.x, the_previous_path_segment.y)
|
63
|
+
else
|
64
|
+
swt_path.moveTo(the_path_segment_args.shift, the_path_segment_args.shift)
|
65
|
+
end
|
66
|
+
swt_path.curveTo(*the_path_segment_args)
|
67
|
+
swt_path.contains(x.to_f, y.to_f, makeshift_gc, !filled)
|
68
|
+
ensure
|
69
|
+
swt_path.dispose
|
70
|
+
end
|
71
|
+
|
72
|
+
def move_by(x_delta, y_delta)
|
73
|
+
the_point_array = @args.compact
|
74
|
+
the_point_array = the_point_array.first if the_point_array.first.is_a?(Array)
|
75
|
+
self.point_array = the_point_array.each_with_index.map {|coordinate, i| i.even? ? coordinate + x_delta : coordinate + y_delta}
|
76
|
+
end
|
77
|
+
|
78
|
+
def path_segment_method_name
|
79
|
+
'cubicTo'
|
80
|
+
end
|
81
|
+
|
82
|
+
def path_segment_args
|
83
|
+
# TODO make args auto-infer control points if previous_point_connected is true or if there is only a point_array with 1 point
|
84
|
+
@args.to_a
|
85
|
+
end
|
86
|
+
|
87
|
+
def path_segment_geometry_method_name
|
88
|
+
'curveTo'
|
89
|
+
end
|
90
|
+
|
91
|
+
def previous_point_connected?
|
92
|
+
@args.compact.count <= 6 && !first_path_segment?
|
93
|
+
end
|
94
|
+
|
95
|
+
def eql?(other)
|
96
|
+
point_array == (other && other.respond_to?(:point_array) && other.point_array)
|
97
|
+
end
|
98
|
+
alias == eql?
|
99
|
+
|
100
|
+
def hash
|
101
|
+
point_array.hash
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -20,6 +20,7 @@
|
|
20
20
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
21
|
|
22
22
|
require 'glimmer/swt/custom/shape'
|
23
|
+
require 'glimmer/swt/custom/shape/path_segment'
|
23
24
|
require 'glimmer/swt/swt_proxy'
|
24
25
|
require 'glimmer/swt/display_proxy'
|
25
26
|
require 'glimmer/swt/color_proxy'
|
@@ -33,6 +34,8 @@ module Glimmer
|
|
33
34
|
# That is because Shape is drawn on a parent as graphics and doesn't have an SWT widget for itself
|
34
35
|
class Shape
|
35
36
|
class Line < Shape
|
37
|
+
include PathSegment
|
38
|
+
|
36
39
|
class << self
|
37
40
|
def include?(x1, y1, x2, y2, x, y)
|
38
41
|
distance1 = Math.sqrt((x - x1)**2 + (y - y1)**2)
|
@@ -79,11 +82,11 @@ module Glimmer
|
|
79
82
|
end
|
80
83
|
|
81
84
|
def width
|
82
|
-
|
85
|
+
size.x
|
83
86
|
end
|
84
87
|
|
85
88
|
def height
|
86
|
-
|
89
|
+
size.y
|
87
90
|
end
|
88
91
|
|
89
92
|
def absolute_x1
|
@@ -104,7 +107,7 @@ module Glimmer
|
|
104
107
|
|
105
108
|
def absolute_x2
|
106
109
|
if parent.is_a?(Shape)
|
107
|
-
parent.absolute_x + x2
|
110
|
+
parent.absolute_x + x2.to_f
|
108
111
|
else
|
109
112
|
x2
|
110
113
|
end
|
@@ -112,7 +115,7 @@ module Glimmer
|
|
112
115
|
|
113
116
|
def absolute_y2
|
114
117
|
if parent.is_a?(Shape)
|
115
|
-
parent.absolute_y +
|
118
|
+
parent.absolute_y + y2.to_f
|
116
119
|
else
|
117
120
|
y2
|
118
121
|
end
|
@@ -134,7 +137,37 @@ module Glimmer
|
|
134
137
|
def irregular?
|
135
138
|
true
|
136
139
|
end
|
140
|
+
|
141
|
+
def path_segment_method_name
|
142
|
+
'lineTo'
|
143
|
+
end
|
144
|
+
|
145
|
+
def path_segment_args
|
146
|
+
# TODO make args auto-infer first point if previous_point_connected is true or if there is only x1,y1 or x2,y2 (but not both), or if there is an x, y, or if there is a point_array with 1 point
|
147
|
+
@args
|
148
|
+
end
|
149
|
+
|
150
|
+
def path_segment_geometry_args
|
151
|
+
# TODO make args auto-infer first point if previous_point_connected is true or if there is only x1,y1 or x2,y2 (but not both), or if there is an x, y, or if there is a point_array with 1 point
|
152
|
+
@args[0..1]
|
153
|
+
end
|
154
|
+
|
155
|
+
def previous_point_connected?
|
156
|
+
@args.compact.count == 2 && !first_path_segment?
|
157
|
+
end
|
137
158
|
|
159
|
+
def eql?(other)
|
160
|
+
x1 == (other && other.respond_to?(:x1) && other.x1) &&
|
161
|
+
y1 == (other && other.respond_to?(:y1) && other.y1) &&
|
162
|
+
x2 == (other && other.respond_to?(:x2) && other.x2) &&
|
163
|
+
y2 == (other && other.respond_to?(:y2) && other.y2)
|
164
|
+
end
|
165
|
+
alias == eql?
|
166
|
+
|
167
|
+
def hash
|
168
|
+
[x1, y1, x2, y2].hash
|
169
|
+
end
|
170
|
+
|
138
171
|
end
|
139
172
|
end
|
140
173
|
end
|
@@ -0,0 +1,197 @@
|
|
1
|
+
# Copyright (c) 2007-2021 Andy Maleh
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
# a copy of this software and associated documentation files (the
|
5
|
+
# "Software"), to deal in the Software without restriction, including
|
6
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
# the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be
|
12
|
+
# included in all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
22
|
+
require 'glimmer/swt/custom/shape'
|
23
|
+
require 'glimmer/swt/custom/shape/path_segment'
|
24
|
+
require 'glimmer/swt/swt_proxy'
|
25
|
+
require 'glimmer/swt/display_proxy'
|
26
|
+
require 'glimmer/swt/color_proxy'
|
27
|
+
require 'glimmer/swt/font_proxy'
|
28
|
+
require 'glimmer/swt/display_proxy'
|
29
|
+
|
30
|
+
module Glimmer
|
31
|
+
module SWT
|
32
|
+
module Custom
|
33
|
+
# Represents a path to be drawn on a control/widget/canvas/display
|
34
|
+
# That is because Shape is drawn on a parent as graphics and doesn't have an SWT widget for itself
|
35
|
+
class Shape
|
36
|
+
class Path < Shape
|
37
|
+
include PathSegment # a path may behave as a path segment in another path
|
38
|
+
|
39
|
+
attr_accessor :flatness, :closed
|
40
|
+
attr_reader :swt_path, :path_segments
|
41
|
+
|
42
|
+
def initialize(parent, keyword, *args, &property_block)
|
43
|
+
super
|
44
|
+
@path_segments = []
|
45
|
+
@uncalculated_path_segments = []
|
46
|
+
end
|
47
|
+
|
48
|
+
def parameter_names
|
49
|
+
[:swt_path]
|
50
|
+
end
|
51
|
+
|
52
|
+
def add_shape(shape)
|
53
|
+
if shape.is_a?(PathSegment)
|
54
|
+
@path_segments << shape
|
55
|
+
@uncalculated_path_segments << shape
|
56
|
+
else
|
57
|
+
super
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def contain?(x, y)
|
62
|
+
makeshift_gc = org.eclipse.swt.graphics.GC.new(Glimmer::SWT::DisplayProxy.instance.swt_display)
|
63
|
+
@swt_path.contains(x.to_f, y.to_f, makeshift_gc, false)
|
64
|
+
end
|
65
|
+
|
66
|
+
def contain?(x, y)
|
67
|
+
include?(x, y, filled: true)
|
68
|
+
end
|
69
|
+
|
70
|
+
# 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)
|
71
|
+
def include?(x, y, filled: nil)
|
72
|
+
filled = filled? if filled.nil?
|
73
|
+
makeshift_gc = org.eclipse.swt.graphics.GC.new(Glimmer::SWT::DisplayProxy.instance.swt_display)
|
74
|
+
@swt_path.contains(x.to_f, y.to_f, makeshift_gc, !filled)
|
75
|
+
end
|
76
|
+
|
77
|
+
def irregular?
|
78
|
+
true
|
79
|
+
end
|
80
|
+
|
81
|
+
def post_dispose_content(path_segment)
|
82
|
+
@path_segments.delete(path_segment)
|
83
|
+
@uncalculated_path_segments = @path_segments.dup
|
84
|
+
dispose
|
85
|
+
end
|
86
|
+
|
87
|
+
def dispose
|
88
|
+
@swt_path&.dispose
|
89
|
+
@swt_path = nil
|
90
|
+
@args = []
|
91
|
+
calculated_args_changed!(children: false)
|
92
|
+
super
|
93
|
+
end
|
94
|
+
|
95
|
+
def calculated_args_changed!(children: true)
|
96
|
+
super
|
97
|
+
end
|
98
|
+
|
99
|
+
def calculated_args
|
100
|
+
@swt_path ||= org.eclipse.swt.graphics.Path.new(Glimmer::SWT::DisplayProxy.instance.swt_display)
|
101
|
+
# TODO recreate @swt_path only if one of the children get disposed (must notify parent on dispose)
|
102
|
+
@args = [@swt_path]
|
103
|
+
@uncalculated_path_segments.dup.each do |path_segment|
|
104
|
+
path_segment.add_to_swt_path(@swt_path)
|
105
|
+
@uncalculated_path_segments.delete(path_segment)
|
106
|
+
end
|
107
|
+
super
|
108
|
+
rescue => e
|
109
|
+
Glimmer::Config.logger.error {e.full_message}
|
110
|
+
end
|
111
|
+
|
112
|
+
def move_by(x_delta, y_delta)
|
113
|
+
@path_segments.each {|path_segment| path_segment.move_by(x_delta, y_delta)}
|
114
|
+
end
|
115
|
+
|
116
|
+
def bounds
|
117
|
+
if @path_segments != @bounds_path_segments
|
118
|
+
@bounds_path_segments = @path_segments
|
119
|
+
shape_bounds = geometry.getBounds2D
|
120
|
+
@bounds = org.eclipse.swt.graphics.Rectangle.new(shape_bounds.x, shape_bounds.y, shape_bounds.width, shape_bounds.height)
|
121
|
+
end
|
122
|
+
@bounds
|
123
|
+
end
|
124
|
+
|
125
|
+
def size
|
126
|
+
if @path_segments != @size_path_segments
|
127
|
+
@size_path_segments = @path_segments
|
128
|
+
shape_bounds = geometry.getBounds2D
|
129
|
+
@size = org.eclipse.swt.graphics.Point.new(shape_bounds.width, shape_bounds.height)
|
130
|
+
end
|
131
|
+
@size
|
132
|
+
end
|
133
|
+
|
134
|
+
# Logical x coordinate relative to parent
|
135
|
+
def x
|
136
|
+
x_value = bounds.x
|
137
|
+
x_value -= parent.absolute_x if parent.is_a?(Shape)
|
138
|
+
x_value
|
139
|
+
end
|
140
|
+
|
141
|
+
# Logical y coordinate relative to parent
|
142
|
+
def y
|
143
|
+
y_value = bounds.y
|
144
|
+
y_value -= parent.absolute_y if parent.is_a?(Shape)
|
145
|
+
y_value
|
146
|
+
end
|
147
|
+
|
148
|
+
def width
|
149
|
+
size.x
|
150
|
+
end
|
151
|
+
|
152
|
+
def height
|
153
|
+
size.y
|
154
|
+
end
|
155
|
+
|
156
|
+
def geometry
|
157
|
+
if @path_segments != @geometry_path_segments
|
158
|
+
@geometry_path_segments = @path_segments
|
159
|
+
@geometry = Java::JavaAwtGeom::Path2D::Double.new
|
160
|
+
@path_segments.each do |path_segment|
|
161
|
+
@geometry.send(path_segment.path_segment_geometry_method_name, *path_segment.path_segment_geometry_args)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
@geometry
|
165
|
+
end
|
166
|
+
|
167
|
+
def path_segment_method_name
|
168
|
+
'addPath'
|
169
|
+
end
|
170
|
+
|
171
|
+
def path_segment_args
|
172
|
+
@args
|
173
|
+
end
|
174
|
+
|
175
|
+
def path_segment_geometry_method_name
|
176
|
+
'append'
|
177
|
+
end
|
178
|
+
|
179
|
+
def path_segment_geometry_args
|
180
|
+
# TODO consider supporting connected true instead of false (2nd arg)
|
181
|
+
[geometry, false]
|
182
|
+
end
|
183
|
+
|
184
|
+
def eql?(other)
|
185
|
+
geometry.equals(other && other.respond_to?(:geometry) && other.geometry)
|
186
|
+
end
|
187
|
+
alias == eql?
|
188
|
+
|
189
|
+
def hash
|
190
|
+
geometry.hashCode
|
191
|
+
end
|
192
|
+
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# Copyright (c) 2007-2021 Andy Maleh
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
# a copy of this software and associated documentation files (the
|
5
|
+
# "Software"), to deal in the Software without restriction, including
|
6
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
# the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be
|
12
|
+
# included in all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
22
|
+
require 'glimmer/swt/custom/shape'
|
23
|
+
|
24
|
+
module Glimmer
|
25
|
+
module SWT
|
26
|
+
module Custom
|
27
|
+
# Represents a path to be drawn on a control/widget/canvas/display
|
28
|
+
# That is because Shape is drawn on a parent as graphics and doesn't have an SWT widget for itself
|
29
|
+
class Shape
|
30
|
+
# Represents path segments like point, line, quad, and cubic curves
|
31
|
+
# Shapes could mix in
|
32
|
+
module PathSegment
|
33
|
+
# Subclasses must override and implement to indicate method name to invoke on SWT Path object to add segment
|
34
|
+
def path_segment_method_name
|
35
|
+
nil
|
36
|
+
end
|
37
|
+
# Subclasses must override and implement to indicate args to pass when invoking SWT Path object method
|
38
|
+
def path_segment_args
|
39
|
+
[]
|
40
|
+
end
|
41
|
+
# Subclasses may override to provide name of method to invoke for geometry object obtained from the Java AWT library java.awt.geom.Path2D.Double (e.g. curveTo vs cubicTo)
|
42
|
+
def path_segment_geometry_method_name
|
43
|
+
path_segment_method_name
|
44
|
+
end
|
45
|
+
# Subclasses must override and implement to indicate args to pass when invoking SWT Path object method
|
46
|
+
def path_segment_geometry_args
|
47
|
+
path_segment_args
|
48
|
+
end
|
49
|
+
# Subclasses must override to indicate otherwise
|
50
|
+
def previous_point_connected?
|
51
|
+
true
|
52
|
+
end
|
53
|
+
|
54
|
+
def dispose
|
55
|
+
parent.post_dispose_content(self) if parent.is_a?(Path)
|
56
|
+
end
|
57
|
+
|
58
|
+
def first_path_segment?
|
59
|
+
parent.path_segments.first == self
|
60
|
+
end
|
61
|
+
|
62
|
+
def previous_path_segment
|
63
|
+
parent.path_segments[parent.path_segments.index(self) - 1] || self
|
64
|
+
end
|
65
|
+
|
66
|
+
def add_to_swt_path(swt_path)
|
67
|
+
if @swt_path != swt_path
|
68
|
+
@swt_path = swt_path
|
69
|
+
the_path_segment_args = path_segment_args.dup
|
70
|
+
if !previous_point_connected? && !is_a?(Point)
|
71
|
+
if the_path_segment_args.count > 2
|
72
|
+
point = the_path_segment_args.shift, the_path_segment_args.shift
|
73
|
+
@swt_path.moveTo(*point)
|
74
|
+
elsif first_path_segment? && self.class != Path
|
75
|
+
point = the_path_segment_args[0..1]
|
76
|
+
@swt_path.moveTo(*point)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
@swt_path.send(path_segment_method_name, *the_path_segment_args)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -20,6 +20,7 @@
|
|
20
20
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
21
|
|
22
22
|
require 'glimmer/swt/custom/shape'
|
23
|
+
require 'glimmer/swt/custom/shape/path_segment'
|
23
24
|
require 'glimmer/swt/swt_proxy'
|
24
25
|
require 'glimmer/swt/display_proxy'
|
25
26
|
require 'glimmer/swt/color_proxy'
|
@@ -33,6 +34,8 @@ module Glimmer
|
|
33
34
|
# That is because Shape is drawn on a parent as graphics and doesn't have an SWT widget for itself
|
34
35
|
class Shape
|
35
36
|
class Point < Shape
|
37
|
+
include PathSegment
|
38
|
+
|
36
39
|
def parameter_names
|
37
40
|
[:x, :y]
|
38
41
|
end
|
@@ -50,6 +53,36 @@ module Glimmer
|
|
50
53
|
x.to_i.between?(self.absolute_x.to_i - 2, self.absolute_x.to_i + 2) && y.to_i.between?(self.absolute_y.to_i - 2, self.absolute_y.to_i + 2)
|
51
54
|
end
|
52
55
|
alias contain? include?
|
56
|
+
|
57
|
+
def path_segment_method_name
|
58
|
+
'addRectangle'
|
59
|
+
end
|
60
|
+
|
61
|
+
def path_segment_args
|
62
|
+
@args + [1, 1]
|
63
|
+
end
|
64
|
+
|
65
|
+
def path_segment_geometry_method_name
|
66
|
+
'moveTo'
|
67
|
+
end
|
68
|
+
|
69
|
+
def path_segment_geometry_args
|
70
|
+
@args
|
71
|
+
end
|
72
|
+
|
73
|
+
def previous_point_connected?
|
74
|
+
false
|
75
|
+
end
|
76
|
+
|
77
|
+
def eql?(other)
|
78
|
+
x == (other && other.respond_to?(:x) && other.x) && y == (other && other.respond_to?(:y) && other.y)
|
79
|
+
end
|
80
|
+
alias == eql?
|
81
|
+
|
82
|
+
def hash
|
83
|
+
[x, y].hash
|
84
|
+
end
|
85
|
+
|
53
86
|
end
|
54
87
|
end
|
55
88
|
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# Copyright (c) 2007-2021 Andy Maleh
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
# a copy of this software and associated documentation files (the
|
5
|
+
# "Software"), to deal in the Software without restriction, including
|
6
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
# the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be
|
12
|
+
# included in all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
22
|
+
require 'glimmer/swt/custom/shape'
|
23
|
+
require 'glimmer/swt/custom/shape/path_segment'
|
24
|
+
require 'glimmer/swt/swt_proxy'
|
25
|
+
require 'glimmer/swt/display_proxy'
|
26
|
+
require 'glimmer/swt/color_proxy'
|
27
|
+
require 'glimmer/swt/font_proxy'
|
28
|
+
require 'glimmer/swt/transform_proxy'
|
29
|
+
|
30
|
+
module Glimmer
|
31
|
+
module SWT
|
32
|
+
module Custom
|
33
|
+
# Represents a shape (graphics) to be drawn on a control/widget/canvas/display
|
34
|
+
# That is because Shape is drawn on a parent as graphics and doesn't have an SWT widget for itself
|
35
|
+
class Shape
|
36
|
+
class Quad < Path
|
37
|
+
def parameter_names
|
38
|
+
[:point_array]
|
39
|
+
end
|
40
|
+
|
41
|
+
def geometry
|
42
|
+
if @point_array != @geometry_point_array
|
43
|
+
@geometry_point_array = @point_array
|
44
|
+
@geometry = Java::JavaAwtGeom::Path2D::Double.new
|
45
|
+
@geometry.send(path_segment_geometry_method_name, *path_segment_geometry_args)
|
46
|
+
end
|
47
|
+
@geometry
|
48
|
+
end
|
49
|
+
|
50
|
+
def contain?(x, y)
|
51
|
+
include?(x, y, filled: true)
|
52
|
+
end
|
53
|
+
|
54
|
+
# 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)
|
55
|
+
def include?(x, y, filled: nil)
|
56
|
+
filled = filled? if filled.nil?
|
57
|
+
makeshift_gc = org.eclipse.swt.graphics.GC.new(Glimmer::SWT::DisplayProxy.instance.swt_display)
|
58
|
+
swt_path = org.eclipse.swt.graphics.Path.new(Glimmer::SWT::DisplayProxy.instance.swt_display)
|
59
|
+
the_path_segment_args = path_segment_args.dup
|
60
|
+
if previous_point_connected?
|
61
|
+
the_previous_path_segment = previous_path_segment
|
62
|
+
swt_path.moveTo(the_previous_path_segment.x, the_previous_path_segment.y)
|
63
|
+
else
|
64
|
+
swt_path.moveTo(the_path_segment_args.shift, the_path_segment_args.shift)
|
65
|
+
end
|
66
|
+
swt_path.quadTo(*the_path_segment_args)
|
67
|
+
swt_path.contains(x.to_f, y.to_f, makeshift_gc, !filled)
|
68
|
+
ensure
|
69
|
+
swt_path.dispose
|
70
|
+
end
|
71
|
+
|
72
|
+
def move_by(x_delta, y_delta)
|
73
|
+
the_point_array = @args.compact
|
74
|
+
the_point_array = the_point_array.first if the_point_array.first.is_a?(Array)
|
75
|
+
self.point_array = the_point_array.each_with_index.map {|coordinate, i| i.even? ? coordinate + x_delta : coordinate + y_delta}
|
76
|
+
end
|
77
|
+
|
78
|
+
def path_segment_method_name
|
79
|
+
'quadTo'
|
80
|
+
end
|
81
|
+
|
82
|
+
def path_segment_args
|
83
|
+
# TODO make args auto-infer control points if previous_point_connected is true or if there is only a point_array with 1 point
|
84
|
+
@args.to_a
|
85
|
+
end
|
86
|
+
|
87
|
+
def previous_point_connected?
|
88
|
+
@args.compact.count <= 4 && !first_path_segment?
|
89
|
+
end
|
90
|
+
|
91
|
+
def eql?(other)
|
92
|
+
point_array == (other && other.respond_to?(:point_array) && other.point_array)
|
93
|
+
end
|
94
|
+
alias == eql?
|
95
|
+
|
96
|
+
def hash
|
97
|
+
point_array.hash
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -73,7 +73,7 @@ module Glimmer
|
|
73
73
|
Glimmer::SWT::DisplayProxy.instance.auto_exec do
|
74
74
|
result = if proxy_source_object&.respond_to?(attribute_setter(attribute_name))
|
75
75
|
swt_widget_operation = true
|
76
|
-
proxy_source_object&.send(attribute_setter(attribute_name), *args) unless proxy_source_object&.send(attribute_getter(attribute_name)) == args.first
|
76
|
+
proxy_source_object&.send(attribute_setter(attribute_name), *args) unless (proxy_source_object&.respond_to?(attribute_getter(attribute_name)) && proxy_source_object&.send(attribute_getter(attribute_name))) == args.first
|
77
77
|
elsif proxy_source_object&.respond_to?(ruby_attribute_setter(attribute_name))
|
78
78
|
swt_widget_operation = true
|
79
79
|
proxy_source_object&.send(ruby_attribute_setter(attribute_name), args)
|
@@ -379,7 +379,7 @@ class MandelbrotFractal
|
|
379
379
|
image @mandelbrot_image
|
380
380
|
}
|
381
381
|
@canvas.set_size @mandelbrot_image.bounds.width, @mandelbrot_image.bounds.height
|
382
|
-
@scrolled_composite.
|
382
|
+
@scrolled_composite.set_min_size(Point.new(@mandelbrot_image.bounds.width, @mandelbrot_image.bounds.height))
|
383
383
|
if @location_x && @location_y
|
384
384
|
# center on mouse click location
|
385
385
|
factor = (zoom / last_zoom)
|
@@ -0,0 +1,223 @@
|
|
1
|
+
# Copyright (c) 2007-2021 Andy Maleh
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
# a copy of this software and associated documentation files (the
|
5
|
+
# "Software"), to deal in the Software without restriction, including
|
6
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
# the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be
|
12
|
+
# included in all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
22
|
+
require 'glimmer-dsl-swt'
|
23
|
+
|
24
|
+
# This Sample is an Early Alpha (New Canvas Path DSL Feature)
|
25
|
+
|
26
|
+
class HelloCanvasPath
|
27
|
+
class Stock
|
28
|
+
class << self
|
29
|
+
attr_writer :stock_price_min, :stock_price_max
|
30
|
+
|
31
|
+
def stock_price_min
|
32
|
+
@stock_price_min ||= 1
|
33
|
+
end
|
34
|
+
|
35
|
+
def stock_price_max
|
36
|
+
@stock_price_max ||= 600
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
attr_reader :name, :stock_prices
|
41
|
+
attr_accessor :stock_price
|
42
|
+
|
43
|
+
def initialize(name, stock_price)
|
44
|
+
@name = name
|
45
|
+
@stock_price = stock_price
|
46
|
+
@stock_prices = [@stock_price]
|
47
|
+
@delta_sign = 1
|
48
|
+
start_new_trend!
|
49
|
+
end
|
50
|
+
|
51
|
+
def tick!
|
52
|
+
@tick_count = @tick_count.to_i + 1
|
53
|
+
delta = @tick_count%@trend_length
|
54
|
+
if delta == 0
|
55
|
+
@delta_sign *= -1
|
56
|
+
start_new_trend!
|
57
|
+
end
|
58
|
+
stock_prices << self.stock_price = [[@stock_price + @delta_sign*delta, Stock.stock_price_min].max, Stock.stock_price_max].min
|
59
|
+
end
|
60
|
+
|
61
|
+
def start_new_trend!
|
62
|
+
@trend_length = (rand*25).to_i + 1
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
include Glimmer::UI::CustomShell
|
67
|
+
|
68
|
+
before_body {
|
69
|
+
@stocks = [
|
70
|
+
Stock.new('AAPL', 121),
|
71
|
+
Stock.new('MSFT', 232),
|
72
|
+
]
|
73
|
+
@stock_colors = [:red, :dark_green, :blue, :magenta]
|
74
|
+
max_stock_name_width = 0
|
75
|
+
left_margin = 5
|
76
|
+
@tabs = ['Cubic Bezier Curves', 'Quadratic Bezier Curves', 'Lines', 'Points'].map {|title| {title: title, paths: [], transforms: []}}
|
77
|
+
@stocks.each_with_index do |stock, i|
|
78
|
+
x = 0
|
79
|
+
observe(stock, :stock_price) do |new_price|
|
80
|
+
begin
|
81
|
+
@tabs.each do |tab|
|
82
|
+
new_x = x
|
83
|
+
new_y = @tabs.first[:canvas].bounds.height - new_price - 1
|
84
|
+
max_stock_name_width = tab[:text]&.bounds&.width if tab[:text]&.bounds&.width.to_f > max_stock_name_width
|
85
|
+
if new_x > 0
|
86
|
+
case tab[:title]
|
87
|
+
when 'Cubic Bezier Curves'
|
88
|
+
if stock.stock_prices[i] && stock.stock_prices[i - 1] && stock.stock_prices[i - 2]
|
89
|
+
tab[:paths][i].content {
|
90
|
+
cubic(new_x - 2, @tabs.first[:canvas].bounds.height - stock.stock_prices[i - 2] - 1, new_x - 1, @tabs.first[:canvas].bounds.height - stock.stock_prices[i - 1] - 1, new_x, new_y)
|
91
|
+
tab[:transforms][i] ||= transform {
|
92
|
+
translate max_stock_name_width + 5 + left_margin, tab[:text].bounds.height / 2.0
|
93
|
+
}
|
94
|
+
}
|
95
|
+
end
|
96
|
+
when 'Quadratic Bezier Curves'
|
97
|
+
if stock.stock_prices[i] && stock.stock_prices[i - 1]
|
98
|
+
tab[:paths][i].content {
|
99
|
+
quad(new_x - 1, @tabs.first[:canvas].bounds.height - stock.stock_prices[i - 1] - 1, new_x, new_y)
|
100
|
+
tab[:transforms][i] ||= transform {
|
101
|
+
translate max_stock_name_width + 5 + left_margin, tab[:text].bounds.height / 2.0
|
102
|
+
}
|
103
|
+
}
|
104
|
+
end
|
105
|
+
when 'Lines'
|
106
|
+
tab[:paths][i].content {
|
107
|
+
line(new_x, new_y)
|
108
|
+
tab[:transforms][i] ||= transform {
|
109
|
+
translate max_stock_name_width + 5 + left_margin, tab[:text].bounds.height / 2.0
|
110
|
+
}
|
111
|
+
}
|
112
|
+
when 'Points'
|
113
|
+
tab[:paths][i].content {
|
114
|
+
point(new_x, new_y)
|
115
|
+
tab[:transforms][i] ||= transform {
|
116
|
+
translate max_stock_name_width + 5 + left_margin, tab[:text].bounds.height / 2.0
|
117
|
+
}
|
118
|
+
}
|
119
|
+
end
|
120
|
+
new_x_location = new_x + max_stock_name_width + 5 + left_margin + 5
|
121
|
+
canvas_width = tab[:canvas].bounds.width
|
122
|
+
if new_x_location > canvas_width
|
123
|
+
tab[:canvas].set_size(new_x_location, @tabs.first[:canvas].bounds.height)
|
124
|
+
tab[:canvas].cursor = :hand
|
125
|
+
tab[:scrolled_composite].set_min_size(new_x_location, @tabs.first[:canvas].bounds.height)
|
126
|
+
tab[:scrolled_composite].set_origin(tab[:scrolled_composite].origin.x + 1, tab[:scrolled_composite].origin.y) if (tab[:scrolled_composite].origin.x + tab[:scrolled_composite].client_area.width) == canvas_width
|
127
|
+
end
|
128
|
+
else
|
129
|
+
tab[:canvas].content {
|
130
|
+
tab[:text] = text(stock.name, new_x + left_margin, new_y) {
|
131
|
+
foreground @stock_colors[i]
|
132
|
+
}
|
133
|
+
}
|
134
|
+
end
|
135
|
+
end
|
136
|
+
x += 1
|
137
|
+
rescue => e
|
138
|
+
Glimmer::Config.logger.error {e.full_message}
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
}
|
143
|
+
|
144
|
+
after_body {
|
145
|
+
@thread = Thread.new {
|
146
|
+
loop {
|
147
|
+
@stocks.each(&:tick!)
|
148
|
+
sleep(0.01)
|
149
|
+
}
|
150
|
+
}
|
151
|
+
}
|
152
|
+
|
153
|
+
body {
|
154
|
+
shell {
|
155
|
+
fill_layout {
|
156
|
+
margin_width 15
|
157
|
+
margin_height 15
|
158
|
+
}
|
159
|
+
text 'Hello, Canvas Path!'
|
160
|
+
minimum_size 650, 650
|
161
|
+
background :white
|
162
|
+
|
163
|
+
tab_folder {
|
164
|
+
@tabs.each do |tab|
|
165
|
+
tab_item {
|
166
|
+
fill_layout {
|
167
|
+
margin_width 0
|
168
|
+
margin_height 0
|
169
|
+
}
|
170
|
+
text tab[:title]
|
171
|
+
|
172
|
+
tab[:scrolled_composite] = scrolled_composite {
|
173
|
+
tab[:canvas] = canvas {
|
174
|
+
background :white
|
175
|
+
|
176
|
+
@stocks.count.times do |n|
|
177
|
+
tab[:paths][n] = path {
|
178
|
+
foreground @stock_colors[n]
|
179
|
+
}
|
180
|
+
end
|
181
|
+
|
182
|
+
on_mouse_down {
|
183
|
+
@drag_detected = false
|
184
|
+
}
|
185
|
+
|
186
|
+
on_drag_detected { |drag_detect_event|
|
187
|
+
@drag_detected = true
|
188
|
+
@drag_start_x = drag_detect_event.x
|
189
|
+
@drag_start_y = drag_detect_event.y
|
190
|
+
}
|
191
|
+
|
192
|
+
on_mouse_move { |mouse_event|
|
193
|
+
if @drag_detected
|
194
|
+
origin = tab[:scrolled_composite].origin
|
195
|
+
new_x = origin.x - (mouse_event.x - @drag_start_x)
|
196
|
+
new_y = origin.y - (mouse_event.y - @drag_start_y)
|
197
|
+
tab[:scrolled_composite].set_origin(new_x, new_y)
|
198
|
+
end
|
199
|
+
}
|
200
|
+
|
201
|
+
on_mouse_up { |mouse_event|
|
202
|
+
@drag_detected = false
|
203
|
+
}
|
204
|
+
}
|
205
|
+
}
|
206
|
+
}
|
207
|
+
end
|
208
|
+
}
|
209
|
+
|
210
|
+
on_swt_show {
|
211
|
+
Stock.stock_price_min = 25
|
212
|
+
Stock.stock_price_max = @tabs.first[:canvas].bounds.height - 6
|
213
|
+
}
|
214
|
+
|
215
|
+
on_widget_disposed {
|
216
|
+
@thread.kill # safe to kill as memory is in data only
|
217
|
+
}
|
218
|
+
}
|
219
|
+
}
|
220
|
+
end
|
221
|
+
|
222
|
+
HelloCanvasPath.launch
|
223
|
+
|
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.
|
4
|
+
version: 4.18.6.0
|
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-
|
11
|
+
date: 2021-02-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -434,13 +434,17 @@ files:
|
|
434
434
|
- lib/glimmer/swt/custom/radio_group.rb
|
435
435
|
- lib/glimmer/swt/custom/shape.rb
|
436
436
|
- lib/glimmer/swt/custom/shape/arc.rb
|
437
|
+
- lib/glimmer/swt/custom/shape/cubic.rb
|
437
438
|
- lib/glimmer/swt/custom/shape/focus.rb
|
438
439
|
- lib/glimmer/swt/custom/shape/image.rb
|
439
440
|
- lib/glimmer/swt/custom/shape/line.rb
|
440
441
|
- lib/glimmer/swt/custom/shape/oval.rb
|
442
|
+
- lib/glimmer/swt/custom/shape/path.rb
|
443
|
+
- lib/glimmer/swt/custom/shape/path_segment.rb
|
441
444
|
- lib/glimmer/swt/custom/shape/point.rb
|
442
445
|
- lib/glimmer/swt/custom/shape/polygon.rb
|
443
446
|
- lib/glimmer/swt/custom/shape/polyline.rb
|
447
|
+
- lib/glimmer/swt/custom/shape/quad.rb
|
444
448
|
- lib/glimmer/swt/custom/shape/rectangle.rb
|
445
449
|
- lib/glimmer/swt/custom/shape/text.rb
|
446
450
|
- lib/glimmer/swt/date_time_proxy.rb
|
@@ -499,6 +503,7 @@ files:
|
|
499
503
|
- samples/hello/hello_button.rb
|
500
504
|
- samples/hello/hello_canvas.rb
|
501
505
|
- samples/hello/hello_canvas_animation.rb
|
506
|
+
- samples/hello/hello_canvas_path.rb
|
502
507
|
- samples/hello/hello_canvas_transform.rb
|
503
508
|
- samples/hello/hello_checkbox.rb
|
504
509
|
- samples/hello/hello_checkbox_group.rb
|