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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8fb342869be74c6e592466ad89d26798dde5cf8f3d6beb52b5bcf6a6e8f221f6
4
- data.tar.gz: c75442b7c5aeac5d77878d52e969669ea677877c12a43c97081155c5412c9c4c
3
+ metadata.gz: 2b3fe4c65726425f091b0660bbf4dd4c55543c5c515bed56487aacb7e1458b7e
4
+ data.tar.gz: 71580957a753685f1eac22fb60ea13c2e2f289bb47017293980d4d06d78d5eec
5
5
  SHA512:
6
- metadata.gz: d3e484674be4fa02ea232e1452a80c4fbb2f141bee407ef6ce922dd0f1e3616f6ee420fc57fdd3d9af6c9d993a88705d95e62d9a5573273e63638a5876bf53d9
7
- data.tar.gz: 6a76ebd41db15abe32ae22b2c675199595e196251b03a84ddad99a3aa2b254b43b8e50e339579764de667e10e3673814fb4ab3886aa9f27a9f8c43a7ca16bdcd
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.5.5
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.5.5 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.
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.5.5
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.5.5'
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.5.5
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)**
@@ -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.5 ruby lib
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.5.5"
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-27"
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
- unless @content_added
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
- end
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 alpha once we allow setting shape properties on parents directly without shapes
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
- bounds.width
85
+ size.x
83
86
  end
84
87
 
85
88
  def height
86
- bounds.height
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 + y1
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
@@ -132,11 +132,11 @@ module Glimmer
132
132
  end
133
133
 
134
134
  def width
135
- bounds.width
135
+ size.x
136
136
  end
137
137
 
138
138
  def height
139
- bounds.height
139
+ size.y
140
140
  end
141
141
 
142
142
  def contain?(x, y)
@@ -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.swt_widget.set_min_size(Point.new(@mandelbrot_image.bounds.width, @mandelbrot_image.bounds.height))
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.5.5
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-27 00:00:00.000000000 Z
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