glimmer-dsl-swt 4.18.5.2 → 4.18.6.1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +38 -0
- data/README.md +8 -10
- data/VERSION +1 -1
- data/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md +93 -16
- data/docs/reference/GLIMMER_SAMPLES.md +32 -0
- data/glimmer-dsl-swt.gemspec +9 -3
- data/lib/glimmer/swt/custom/drawable.rb +8 -7
- data/lib/glimmer/swt/custom/shape.rb +416 -37
- data/lib/glimmer/swt/custom/shape/arc.rb +22 -4
- data/lib/glimmer/swt/custom/shape/cubic.rb +117 -0
- data/lib/glimmer/swt/custom/shape/image.rb +19 -6
- data/lib/glimmer/swt/custom/shape/line.rb +119 -1
- data/lib/glimmer/swt/custom/shape/oval.rb +3 -3
- data/lib/glimmer/swt/custom/shape/path.rb +211 -0
- data/lib/glimmer/swt/custom/shape/path_segment.rb +111 -0
- data/lib/glimmer/swt/custom/shape/point.rb +40 -4
- data/lib/glimmer/swt/custom/shape/polygon.rb +93 -3
- data/lib/glimmer/swt/custom/shape/polyline.rb +76 -4
- data/lib/glimmer/swt/custom/shape/quad.rb +113 -0
- data/lib/glimmer/swt/custom/shape/rectangle.rb +7 -2
- data/lib/glimmer/swt/custom/shape/text.rb +2 -4
- data/lib/glimmer/swt/dialog_proxy.rb +4 -0
- data/lib/glimmer/swt/proxy_properties.rb +1 -1
- data/lib/glimmer/swt/widget_proxy.rb +16 -0
- data/samples/elaborate/contact_manager.rb +2 -0
- data/samples/elaborate/login.rb +2 -0
- data/samples/elaborate/mandelbrot_fractal.rb +2 -1
- data/samples/elaborate/meta_sample.rb +1 -0
- data/samples/elaborate/stock_ticker.rb +229 -0
- data/samples/elaborate/tetris.rb +2 -1
- data/samples/elaborate/tic_tac_toe.rb +2 -0
- data/samples/elaborate/user_profile.rb +10 -8
- data/samples/hello/hello_browser.rb +2 -0
- data/samples/hello/hello_button.rb +2 -0
- data/samples/hello/hello_canvas.rb +40 -21
- data/samples/hello/hello_canvas_animation.rb +2 -0
- data/samples/hello/hello_canvas_path.rb +66 -0
- data/samples/hello/hello_canvas_transform.rb +2 -0
- data/samples/hello/hello_checkbox.rb +2 -0
- data/samples/hello/hello_checkbox_group.rb +2 -0
- data/samples/hello/hello_code_text.rb +2 -0
- data/samples/hello/hello_color_dialog.rb +2 -0
- data/samples/hello/hello_combo.rb +2 -0
- data/samples/hello/hello_computed.rb +2 -0
- data/samples/hello/hello_cursor.rb +2 -0
- data/samples/hello/hello_custom_shell.rb +1 -0
- data/samples/hello/hello_custom_widget.rb +2 -0
- data/samples/hello/hello_date_time.rb +2 -0
- data/samples/hello/hello_dialog.rb +2 -0
- data/samples/hello/hello_directory_dialog.rb +2 -0
- data/samples/hello/hello_drag_and_drop.rb +5 -3
- data/samples/hello/hello_expand_bar.rb +2 -0
- data/samples/hello/hello_file_dialog.rb +2 -0
- data/samples/hello/hello_font_dialog.rb +2 -0
- data/samples/hello/hello_group.rb +2 -0
- data/samples/hello/hello_link.rb +2 -0
- data/samples/hello/hello_list_multi_selection.rb +2 -0
- data/samples/hello/hello_list_single_selection.rb +2 -0
- data/samples/hello/hello_menu_bar.rb +2 -0
- data/samples/hello/hello_message_box.rb +2 -0
- data/samples/hello/hello_pop_up_context_menu.rb +2 -0
- data/samples/hello/hello_progress_bar.rb +2 -0
- data/samples/hello/hello_radio.rb +2 -0
- data/samples/hello/hello_radio_group.rb +2 -0
- data/samples/hello/hello_sash_form.rb +2 -0
- data/samples/hello/hello_spinner.rb +2 -0
- data/samples/hello/hello_styled_text.rb +19 -17
- data/samples/hello/hello_tab.rb +2 -0
- data/samples/hello/hello_table.rb +2 -0
- data/samples/hello/hello_world.rb +2 -0
- metadata +8 -2
@@ -26,6 +26,34 @@ require 'glimmer/swt/color_proxy'
|
|
26
26
|
require 'glimmer/swt/font_proxy'
|
27
27
|
require 'glimmer/swt/transform_proxy'
|
28
28
|
|
29
|
+
class Java::OrgEclipseSwtGraphics::GC
|
30
|
+
def setLineDashOffset(value)
|
31
|
+
lineMiterLimit = getLineAttributes&.miterLimit || 999_999
|
32
|
+
setLineAttributes(Java::OrgEclipseSwtGraphics::LineAttributes.new(getLineWidth, getLineCap, getLineJoin, getLineStyle, getLineDash.map(&:to_f).to_java(:float), value, lineMiterLimit))
|
33
|
+
end
|
34
|
+
alias set_line_dash_offset setLineDashOffset
|
35
|
+
alias line_dash_offset= setLineDashOffset
|
36
|
+
|
37
|
+
def getLineDashOffset
|
38
|
+
getLineAttributes&.dashOffset
|
39
|
+
end
|
40
|
+
alias get_line_dash_offset getLineDashOffset
|
41
|
+
alias line_dash_offset getLineDashOffset
|
42
|
+
|
43
|
+
def setLineMiterLimit(value)
|
44
|
+
lineDashOffset = getLineAttributes&.dashOffset || 0
|
45
|
+
setLineAttributes(Java::OrgEclipseSwtGraphics::LineAttributes.new(getLineWidth, getLineCap, getLineJoin, getLineStyle, getLineDash.map(&:to_f).to_java(:float), lineDashOffset, value))
|
46
|
+
end
|
47
|
+
alias set_line_miter_limit setLineMiterLimit
|
48
|
+
alias line_miter_limit= setLineMiterLimit
|
49
|
+
|
50
|
+
def getLineMiterLimit
|
51
|
+
getLineAttributes&.miterLimit
|
52
|
+
end
|
53
|
+
alias get_line_miter_limit getLineMiterLimit
|
54
|
+
alias line_miter_limit getLineMiterLimit
|
55
|
+
end
|
56
|
+
|
29
57
|
module Glimmer
|
30
58
|
module SWT
|
31
59
|
module Custom
|
@@ -46,7 +74,8 @@ module Glimmer
|
|
46
74
|
end
|
47
75
|
|
48
76
|
def valid?(parent, keyword, *args, &block)
|
49
|
-
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)
|
50
79
|
end
|
51
80
|
|
52
81
|
def gc_instance_methods
|
@@ -99,6 +128,7 @@ module Glimmer
|
|
99
128
|
end
|
100
129
|
|
101
130
|
attr_reader :drawable, :parent, :name, :args, :options, :shapes
|
131
|
+
attr_accessor :extent
|
102
132
|
|
103
133
|
def initialize(parent, keyword, *args, &property_block)
|
104
134
|
@parent = parent
|
@@ -118,6 +148,7 @@ module Glimmer
|
|
118
148
|
|
119
149
|
def add_shape(shape)
|
120
150
|
@shapes << shape
|
151
|
+
calculated_args_changed_for_defaults!
|
121
152
|
end
|
122
153
|
|
123
154
|
def draw?
|
@@ -138,34 +169,67 @@ module Glimmer
|
|
138
169
|
@options[:round]
|
139
170
|
end
|
140
171
|
|
141
|
-
#
|
172
|
+
# The bounding box top-left x, y, width, height in absolute positioning
|
173
|
+
def bounds
|
174
|
+
org.eclipse.swt.graphics.Rectangle.new(absolute_x, absolute_y, calculated_width, calculated_height)
|
175
|
+
end
|
176
|
+
|
177
|
+
# The bounding box top-left x and y
|
178
|
+
def location
|
179
|
+
org.eclipse.swt.graphics.Point.new(bounds.x, bounds.y)
|
180
|
+
end
|
181
|
+
|
182
|
+
# The bounding box width and height (as a Point object with x being width and y being height)
|
183
|
+
def size
|
184
|
+
org.eclipse.swt.graphics.Point.new(calculated_width, calculated_height)
|
185
|
+
end
|
186
|
+
|
187
|
+
def extent
|
188
|
+
@extent || size
|
189
|
+
end
|
190
|
+
|
191
|
+
# Returns if shape contains a point
|
192
|
+
# Subclasses (like polygon) may override to indicate if a point x,y coordinates falls inside the shape
|
142
193
|
# some shapes may choose to provide a fuzz factor to make usage of this method for mouse clicking more user friendly
|
143
194
|
def contain?(x, y)
|
144
195
|
# assume a rectangular filled shape by default (works for several shapes like image, text, and focus)
|
145
|
-
|
146
|
-
x.between?(self.x, self.x + width) && y.between?(self.y, self.y + height)
|
147
|
-
else
|
148
|
-
false # subclasses must provide implementation
|
149
|
-
end
|
196
|
+
x.between?(self.absolute_x, self.absolute_x + calculated_width) && y.between?(self.absolute_y, self.absolute_y + calculated_height)
|
150
197
|
end
|
151
198
|
|
152
|
-
#
|
199
|
+
# Returns if shape includes a point. When the shape is filled, this is the same as contain. When the shape is drawn, it only returns true if the point lies on the edge (boundary/border)
|
200
|
+
# Subclasses (like polygon) may override to indicate if a point x,y coordinates falls on the edge of a drawn shape or inside a filled shape
|
153
201
|
# some shapes may choose to provide a fuzz factor to make usage of this method for mouse clicking more user friendly
|
154
202
|
def include?(x, y)
|
155
203
|
# assume a rectangular shape by default
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
204
|
+
contain?(x, y)
|
205
|
+
end
|
206
|
+
|
207
|
+
# Indicates if a shape's x, y, width, height differ from its bounds calculation (e.g. arc / polygon)
|
208
|
+
def irregular?
|
209
|
+
false
|
161
210
|
end
|
162
211
|
|
163
212
|
# moves by x delta and y delta. Subclasses must implement
|
164
213
|
# provdies a default implementation that assumes moving x and y is sufficient by default (not for polygons though, which must override)
|
165
214
|
def move_by(x_delta, y_delta)
|
166
|
-
if respond_to?(:x) && respond_to?(:y) && x && y
|
167
|
-
|
168
|
-
|
215
|
+
if respond_to?(:x) && respond_to?(:y) && respond_to?(:x=) && respond_to?(:y=)
|
216
|
+
if default_x?
|
217
|
+
self.default_x_delta += x_delta
|
218
|
+
else
|
219
|
+
self.x += x_delta
|
220
|
+
end
|
221
|
+
if default_y?
|
222
|
+
self.default_y_delta += y_delta
|
223
|
+
else
|
224
|
+
self.y += y_delta
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
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)
|
169
233
|
end
|
170
234
|
end
|
171
235
|
|
@@ -178,8 +242,8 @@ module Glimmer
|
|
178
242
|
end
|
179
243
|
|
180
244
|
def post_add_content
|
181
|
-
|
182
|
-
|
245
|
+
amend_method_name_options_based_on_properties!
|
246
|
+
if !@content_added || @method_name != @original_method_name
|
183
247
|
@drawable.setup_shape_painting unless @drawable.is_a?(ImageProxy)
|
184
248
|
@content_added = true
|
185
249
|
end
|
@@ -188,12 +252,17 @@ module Glimmer
|
|
188
252
|
def apply_property_arg_conversions(method_name, property, args)
|
189
253
|
args = args.dup
|
190
254
|
the_java_method = org.eclipse.swt.graphics.GC.java_class.declared_instance_methods.detect {|m| m.name == method_name}
|
255
|
+
return args if the_java_method.nil?
|
191
256
|
if the_java_method.parameter_types.first == Color.java_class && args.first.is_a?(RGB)
|
192
257
|
args[0] = [args[0].red, args[0].green, args[0].blue]
|
193
258
|
end
|
194
259
|
if ['setBackground', 'setForeground'].include?(method_name.to_s) && args.first.is_a?(Array)
|
195
260
|
args[0] = ColorProxy.new(args[0])
|
196
261
|
end
|
262
|
+
if method_name.to_s == 'setLineDash' && args.size > 1
|
263
|
+
args[0] = args.dup
|
264
|
+
args[1..-1] = []
|
265
|
+
end
|
197
266
|
if args.first.is_a?(Symbol) || args.first.is_a?(::String)
|
198
267
|
if the_java_method.parameter_types.first == Color.java_class
|
199
268
|
args[0] = ColorProxy.new(args[0])
|
@@ -267,19 +336,21 @@ module Glimmer
|
|
267
336
|
end
|
268
337
|
|
269
338
|
def apply_shape_arg_defaults!
|
339
|
+
self.x = :default if current_parameter_name?(:x) && x.nil?
|
340
|
+
self.y = :default if current_parameter_name?(:y) && y.nil?
|
341
|
+
self.dest_x = :default if current_parameter_name?(:dest_x) && dest_x.nil?
|
342
|
+
self.dest_y = :default if current_parameter_name?(:dest_y) && dest_y.nil?
|
343
|
+
self.width = :default if current_parameter_name?(:width) && width.nil?
|
344
|
+
self.height = :default if current_parameter_name?(:height) && height.nil?
|
270
345
|
if @name.include?('rectangle') && round? && @args.size.between?(4, 5)
|
271
346
|
(6 - @args.size).times {@args << 60}
|
272
347
|
elsif @name.include?('rectangle') && gradient? && @args.size == 4
|
273
|
-
|
274
|
-
elsif (@name.include?('text') || @name.include?('string')) && !@properties.keys.map(&:to_s).include?('background') && @args.size
|
275
|
-
|
348
|
+
set_attribute('vertical', true, redraw: false)
|
349
|
+
elsif (@name.include?('text') || @name.include?('string')) && !@properties.keys.map(&:to_s).include?('background') && @args.size < 4
|
350
|
+
set_attribute('is_transparent', true, redraw: false)
|
276
351
|
end
|
277
352
|
if @name.include?('image')
|
278
353
|
@drawable.requires_shape_disposal = true
|
279
|
-
if @args.size == 1
|
280
|
-
@args[1] = 0
|
281
|
-
@args[2] = 0
|
282
|
-
end
|
283
354
|
end
|
284
355
|
end
|
285
356
|
|
@@ -295,6 +366,7 @@ module Glimmer
|
|
295
366
|
end
|
296
367
|
|
297
368
|
def amend_method_name_options_based_on_properties!
|
369
|
+
@original_method_name = @method_name
|
298
370
|
return if @name == 'point'
|
299
371
|
if @name != 'text' && @name != 'string' && has_some_background? && !has_some_foreground?
|
300
372
|
@options[:fill] = true
|
@@ -315,6 +387,12 @@ module Glimmer
|
|
315
387
|
[]
|
316
388
|
end
|
317
389
|
|
390
|
+
# subclasses may override to specify location parameter names if different from x and y (e.g. all polygon points are location parameters)
|
391
|
+
# used in calculating movement changes
|
392
|
+
def location_parameter_names
|
393
|
+
[:x, :y]
|
394
|
+
end
|
395
|
+
|
318
396
|
def possible_parameter_names
|
319
397
|
parameter_names
|
320
398
|
end
|
@@ -323,8 +401,12 @@ module Glimmer
|
|
323
401
|
possible_parameter_names.map(&:to_s).include?(ruby_attribute_getter(attribute_name))
|
324
402
|
end
|
325
403
|
|
404
|
+
def current_parameter_name?(attribute_name)
|
405
|
+
parameter_names.include?(attribute_name.to_s.to_sym)
|
406
|
+
end
|
407
|
+
|
326
408
|
def parameter_index(attribute_name)
|
327
|
-
parameter_names.
|
409
|
+
parameter_names.index(attribute_name.to_s.to_sym)
|
328
410
|
end
|
329
411
|
|
330
412
|
def set_parameter_attribute(attribute_name, *args)
|
@@ -333,18 +415,35 @@ module Glimmer
|
|
333
415
|
|
334
416
|
def has_attribute?(attribute_name, *args)
|
335
417
|
self.class.gc_instance_methods.include?(attribute_setter(attribute_name)) or
|
336
|
-
parameter_name?(attribute_name)
|
418
|
+
parameter_name?(attribute_name) or
|
419
|
+
(respond_to?(attribute_name, super: true) and respond_to?(ruby_attribute_setter(attribute_name), super: true))
|
337
420
|
end
|
338
|
-
|
421
|
+
|
339
422
|
def set_attribute(attribute_name, *args)
|
423
|
+
options = args.last if args.last.is_a?(Hash)
|
424
|
+
args.pop if !options.nil? && !options[:redraw].nil?
|
425
|
+
perform_redraw = @perform_redraw
|
426
|
+
perform_redraw = options[:redraw] if perform_redraw.nil? && !options.nil?
|
427
|
+
perform_redraw = true if perform_redraw.nil?
|
340
428
|
if parameter_name?(attribute_name)
|
341
429
|
set_parameter_attribute(attribute_name, *args)
|
430
|
+
elsif (respond_to?(attribute_name, super: true) and respond_to?(ruby_attribute_setter(attribute_name), super: true))
|
431
|
+
self.send(ruby_attribute_setter(attribute_name), *args)
|
342
432
|
else
|
343
433
|
@properties[ruby_attribute_getter(attribute_name)] = args
|
344
434
|
end
|
345
|
-
if @content_added &&
|
435
|
+
if @content_added && perform_redraw && !drawable.is_disposed
|
346
436
|
@calculated_paint_args = false
|
347
|
-
|
437
|
+
attribute_name = ruby_attribute_getter(attribute_name)
|
438
|
+
if location_parameter_names.map(&:to_s).include?(attribute_name)
|
439
|
+
@calculated_args = nil
|
440
|
+
parent.calculated_args_changed_for_defaults! if parent.is_a?(Shape)
|
441
|
+
end
|
442
|
+
if ['width', 'height'].include?(attribute_name)
|
443
|
+
calculated_args_changed_for_defaults!
|
444
|
+
end
|
445
|
+
# TODO consider redrawing an image proxy's gc in the future
|
446
|
+
drawable.redraw unless drawable.is_a?(ImageProxy)
|
348
447
|
end
|
349
448
|
end
|
350
449
|
|
@@ -352,6 +451,8 @@ module Glimmer
|
|
352
451
|
if parameter_name?(attribute_name)
|
353
452
|
arg_index = parameter_index(attribute_name)
|
354
453
|
@args[arg_index] if arg_index
|
454
|
+
elsif (respond_to?(attribute_name, super: true) and respond_to?(ruby_attribute_setter(attribute_name), super: true))
|
455
|
+
self.send(attribute_name)
|
355
456
|
else
|
356
457
|
@properties.symbolize_keys[attribute_name.to_s.to_sym]
|
357
458
|
end
|
@@ -368,7 +469,9 @@ module Glimmer
|
|
368
469
|
end
|
369
470
|
|
370
471
|
def respond_to?(method_name, *args, &block)
|
371
|
-
if
|
472
|
+
options = args.last if args.last.is_a?(Hash)
|
473
|
+
super_invocation = options && options[:super]
|
474
|
+
if !super_invocation && has_attribute?(method_name)
|
372
475
|
true
|
373
476
|
else
|
374
477
|
super
|
@@ -397,6 +500,7 @@ module Glimmer
|
|
397
500
|
end
|
398
501
|
|
399
502
|
def dispose(dispose_images: true, dispose_patterns: true)
|
503
|
+
shapes.each { |shape| shape.is_a?(Shape::Path) && shape.dispose }
|
400
504
|
if dispose_patterns
|
401
505
|
@background_pattern&.dispose
|
402
506
|
@background_pattern = nil
|
@@ -409,22 +513,297 @@ module Glimmer
|
|
409
513
|
end
|
410
514
|
@parent.shapes.delete(self)
|
411
515
|
end
|
412
|
-
|
516
|
+
|
413
517
|
def paint(paint_event)
|
518
|
+
# pre-paint children an extra-time first when default width/height need to be calculated for defaults
|
519
|
+
paint_children(paint_event) if default_width? || default_height?
|
520
|
+
paint_self(paint_event)
|
521
|
+
# re-paint children from scratch in the special case of pre-calculating parent width/height to re-center within new parent dimensions
|
522
|
+
shapes.each(&:calculated_args_changed!) if default_width? || default_height?
|
523
|
+
paint_children(paint_event)
|
524
|
+
rescue => e
|
525
|
+
Glimmer::Config.logger.error {"Error encountered in painting shape (#{self.inspect}) with calculated args (#{@calculated_args}) and args (#{@args})"}
|
526
|
+
Glimmer::Config.logger.error {e.full_message}
|
527
|
+
end
|
528
|
+
|
529
|
+
def paint_self(paint_event)
|
530
|
+
@painting = true
|
414
531
|
calculate_paint_args!
|
532
|
+
@original_properties_backup = {}
|
415
533
|
@properties.each do |property, args|
|
416
534
|
method_name = attribute_setter(property)
|
417
|
-
|
535
|
+
@original_properties_backup[method_name] = paint_event.gc.send(method_name.sub('set', 'get')) rescue nil
|
418
536
|
paint_event.gc.send(method_name, *args)
|
419
537
|
if property == 'transform' && args.first.is_a?(TransformProxy)
|
420
538
|
args.first.swt_transform.dispose
|
421
539
|
end
|
422
540
|
end
|
423
|
-
|
424
|
-
|
541
|
+
ensure_extent(paint_event)
|
542
|
+
if !@calculated_args || parent_shape_absolute_location_changed?
|
543
|
+
@calculated_args = calculated_args
|
544
|
+
end
|
545
|
+
# paint unless parent's calculated args are not calculated yet, meaning it is about to get painted and trigger a paint on this child anyways
|
546
|
+
paint_event.gc.send(@method_name, *@calculated_args) unless parent.is_a?(Shape) && !parent.calculated_args?
|
547
|
+
@original_properties_backup.each do |method_name, value|
|
548
|
+
paint_event.gc.send(method_name, value)
|
549
|
+
end
|
550
|
+
@painting = false
|
425
551
|
rescue => e
|
426
|
-
Glimmer::Config.logger.error {"Error encountered in painting shape
|
552
|
+
Glimmer::Config.logger.error {"Error encountered in painting shape (#{self.inspect}) with calculated args (#{@calculated_args}) and args (#{@args})"}
|
427
553
|
Glimmer::Config.logger.error {e.full_message}
|
554
|
+
ensure
|
555
|
+
@painting = false
|
556
|
+
end
|
557
|
+
|
558
|
+
def paint_children(paint_event)
|
559
|
+
shapes.to_a.each do |shape|
|
560
|
+
shape.paint(paint_event)
|
561
|
+
end
|
562
|
+
end
|
563
|
+
|
564
|
+
def ensure_extent(paint_event)
|
565
|
+
old_extent = @extent
|
566
|
+
if ['text', 'string'].include?(@name)
|
567
|
+
extent_args = [string]
|
568
|
+
extent_flags = SWTProxy[:draw_transparent] if current_parameter_name?(:is_transparent) && is_transparent
|
569
|
+
extent_flags = flags if current_parameter_name?(:flags)
|
570
|
+
extent_args << extent_flags unless extent_flags.nil?
|
571
|
+
self.extent = paint_event.gc.send("#{@name}Extent", *extent_args)
|
572
|
+
end
|
573
|
+
if !@extent.nil? && (old_extent&.x != @extent&.x || old_extent&.y != @extent&.y)
|
574
|
+
calculated_args_changed!
|
575
|
+
parent.calculated_args_changed_for_defaults! if parent.is_a?(Shape)
|
576
|
+
end
|
577
|
+
end
|
578
|
+
|
579
|
+
def expanded_shapes
|
580
|
+
if shapes.to_a.any?
|
581
|
+
shapes.map do |shape|
|
582
|
+
[shape] + shape.expanded_shapes
|
583
|
+
end.flatten
|
584
|
+
else
|
585
|
+
[]
|
586
|
+
end
|
587
|
+
end
|
588
|
+
|
589
|
+
def parent_shape_absolute_location_changed?
|
590
|
+
(parent.is_a?(Shape) && (parent.absolute_x != @parent_absolute_x || parent.absolute_y != @parent_absolute_y))
|
591
|
+
end
|
592
|
+
|
593
|
+
def calculated_args_changed!(children: true)
|
594
|
+
# TODO add a children: true option to enable setting to false to avoid recalculating children args
|
595
|
+
@calculated_args = nil
|
596
|
+
shapes.each(&:calculated_args_changed!) if children
|
597
|
+
end
|
598
|
+
|
599
|
+
def calculated_args_changed_for_defaults!
|
600
|
+
has_default_dimensions = default_width? || default_height?
|
601
|
+
parent_calculated_args_changed_for_defaults = has_default_dimensions
|
602
|
+
@calculated_args = nil if default_x? || default_y? || has_default_dimensions
|
603
|
+
if has_default_dimensions && parent.is_a?(Shape)
|
604
|
+
parent.calculated_args_changed_for_defaults!
|
605
|
+
elsif @content_added && !drawable.is_disposed
|
606
|
+
# TODO consider optimizing in the future if needed by ensuring one redraw for all parents in the hierarchy at the end instead of doing one per parent that needs it
|
607
|
+
drawable.redraw if !@painting && !drawable.is_a?(ImageProxy)
|
608
|
+
end
|
609
|
+
end
|
610
|
+
|
611
|
+
def calculated_args?
|
612
|
+
!!@calculated_args
|
613
|
+
end
|
614
|
+
|
615
|
+
# args translated to absolute coordinates
|
616
|
+
def calculated_args
|
617
|
+
return @args if !default_x? && !default_y? && !default_width? && !default_height? && parent.is_a?(Drawable)
|
618
|
+
# Note: Must set x and move_by because not all shapes have a real x and some must translate all their points with move_by
|
619
|
+
# TODO change that by setting a bounding box for all shapes with a calculated top-left x, y and
|
620
|
+
# a setter that does the moving inside them instead so that I could rely on absolute_x and absolute_y
|
621
|
+
# here to get the job done of calculating absolute args
|
622
|
+
@perform_redraw = false
|
623
|
+
original_x = nil
|
624
|
+
original_y = nil
|
625
|
+
original_width = nil
|
626
|
+
original_height = nil
|
627
|
+
if parent.is_a?(Shape)
|
628
|
+
@parent_absolute_x = parent.absolute_x
|
629
|
+
@parent_absolute_y = parent.absolute_y
|
630
|
+
end
|
631
|
+
if default_width?
|
632
|
+
original_width = width
|
633
|
+
self.width = default_width + default_width_delta
|
634
|
+
end
|
635
|
+
if default_height?
|
636
|
+
original_height = height
|
637
|
+
self.height = default_height + default_height_delta
|
638
|
+
end
|
639
|
+
if default_x?
|
640
|
+
original_x = x
|
641
|
+
self.x = default_x + default_x_delta
|
642
|
+
end
|
643
|
+
if default_y?
|
644
|
+
original_y = y
|
645
|
+
self.y = default_y + default_y_delta
|
646
|
+
end
|
647
|
+
if parent.is_a?(Shape)
|
648
|
+
move_by(@parent_absolute_x, @parent_absolute_y)
|
649
|
+
result_args = @args.clone
|
650
|
+
move_by(-1*@parent_absolute_x, -1*@parent_absolute_y)
|
651
|
+
else
|
652
|
+
result_args = @args.clone
|
653
|
+
end
|
654
|
+
if original_x
|
655
|
+
self.x = original_x
|
656
|
+
end
|
657
|
+
if original_y
|
658
|
+
self.y = original_y
|
659
|
+
end
|
660
|
+
if original_width
|
661
|
+
self.width = original_width
|
662
|
+
end
|
663
|
+
if original_height
|
664
|
+
self.height = original_height
|
665
|
+
end
|
666
|
+
@perform_redraw = true
|
667
|
+
result_args
|
668
|
+
end
|
669
|
+
|
670
|
+
def default_x?
|
671
|
+
current_parameter_name?(:x) and
|
672
|
+
(x.nil? || x.to_s == 'default' || (x.is_a?(Array) && x.first.to_s == 'default'))
|
673
|
+
end
|
674
|
+
|
675
|
+
def default_y?
|
676
|
+
current_parameter_name?(:y) and
|
677
|
+
(y.nil? || y.to_s == 'default' || (y.is_a?(Array) && y.first.to_s == 'default'))
|
678
|
+
end
|
679
|
+
|
680
|
+
def default_width?
|
681
|
+
return false unless current_parameter_name?(:width)
|
682
|
+
width = self.width
|
683
|
+
(width.nil? || width == :default || width == 'default' || (width.is_a?(Array) && (width.first.to_s == :default || width.first.to_s == 'default')))
|
684
|
+
end
|
685
|
+
|
686
|
+
def default_height?
|
687
|
+
return false unless current_parameter_name?(:height)
|
688
|
+
height = self.height
|
689
|
+
(height.nil? || height == :default || height == 'default' || (height.is_a?(Array) && (height.first.to_s == :default || height.first.to_s == 'default')))
|
690
|
+
end
|
691
|
+
|
692
|
+
def default_x
|
693
|
+
result = ((parent.size.x - size.x) / 2)
|
694
|
+
result += parent.bounds.x - parent.absolute_x if parent.is_a?(Shape) && parent.irregular?
|
695
|
+
result
|
696
|
+
end
|
697
|
+
|
698
|
+
def default_y
|
699
|
+
result = ((parent.size.y - size.y) / 2)
|
700
|
+
result += parent.bounds.y - parent.absolute_y if parent.is_a?(Shape) && parent.irregular?
|
701
|
+
result
|
702
|
+
end
|
703
|
+
|
704
|
+
def default_width
|
705
|
+
# TODO consider caching
|
706
|
+
x_ends = shapes.map do |shape|
|
707
|
+
shape_width = shape.calculated_width.to_f
|
708
|
+
shape_x = shape.default_x? ? 0 : shape.x.to_f
|
709
|
+
shape_x + shape_width
|
710
|
+
end
|
711
|
+
x_ends.max.to_f
|
712
|
+
end
|
713
|
+
|
714
|
+
def default_height
|
715
|
+
# TODO consider caching
|
716
|
+
y_ends = shapes.map do |shape|
|
717
|
+
shape_height = shape.calculated_height.to_f
|
718
|
+
shape_y = shape.default_y? ? 0 : shape.y.to_f
|
719
|
+
shape_y + shape_height
|
720
|
+
end
|
721
|
+
y_ends.max.to_f
|
722
|
+
end
|
723
|
+
|
724
|
+
def calculated_width
|
725
|
+
default_width? ? (default_width + default_width_delta) : width
|
726
|
+
end
|
727
|
+
|
728
|
+
def calculated_height
|
729
|
+
default_height? ? (default_height + default_height_delta) : height
|
730
|
+
end
|
731
|
+
|
732
|
+
def default_x_delta
|
733
|
+
return 0 unless default_x? && x.is_a?(Array)
|
734
|
+
x[1].to_f
|
735
|
+
end
|
736
|
+
|
737
|
+
def default_y_delta
|
738
|
+
return 0 unless default_y? && y.is_a?(Array)
|
739
|
+
y[1].to_f
|
740
|
+
end
|
741
|
+
|
742
|
+
def default_width_delta
|
743
|
+
return 0 unless default_width? && width.is_a?(Array)
|
744
|
+
width[1].to_f
|
745
|
+
end
|
746
|
+
|
747
|
+
def default_height_delta
|
748
|
+
return 0 unless default_height? && height.is_a?(Array)
|
749
|
+
height[1].to_f
|
750
|
+
end
|
751
|
+
|
752
|
+
def default_x_delta=(delta)
|
753
|
+
return unless default_x?
|
754
|
+
self.x = [:default, delta]
|
755
|
+
end
|
756
|
+
|
757
|
+
def default_y_delta=(delta)
|
758
|
+
return unless default_y?
|
759
|
+
self.y = [:default, delta]
|
760
|
+
end
|
761
|
+
|
762
|
+
def default_width_delta=(delta)
|
763
|
+
return unless default_width?
|
764
|
+
self.width = [:default, delta]
|
765
|
+
end
|
766
|
+
|
767
|
+
def default_height_delta=(delta)
|
768
|
+
return unless default_height?
|
769
|
+
self.height = [:default, delta]
|
770
|
+
end
|
771
|
+
|
772
|
+
def calculated_x
|
773
|
+
result = default_x? ? default_x : self.x
|
774
|
+
result += default_x_delta
|
775
|
+
result
|
776
|
+
end
|
777
|
+
|
778
|
+
def calculated_y
|
779
|
+
result = default_y? ? default_y : self.y
|
780
|
+
result += default_y_delta
|
781
|
+
result
|
782
|
+
end
|
783
|
+
|
784
|
+
def absolute_x
|
785
|
+
x = calculated_x
|
786
|
+
if parent.is_a?(Shape)
|
787
|
+
parent.absolute_x + x
|
788
|
+
else
|
789
|
+
x
|
790
|
+
end
|
791
|
+
end
|
792
|
+
|
793
|
+
def absolute_y
|
794
|
+
y = calculated_y
|
795
|
+
if parent.is_a?(Shape)
|
796
|
+
parent.absolute_y + y
|
797
|
+
else
|
798
|
+
y
|
799
|
+
end
|
800
|
+
end
|
801
|
+
|
802
|
+
# Overriding inspect to avoid printing very long shape hierarchies
|
803
|
+
def inspect
|
804
|
+
"#<#{self.class.name}:0x#{self.hash.to_s(16)} args=#{@args.inspect}, properties=#{@properties.inspect}}>"
|
805
|
+
rescue => e
|
806
|
+
"#<#{self.class.name}:0x#{self.hash.to_s(16)}"
|
428
807
|
end
|
429
808
|
|
430
809
|
def calculate_paint_args!
|
@@ -449,7 +828,7 @@ module Glimmer
|
|
449
828
|
# TODO regarding alpha, make sure to reset it to parent stored alpha once we allow setting shape properties on parents directly without shapes
|
450
829
|
@properties['alpha'] ||= [255]
|
451
830
|
@properties['font'] = [@drawable.font] if @drawable.respond_to?(:font) && draw? && !@properties.keys.map(&:to_s).include?('font')
|
452
|
-
# 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
|
453
832
|
# Also do that with all future-added properties
|
454
833
|
@properties['transform'] = [nil] if @drawable.respond_to?(:transform) && !@properties.keys.map(&:to_s).include?('transform')
|
455
834
|
@properties.each do |property, args|
|