glimmer-dsl-swt 4.18.5.5 → 4.18.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +42 -0
  3. data/README.md +4 -4
  4. data/VERSION +1 -1
  5. data/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md +95 -5
  6. data/docs/reference/GLIMMER_PACKAGING_AND_DISTRIBUTION.md +2 -0
  7. data/docs/reference/GLIMMER_SAMPLES.md +67 -0
  8. data/glimmer-dsl-swt.gemspec +18 -6
  9. data/lib/glimmer/dsl/swt/animation_expression.rb +1 -1
  10. data/lib/glimmer/dsl/swt/custom_shape_expression.rb +61 -0
  11. data/lib/glimmer/dsl/swt/custom_widget_expression.rb +1 -1
  12. data/lib/glimmer/dsl/swt/dsl.rb +1 -0
  13. data/lib/glimmer/dsl/swt/expand_item_expression.rb +4 -4
  14. data/lib/glimmer/dsl/swt/image_expression.rb +1 -1
  15. data/lib/glimmer/dsl/swt/multiply_expression.rb +1 -1
  16. data/lib/glimmer/dsl/swt/shape_expression.rb +1 -1
  17. data/lib/glimmer/dsl/swt/transform_expression.rb +1 -1
  18. data/lib/glimmer/dsl/swt/widget_expression.rb +2 -1
  19. data/lib/glimmer/swt/color_proxy.rb +1 -1
  20. data/lib/glimmer/swt/custom/shape.rb +173 -53
  21. data/lib/glimmer/swt/custom/shape/cubic.rb +118 -0
  22. data/lib/glimmer/swt/custom/shape/line.rb +47 -4
  23. data/lib/glimmer/swt/custom/shape/path.rb +240 -0
  24. data/lib/glimmer/swt/custom/shape/path_segment.rb +135 -0
  25. data/lib/glimmer/swt/custom/shape/point.rb +33 -0
  26. data/lib/glimmer/swt/custom/shape/polygon.rb +2 -2
  27. data/lib/glimmer/swt/custom/shape/quad.rb +114 -0
  28. data/lib/glimmer/swt/display_proxy.rb +1 -1
  29. data/lib/glimmer/swt/message_box_proxy.rb +1 -1
  30. data/lib/glimmer/swt/proxy_properties.rb +1 -1
  31. data/lib/glimmer/swt/shell_proxy.rb +1 -1
  32. data/lib/glimmer/swt/tab_folder_proxy.rb +52 -0
  33. data/lib/glimmer/swt/transform_proxy.rb +1 -1
  34. data/lib/glimmer/swt/widget_proxy.rb +1 -1
  35. data/lib/glimmer/ui/custom_shape.rb +281 -0
  36. data/samples/elaborate/mandelbrot_fractal.rb +1 -1
  37. data/samples/elaborate/stock_ticker.rb +214 -0
  38. data/samples/hello/hello_canvas.rb +3 -0
  39. data/samples/hello/hello_canvas_data_binding.rb +214 -0
  40. data/samples/hello/hello_canvas_path.rb +120 -0
  41. data/samples/hello/hello_custom_shape.rb +78 -0
  42. data/samples/hello/hello_shape.rb +71 -0
  43. metadata +16 -4
@@ -0,0 +1,118 @@
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'
24
+ require 'glimmer/swt/custom/shape/path_segment'
25
+ require 'glimmer/swt/swt_proxy'
26
+ require 'glimmer/swt/display_proxy'
27
+ require 'glimmer/swt/color_proxy'
28
+ require 'glimmer/swt/font_proxy'
29
+ require 'glimmer/swt/transform_proxy'
30
+
31
+ module Glimmer
32
+ module SWT
33
+ module Custom
34
+ # Represents a shape (graphics) to be drawn on a control/widget/canvas/display
35
+ # That is because Shape is drawn on a parent as graphics and doesn't have an SWT widget for itself
36
+ class Shape
37
+ class Cubic < Path
38
+ def parameter_names
39
+ [:point_array]
40
+ end
41
+
42
+ def geometry
43
+ the_point_array = point_array
44
+ if the_point_array != @geometry_point_array
45
+ @geometry_point_array = the_point_array
46
+ @geometry = Java::JavaAwtGeom::Path2D::Double.new
47
+ add_to_geometry(@geometry)
48
+ end
49
+ @geometry
50
+ end
51
+
52
+ def contain?(x, y)
53
+ include?(x, y, filled: true)
54
+ end
55
+
56
+ # 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)
57
+ def include?(x, y, filled: nil)
58
+ filled = filled? if filled.nil?
59
+ makeshift_gc = org.eclipse.swt.graphics.GC.new(Glimmer::SWT::DisplayProxy.instance.swt_display)
60
+ swt_path = org.eclipse.swt.graphics.Path.new(Glimmer::SWT::DisplayProxy.instance.swt_display)
61
+ the_path_segment_args = path_segment_args.dup
62
+ if previous_point_connected?
63
+ the_previous_path_segment = previous_path_segment
64
+ swt_path.moveTo(the_previous_path_segment.x, the_previous_path_segment.y)
65
+ else
66
+ swt_path.moveTo(the_path_segment_args.shift, the_path_segment_args.shift)
67
+ end
68
+ swt_path.curveTo(*the_path_segment_args)
69
+ swt_path.contains(x.to_f, y.to_f, makeshift_gc, !filled)
70
+ ensure
71
+ swt_path.dispose
72
+ end
73
+
74
+ def move_by(x_delta, y_delta)
75
+ the_point_array = @args.compact
76
+ the_point_array = the_point_array.first if the_point_array.first.is_a?(Array)
77
+ self.point_array = the_point_array.each_with_index.map {|coordinate, i| i.even? ? coordinate + x_delta : coordinate + y_delta}
78
+ end
79
+
80
+ def path_segment_method_name
81
+ 'cubicTo'
82
+ end
83
+
84
+ def path_segment_args
85
+ # TODO make args auto-infer control points if previous_point_connected is true or if there is only a point_array with 1 point
86
+ @args.to_a
87
+ end
88
+
89
+ def default_path_segment_arg_count
90
+ 8
91
+ end
92
+
93
+ def default_connected_path_segment_arg_count
94
+ 6
95
+ end
96
+
97
+ def path_segment_geometry_method_name
98
+ 'curveTo'
99
+ end
100
+
101
+ def previous_point_connected?
102
+ @args.compact.count == 6 && !first_path_segment?
103
+ end
104
+
105
+ def eql?(other)
106
+ other.is_a?(Cubic) && point_array == (other && other.respond_to?(:point_array) && other.point_array)
107
+ end
108
+ alias == eql?
109
+
110
+ def hash
111
+ point_array.hash
112
+ end
113
+
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
@@ -1,4 +1,5 @@
1
1
  # Copyright (c) 2007-2021 Andy Maleh
2
+ # Copyright (c) 2007-2021 Andy Maleh
2
3
  #
3
4
  # Permission is hereby granted, free of charge, to any person obtaining
4
5
  # a copy of this software and associated documentation files (the
@@ -20,6 +21,7 @@
20
21
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22
 
22
23
  require 'glimmer/swt/custom/shape'
24
+ require 'glimmer/swt/custom/shape/path_segment'
23
25
  require 'glimmer/swt/swt_proxy'
24
26
  require 'glimmer/swt/display_proxy'
25
27
  require 'glimmer/swt/color_proxy'
@@ -33,6 +35,8 @@ module Glimmer
33
35
  # That is because Shape is drawn on a parent as graphics and doesn't have an SWT widget for itself
34
36
  class Shape
35
37
  class Line < Shape
38
+ include PathSegment
39
+
36
40
  class << self
37
41
  def include?(x1, y1, x2, y2, x, y)
38
42
  distance1 = Math.sqrt((x - x1)**2 + (y - y1)**2)
@@ -79,11 +83,11 @@ module Glimmer
79
83
  end
80
84
 
81
85
  def width
82
- bounds.width
86
+ size.x
83
87
  end
84
88
 
85
89
  def height
86
- bounds.height
90
+ size.y
87
91
  end
88
92
 
89
93
  def absolute_x1
@@ -104,7 +108,7 @@ module Glimmer
104
108
 
105
109
  def absolute_x2
106
110
  if parent.is_a?(Shape)
107
- parent.absolute_x + x2
111
+ parent.absolute_x + x2.to_f
108
112
  else
109
113
  x2
110
114
  end
@@ -112,7 +116,7 @@ module Glimmer
112
116
 
113
117
  def absolute_y2
114
118
  if parent.is_a?(Shape)
115
- parent.absolute_y + y1
119
+ parent.absolute_y + y2.to_f
116
120
  else
117
121
  y2
118
122
  end
@@ -134,7 +138,46 @@ module Glimmer
134
138
  def irregular?
135
139
  true
136
140
  end
141
+
142
+ def path_segment_method_name
143
+ 'lineTo'
144
+ end
145
+
146
+ def path_segment_args
147
+ # 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
148
+ @args
149
+ end
150
+
151
+ def default_path_segment_arg_count
152
+ 4
153
+ end
137
154
 
155
+ def default_connected_path_segment_arg_count
156
+ 2
157
+ end
158
+
159
+ def path_segment_geometry_args
160
+ # 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
161
+ @args
162
+ end
163
+
164
+ def previous_point_connected?
165
+ @args.compact.count == 2 && !first_path_segment?
166
+ end
167
+
168
+ def eql?(other)
169
+ other.is_a?(Line) &&
170
+ x1 == (other && other.respond_to?(:x1) && other.x1) &&
171
+ y1 == (other && other.respond_to?(:y1) && other.y1) &&
172
+ x2 == (other && other.respond_to?(:x2) && other.x2) &&
173
+ y2 == (other && other.respond_to?(:y2) && other.y2)
174
+ end
175
+ alias == eql?
176
+
177
+ def hash
178
+ [x1, y1, x2, y2].hash
179
+ end
180
+
138
181
  end
139
182
  end
140
183
  end
@@ -0,0 +1,240 @@
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
+ class Shape
34
+ # Represents a path to be drawn on a control/widget/canvas/display
35
+ # That is because Shape is drawn on a parent as graphics and doesn't have an SWT widget for itself
36
+ # swt_path is not guaranteed to have any object in it till after rendering
37
+ class Path < Shape
38
+ include PathSegment # a path may behave as a path segment in another path
39
+
40
+ attr_reader :swt_path, :path_segments
41
+ attr_accessor :calculated_path_args
42
+
43
+ def initialize(parent, keyword, *args, &property_block)
44
+ super
45
+ @path_segments = []
46
+ @uncalculated_path_segments = []
47
+ end
48
+
49
+ def parameter_names
50
+ [:swt_path]
51
+ end
52
+
53
+ def add_shape(shape)
54
+ if shape.is_a?(PathSegment)
55
+ Glimmer::SWT::DisplayProxy.instance.auto_exec do
56
+ @path_segments << shape
57
+ @uncalculated_path_segments << shape
58
+ end
59
+ else
60
+ super
61
+ end
62
+ end
63
+
64
+ def contain?(x, y)
65
+ makeshift_gc = org.eclipse.swt.graphics.GC.new(Glimmer::SWT::DisplayProxy.instance.swt_display)
66
+ @swt_path.contains(x.to_f, y.to_f, makeshift_gc, false)
67
+ end
68
+
69
+ def contain?(x, y)
70
+ include?(x, y, filled: true)
71
+ end
72
+
73
+ # 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)
74
+ def include?(x, y, filled: nil)
75
+ filled = filled? if filled.nil?
76
+ makeshift_gc = org.eclipse.swt.graphics.GC.new(Glimmer::SWT::DisplayProxy.instance.swt_display)
77
+ @swt_path.contains(x.to_f, y.to_f, makeshift_gc, !filled)
78
+ end
79
+
80
+ def irregular?
81
+ true
82
+ end
83
+
84
+ def post_dispose_content(path_segment)
85
+ Glimmer::SWT::DisplayProxy.instance.auto_exec do
86
+ @path_segments.delete(path_segment)
87
+ @uncalculated_path_segments = @path_segments.dup
88
+ @swt_path&.dispose
89
+ @swt_path = nil
90
+ @args = []
91
+ calculated_args_changed!(children: false)
92
+ end
93
+ end
94
+
95
+ def clear
96
+ Glimmer::SWT::DisplayProxy.instance.auto_exec do
97
+ @path_segments.each { |path_segments| path_segments.class == Path && path_segments.dispose }
98
+ @path_segments.clear
99
+ @uncalculated_path_segments = @path_segments.dup
100
+ @swt_path&.dispose
101
+ @swt_path = nil
102
+ @args = []
103
+ calculated_args_changed!(children: false)
104
+ drawable.redraw unless drawable.is_a?(ImageProxy)
105
+ end
106
+ end
107
+
108
+ def dispose(redraw: true)
109
+ Glimmer::SWT::DisplayProxy.instance.auto_exec do
110
+ clear if self.class == Path
111
+ super(redraw: redraw) if (parent.is_a?(Shape) && (!parent.is_a?(PathSegment) || !parent.part_of_path?)) || parent.is_a?(Drawable)
112
+ end
113
+ end
114
+
115
+ def calculated_args_changed!(children: true)
116
+ super
117
+ end
118
+
119
+ def calculated_args
120
+ new_swt_path = @swt_path.nil? || !@calculated_paint_args || !@calculated_path_args
121
+ if new_swt_path
122
+ Glimmer::SWT::DisplayProxy.instance.auto_exec do
123
+ @swt_path&.dispose
124
+ @swt_path = org.eclipse.swt.graphics.Path.new(Glimmer::SWT::DisplayProxy.instance.swt_display)
125
+ @uncalculated_path_segments = @path_segments.dup
126
+ end
127
+ end
128
+ # TODO recreate @swt_path only if one of the children get disposed (must notify parent on dispose)
129
+ @args = [@swt_path]
130
+ @uncalculated_path_segments.dup.each do |path_segment|
131
+ Glimmer::SWT::DisplayProxy.instance.auto_exec do
132
+ path_segment.add_to_swt_path(@swt_path)
133
+ @uncalculated_path_segments.delete(path_segment)
134
+ end
135
+ end
136
+ @calculated_path_args = true
137
+ if new_swt_path
138
+ @path_calculated_args = super
139
+ else
140
+ @path_calculated_args
141
+ end
142
+ rescue => e
143
+ Glimmer::Config.logger.error {e.full_message}
144
+ @args
145
+ end
146
+
147
+ def move_by(x_delta, y_delta)
148
+ @path_segments.each {|path_segment| path_segment.move_by(x_delta, y_delta)}
149
+ end
150
+
151
+ def bounds
152
+ if @path_segments != @bounds_path_segments
153
+ @bounds_path_segments = @path_segments
154
+ shape_bounds = geometry.getBounds2D
155
+ @bounds = org.eclipse.swt.graphics.Rectangle.new(shape_bounds.x, shape_bounds.y, shape_bounds.width, shape_bounds.height)
156
+ end
157
+ @bounds
158
+ end
159
+
160
+ def size
161
+ if @path_segments != @size_path_segments
162
+ @size_path_segments = @path_segments
163
+ shape_bounds = geometry.getBounds2D
164
+ @size = org.eclipse.swt.graphics.Point.new(shape_bounds.width, shape_bounds.height)
165
+ end
166
+ @size
167
+ end
168
+
169
+ # Logical x coordinate relative to parent
170
+ def x
171
+ x_value = bounds.x
172
+ x_value -= parent.absolute_x if parent.is_a?(Shape)
173
+ x_value
174
+ end
175
+
176
+ # Logical y coordinate relative to parent
177
+ def y
178
+ y_value = bounds.y
179
+ y_value -= parent.absolute_y if parent.is_a?(Shape)
180
+ y_value
181
+ end
182
+
183
+ def width
184
+ size.x
185
+ end
186
+
187
+ def height
188
+ size.y
189
+ end
190
+
191
+ def geometry
192
+ if @path_segments != @geometry_path_segments
193
+ @geometry_path_segments = @path_segments
194
+ @geometry = Java::JavaAwtGeom::Path2D::Double.new
195
+ @path_segments.each do |path_segment|
196
+ path_segment.add_to_geometry(@geometry)
197
+ end
198
+ end
199
+ @geometry
200
+ end
201
+
202
+ def path_segment_method_name
203
+ 'addPath'
204
+ end
205
+
206
+ def path_segment_args
207
+ @args
208
+ end
209
+
210
+ def path_segment_geometry_method_name
211
+ if self.class == Path
212
+ 'append'
213
+ else
214
+ super
215
+ end
216
+ end
217
+
218
+ def path_segment_geometry_args
219
+ if self.class == Path
220
+ # TODO consider supporting connected true instead of false (2nd arg)
221
+ [geometry, false]
222
+ else
223
+ super
224
+ end
225
+ end
226
+
227
+ def eql?(other)
228
+ (other.class == Path) && geometry.equals(other && other.respond_to?(:geometry) && other.geometry)
229
+ end
230
+ alias == eql?
231
+
232
+ def hash
233
+ geometry.hashCode
234
+ end
235
+
236
+ end
237
+ end
238
+ end
239
+ end
240
+ end