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
@@ -33,7 +33,7 @@ module Glimmer
33
33
  Glimmer::SWT::Custom::Animation.new(parent)
34
34
  end
35
35
 
36
- def add_content(parent, &block)
36
+ def add_content(parent, keyword, *args, &block)
37
37
  super
38
38
  parent.post_add_content
39
39
  end
@@ -0,0 +1,61 @@
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'
23
+ require 'glimmer/dsl/expression'
24
+ require 'glimmer/dsl/parent_expression'
25
+ require 'glimmer/dsl/top_level_expression'
26
+ require 'glimmer/ui/custom_shape'
27
+ require 'glimmer/swt/custom/code_text'
28
+ require 'glimmer/swt/custom/checkbox_group'
29
+
30
+ module Glimmer
31
+ module DSL
32
+ module SWT
33
+ class CustomShapeExpression < Expression
34
+ # TODO Make custom shapes automatically generate static expressions
35
+ include ParentExpression
36
+ include TopLevelExpression
37
+
38
+ def can_interpret?(parent, keyword, *args, &block)
39
+ !!UI::CustomShape.for(keyword)
40
+ end
41
+
42
+ def interpret(parent, keyword, *args, &block)
43
+ options = args.last.is_a?(Hash) ? args.pop : {}
44
+ UI::CustomShape.for(keyword).new(parent, *args, options, &block).tap do |new_custom_shape|
45
+ new_custom_shape.body_root.paint_pixel_by_pixel(&block) if block&.parameters&.count == 2
46
+ end
47
+ end
48
+
49
+ def add_content(parent, keyword, *args, &block)
50
+ # TODO consider avoiding source_location
51
+ return if block&.parameters&.count == 2
52
+ if block.source_location == parent.content&.__getobj__.source_location
53
+ parent.content.call(parent) unless parent.content.called?
54
+ else
55
+ super
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -51,7 +51,7 @@ module Glimmer
51
51
  end
52
52
  end
53
53
 
54
- def add_content(parent, &block)
54
+ def add_content(parent, keyword, *args, &block)
55
55
  # TODO consider avoiding source_location
56
56
  return if block&.parameters&.count == 2
57
57
  if block.source_location == parent.content&.__getobj__.source_location
@@ -57,6 +57,7 @@ module Glimmer
57
57
  widget
58
58
  custom_widget
59
59
  shape
60
+ custom_shape
60
61
  ]
61
62
  )
62
63
  end
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2007-2021 Andy Maleh
2
- #
2
+ #
3
3
  # Permission is hereby granted, free of charge, to any person obtaining
4
4
  # a copy of this software and associated documentation files (the
5
5
  # "Software"), to deal in the Software without restriction, including
@@ -7,10 +7,10 @@
7
7
  # distribute, sublicense, and/or sell copies of the Software, and to
8
8
  # permit persons to whom the Software is furnished to do so, subject to
9
9
  # the following conditions:
10
- #
10
+ #
11
11
  # The above copyright notice and this permission notice shall be
12
12
  # included in all copies or substantial portions of the Software.
13
- #
13
+ #
14
14
  # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
15
  # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
16
  # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -49,7 +49,7 @@ module Glimmer
49
49
  Glimmer::SWT::ExpandItemProxy.new(parent, args)
50
50
  end
51
51
 
52
- def add_content(parent, &block)
52
+ def add_content(parent, keyword, *args, &block)
53
53
  super
54
54
  parent.post_add_content
55
55
  end
@@ -57,7 +57,7 @@ module Glimmer
57
57
  end
58
58
  end
59
59
 
60
- def add_content(parent, &block)
60
+ def add_content(parent, keyword, *args, &block)
61
61
  return if @create_pixel_by_pixel || block&.parameters&.count == 2
62
62
  super
63
63
  parent.post_add_content
@@ -39,7 +39,7 @@ module Glimmer
39
39
  Glimmer::SWT::TransformProxy.new(parent, *args, multiply: true)
40
40
  end
41
41
 
42
- def add_content(parent, &block)
42
+ def add_content(parent, keyword, *args, &block)
43
43
  super
44
44
  parent.post_add_content
45
45
  end
@@ -40,7 +40,7 @@ module Glimmer
40
40
  Glimmer::SWT::Custom::Shape.create(parent, keyword, *args, &block)
41
41
  end
42
42
 
43
- def add_content(parent, &block)
43
+ def add_content(parent, keyword, *args, &block)
44
44
  super
45
45
  parent.post_add_content
46
46
  end
@@ -41,7 +41,7 @@ module Glimmer
41
41
  Glimmer::SWT::TransformProxy.new(parent, *args)
42
42
  end
43
43
 
44
- def add_content(parent, &block)
44
+ def add_content(parent, keyword, *args, &block)
45
45
  super
46
46
  parent.post_add_content
47
47
  end
@@ -46,7 +46,7 @@ module Glimmer
46
46
  end
47
47
  end
48
48
 
49
- def add_content(parent, &block)
49
+ def add_content(parent, keyword, *args, &block)
50
50
  return if block&.parameters&.count == 2
51
51
  super
52
52
  parent.post_add_content
@@ -69,3 +69,4 @@ require 'glimmer/swt/table_column_proxy'
69
69
  require 'glimmer/swt/sash_form_proxy'
70
70
  require 'glimmer/swt/styled_text_proxy'
71
71
  require 'glimmer/swt/date_time_proxy'
72
+ require 'glimmer/swt/tab_folder_proxy'
@@ -99,7 +99,7 @@ module Glimmer
99
99
  def ensure_arg_values_within_valid_bounds
100
100
  if @args.to_a.size >= 3
101
101
  @args = @args.map do |value|
102
- [[value, 255].min, 0].max
102
+ [[value.to_f, 255].min, 0].max
103
103
  end
104
104
  end
105
105
  end
@@ -60,7 +60,6 @@ module Glimmer
60
60
  # Represents a shape (graphics) to be drawn on a control/widget/canvas/display
61
61
  # That is because Shape is drawn on a parent as graphics and doesn't have an SWT widget for itself
62
62
  class Shape
63
- include Packages
64
63
  include Properties
65
64
 
66
65
  class << self
@@ -74,7 +73,9 @@ module Glimmer
74
73
  end
75
74
 
76
75
  def valid?(parent, keyword, *args, &block)
77
- gc_instance_methods.include?(method_name(keyword, arg_options(args)))
76
+ return true if keyword.to_s == 'shape'
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
@@ -126,7 +127,7 @@ module Glimmer
126
127
  end
127
128
  end
128
129
 
129
- attr_reader :drawable, :parent, :name, :args, :options, :shapes
130
+ attr_reader :drawable, :parent, :name, :args, :options, :shapes, :properties
130
131
  attr_accessor :extent
131
132
 
132
133
  def initialize(parent, keyword, *args, &property_block)
@@ -134,7 +135,7 @@ module Glimmer
134
135
  @drawable = @parent.is_a?(Drawable) ? @parent : @parent.drawable
135
136
  @name = keyword
136
137
  @options = self.class.arg_options(args, extract: true)
137
- @method_name = self.class.method_name(keyword, @options)
138
+ @method_name = self.class.method_name(keyword, @options) unless keyword.to_s == 'shape'
138
139
  @args = args
139
140
  @properties = {}
140
141
  @shapes = [] # nested shapes
@@ -225,6 +226,13 @@ 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, @name, &block)
232
+ calculated_args_changed!(children: false)
233
+ end
234
+ end
235
+
228
236
  def has_some_background?
229
237
  @properties.keys.map(&:to_s).include?('background') || @properties.keys.map(&:to_s).include?('background_pattern')
230
238
  end
@@ -234,18 +242,19 @@ module Glimmer
234
242
  end
235
243
 
236
244
  def post_add_content
237
- unless @content_added
238
- amend_method_name_options_based_on_properties!
245
+ amend_method_name_options_based_on_properties!
246
+ if !@content_added || @method_name != @original_method_name
239
247
  @drawable.setup_shape_painting unless @drawable.is_a?(ImageProxy)
240
248
  @content_added = true
241
249
  end
242
250
  end
243
251
 
244
- def apply_property_arg_conversions(method_name, property, args)
252
+ def apply_property_arg_conversions(property, args)
253
+ method_name = attribute_setter(property)
245
254
  args = args.dup
246
255
  the_java_method = org.eclipse.swt.graphics.GC.java_class.declared_instance_methods.detect {|m| m.name == method_name}
247
256
  return args if the_java_method.nil?
248
- if the_java_method.parameter_types.first == Color.java_class && args.first.is_a?(RGB)
257
+ if the_java_method.parameter_types.first == org.eclipse.swt.graphics.Color.java_class && args.first.is_a?(org.eclipse.swt.graphics.RGB)
249
258
  args[0] = [args[0].red, args[0].green, args[0].blue]
250
259
  end
251
260
  if ['setBackground', 'setForeground'].include?(method_name.to_s) && args.first.is_a?(Array)
@@ -255,10 +264,23 @@ module Glimmer
255
264
  args[0] = args.dup
256
265
  args[1..-1] = []
257
266
  end
267
+ if method_name.to_s == 'setAntialias' && [nil, true, false].include?(args.first)
268
+ args[0] = case args.first
269
+ when true
270
+ args[0] = :on
271
+ when false
272
+ args[0] = :off
273
+ when nil
274
+ args[0] = :default
275
+ end
276
+ end
258
277
  if args.first.is_a?(Symbol) || args.first.is_a?(::String)
259
- if the_java_method.parameter_types.first == Color.java_class
278
+ if the_java_method.parameter_types.first == org.eclipse.swt.graphics.Color.java_class
260
279
  args[0] = ColorProxy.new(args[0])
261
280
  end
281
+ if method_name.to_s == 'setLineStyle'
282
+ args[0] = "line_#{args[0]}" if !args[0].to_s.downcase.start_with?('line_')
283
+ end
262
284
  if the_java_method.parameter_types.first == Java::int.java_class
263
285
  args[0] = SWTProxy.constant(args[0])
264
286
  end
@@ -266,7 +288,7 @@ module Glimmer
266
288
  if args.first.is_a?(ColorProxy)
267
289
  args[0] = args[0].swt_color
268
290
  end
269
- if (args.first.is_a?(Hash) || args.first.is_a?(FontData)) && the_java_method.parameter_types.first == Font.java_class
291
+ if (args.first.is_a?(Hash) || args.first.is_a?(org.eclipse.swt.graphics.FontData)) && the_java_method.parameter_types.first == org.eclipse.swt.graphics.Font.java_class
270
292
  args[0] = FontProxy.new(args[0])
271
293
  end
272
294
  if args.first.is_a?(FontProxy)
@@ -279,7 +301,7 @@ module Glimmer
279
301
  @drawable.requires_shape_disposal = true
280
302
  args = args.first if args.first.is_a?(Array)
281
303
  args.each_with_index do |arg, i|
282
- arg = ColorProxy.new(arg.red, arg.green, arg.blue) if arg.is_a?(RGB)
304
+ arg = ColorProxy.new(arg.red, arg.green, arg.blue) if arg.is_a?(org.eclipse.swt.graphics.RGB)
283
305
  arg = ColorProxy.new(arg) if arg.is_a?(Symbol) || arg.is_a?(::String)
284
306
  arg = arg.swt_color if arg.is_a?(ColorProxy)
285
307
  args[i] = arg
@@ -328,10 +350,16 @@ module Glimmer
328
350
  end
329
351
 
330
352
  def apply_shape_arg_defaults!
331
- self.x = :default if current_parameter_name?(:x) && x.nil?
332
- self.y = :default if current_parameter_name?(:y) && y.nil?
333
- self.dest_x = :default if current_parameter_name?(:dest_x) && dest_x.nil?
334
- self.dest_y = :default if current_parameter_name?(:dest_y) && dest_y.nil?
353
+ if current_parameter_name?(:dest_x) && dest_x.nil?
354
+ self.dest_x = :default
355
+ elsif parameter_name?(:x) && x.nil?
356
+ self.x = :default
357
+ end
358
+ if current_parameter_name?(:dest_y) && dest_y.nil?
359
+ self.dest_y = :default
360
+ elsif parameter_name?(:y) && y.nil?
361
+ self.y = :default
362
+ end
335
363
  self.width = :default if current_parameter_name?(:width) && width.nil?
336
364
  self.height = :default if current_parameter_name?(:height) && height.nil?
337
365
  if @name.include?('rectangle') && round? && @args.size.between?(4, 5)
@@ -358,6 +386,7 @@ module Glimmer
358
386
  end
359
387
 
360
388
  def amend_method_name_options_based_on_properties!
389
+ @original_method_name = @method_name
361
390
  return if @name == 'point'
362
391
  if @name != 'text' && @name != 'string' && has_some_background? && !has_some_foreground?
363
392
  @options[:fill] = true
@@ -375,7 +404,7 @@ module Glimmer
375
404
 
376
405
  # parameter names for arguments to pass to SWT GC.xyz method for rendering shape (e.g. draw_image(image, x, y) yields :image, :x, :y parameter names)
377
406
  def parameter_names
378
- []
407
+ [:x, :y, :width, :height]
379
408
  end
380
409
 
381
410
  # subclasses may override to specify location parameter names if different from x and y (e.g. all polygon points are location parameters)
@@ -425,6 +454,11 @@ module Glimmer
425
454
  end
426
455
  if @content_added && perform_redraw && !drawable.is_disposed
427
456
  @calculated_paint_args = false
457
+ if is_a?(PathSegment)
458
+ root_path&.calculated_path_args = @calculated_path_args = false
459
+ calculated_args_changed!
460
+ root_path&.calculated_args_changed!
461
+ end
428
462
  attribute_name = ruby_attribute_getter(attribute_name)
429
463
  if location_parameter_names.map(&:to_s).include?(attribute_name)
430
464
  @calculated_args = nil
@@ -490,7 +524,8 @@ module Glimmer
490
524
  pattern_args(type: 'foreground')
491
525
  end
492
526
 
493
- def dispose(dispose_images: true, dispose_patterns: true)
527
+ def dispose(dispose_images: true, dispose_patterns: true, redraw: true)
528
+ shapes.each { |shape| shape.is_a?(Shape::Path) && shape.dispose }
494
529
  if dispose_patterns
495
530
  @background_pattern&.dispose
496
531
  @background_pattern = nil
@@ -502,10 +537,42 @@ module Glimmer
502
537
  @image = nil
503
538
  end
504
539
  @parent.shapes.delete(self)
540
+ drawable.redraw if redraw && !drawable.is_a?(ImageProxy)
541
+ end
542
+
543
+ # Indicate if this is a shape composite (meaning a shape bag that just contains nested shapes, but doesn't render anything of its own)
544
+ def shape_composite?
545
+ @name == 'shape'
546
+ end
547
+
548
+ # ordered from closest to farthest parent
549
+ def parent_shapes
550
+ current_parent = parent
551
+ the_parent_shapes = []
552
+ until current_parent.is_a?(Drawable)
553
+ the_parent_shapes << current_parent
554
+ current_parent = current_parent.parent
555
+ end
556
+ the_parent_shapes
557
+ end
558
+
559
+ # ordered from closest to farthest parent
560
+ def parent_shape_composites
561
+ parent_shapes.select(&:shape_composite?)
562
+ end
563
+
564
+ def all_parent_properties
565
+ # TODO consider providing a converted property version of this ready for consumption
566
+ @all_parent_properties ||= parent_shape_composites.reverse.reduce({}) do |all_properties, parent_shape|
567
+ parent_properties = parent_shape.properties
568
+ parent_properties.each do |property, args|
569
+ parent_properties[property] = apply_property_arg_conversions(property, args)
570
+ end
571
+ all_properties.merge(parent_properties)
572
+ end
505
573
  end
506
574
 
507
575
  def paint(paint_event)
508
- # pre-paint children an extra-time first when default width/height need to be calculated for defaults
509
576
  paint_children(paint_event) if default_width? || default_height?
510
577
  paint_self(paint_event)
511
578
  # re-paint children from scratch in the special case of pre-calculating parent width/height to re-center within new parent dimensions
@@ -518,28 +585,33 @@ module Glimmer
518
585
 
519
586
  def paint_self(paint_event)
520
587
  @painting = true
521
- calculate_paint_args!
522
- @original_properties_backup = {}
523
- @properties.each do |property, args|
524
- method_name = attribute_setter(property)
525
- @original_properties_backup[method_name] = paint_event.gc.send(method_name.sub('set', 'get')) rescue nil
526
- paint_event.gc.send(method_name, *args)
527
- if property == 'transform' && args.first.is_a?(TransformProxy)
528
- args.first.swt_transform.dispose
588
+ unless shape_composite?
589
+ calculate_paint_args!
590
+ @original_gc_properties = {} # this stores GC properties before making calls to updates TODO avoid using in pixel graphics
591
+ @original_properties = @properties # this stores original shape attributes like background/foreground/font
592
+ @properties.merge(all_parent_properties).each do |property, args|
593
+ method_name = attribute_setter(property)
594
+ @original_gc_properties[method_name] = paint_event.gc.send(method_name.sub('set', 'get')) rescue nil
595
+ paint_event.gc.send(method_name, *args)
596
+ if property == 'transform' && args.first.is_a?(TransformProxy)
597
+ args.first.swt_transform.dispose
598
+ end
529
599
  end
600
+ ensure_extent(paint_event)
530
601
  end
531
- ensure_extent(paint_event)
532
602
  if !@calculated_args || parent_shape_absolute_location_changed?
533
603
  @calculated_args = calculated_args
534
604
  end
535
- # 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
536
- paint_event.gc.send(@method_name, *@calculated_args) unless parent.is_a?(Shape) && !parent.calculated_args?
537
- @original_properties_backup.each do |method_name, value|
538
- paint_event.gc.send(method_name, value)
605
+ unless shape_composite?
606
+ # 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
607
+ paint_event.gc.send(@method_name, *@calculated_args) unless (parent.is_a?(Shape) && !parent.calculated_args?)
608
+ @original_gc_properties.each do |method_name, value|
609
+ paint_event.gc.send(method_name, value)
610
+ end
539
611
  end
540
612
  @painting = false
541
613
  rescue => e
542
- Glimmer::Config.logger.error {"Error encountered in painting shape (#{self.inspect}) with calculated args (#{@calculated_args}) and args (#{@args})"}
614
+ Glimmer::Config.logger.error {"Error encountered in painting shape (#{self.inspect}) with method (#{@method_name}) calculated args (#{@calculated_args}) and args (#{@args})"}
543
615
  Glimmer::Config.logger.error {e.full_message}
544
616
  ensure
545
617
  @painting = false
@@ -620,11 +692,19 @@ module Glimmer
620
692
  end
621
693
  if default_width?
622
694
  original_width = width
623
- self.width = default_width + default_width_delta
695
+ self.width = default_width + width_delta
624
696
  end
625
697
  if default_height?
626
698
  original_height = height
627
- self.height = default_height + default_height_delta
699
+ self.height = default_height + height_delta
700
+ end
701
+ if max_width?
702
+ original_width = width
703
+ self.width = max_width + width_delta
704
+ end
705
+ if max_height?
706
+ original_height = height
707
+ self.height = max_height + height_delta
628
708
  end
629
709
  if default_x?
630
710
  original_x = x
@@ -679,6 +759,16 @@ module Glimmer
679
759
  (height.nil? || height == :default || height == 'default' || (height.is_a?(Array) && (height.first.to_s == :default || height.first.to_s == 'default')))
680
760
  end
681
761
 
762
+ def max_width?
763
+ current_parameter_name?(:width) and
764
+ (width.nil? || width.to_s == 'max' || (width.is_a?(Array) && width.first.to_s == 'max'))
765
+ end
766
+
767
+ def max_height?
768
+ current_parameter_name?(:height) and
769
+ (height.nil? || height.to_s == 'max' || (height.is_a?(Array) && height.first.to_s == 'max'))
770
+ end
771
+
682
772
  def default_x
683
773
  result = ((parent.size.x - size.x) / 2)
684
774
  result += parent.bounds.x - parent.absolute_x if parent.is_a?(Shape) && parent.irregular?
@@ -694,29 +784,61 @@ module Glimmer
694
784
  def default_width
695
785
  # TODO consider caching
696
786
  x_ends = shapes.map do |shape|
697
- shape_width = shape.calculated_width.to_f
698
- shape_x = shape.default_x? ? 0 : shape.x.to_f
699
- shape_x + shape_width
787
+ if shape.max_width?
788
+ 0
789
+ else
790
+ shape_width = shape.calculated_width.to_f
791
+ shape_x = shape.default_x? ? 0 : shape.x.to_f
792
+ shape_x + shape_width
793
+ end
794
+ end
795
+ if shapes.size == 1 && shapes.first.max_width?
796
+ self.parent.size.x
797
+ else
798
+ x_ends.max.to_f
700
799
  end
701
- x_ends.max.to_f
702
800
  end
703
801
 
704
802
  def default_height
705
803
  # TODO consider caching
706
804
  y_ends = shapes.map do |shape|
707
- shape_height = shape.calculated_height.to_f
708
- shape_y = shape.default_y? ? 0 : shape.y.to_f
709
- shape_y + shape_height
805
+ if shape.max_height?
806
+ 0
807
+ else
808
+ shape_height = shape.calculated_height.to_f
809
+ shape_y = shape.default_y? ? 0 : shape.y.to_f
810
+ shape_y + shape_height
811
+ end
812
+ end
813
+ if shapes.size == 1 && shapes.first.max_height?
814
+ self.parent.size.y
815
+ else
816
+ y_ends.max.to_f
710
817
  end
711
- y_ends.max.to_f
818
+ end
819
+
820
+ def max_width
821
+ # consider caching
822
+ parent.is_a?(Drawable) ? parent.size.x : parent.calculated_width
823
+ end
824
+
825
+ def max_height
826
+ # consider caching
827
+ parent.is_a?(Drawable) ? parent.size.y : parent.calculated_height
712
828
  end
713
829
 
714
830
  def calculated_width
715
- default_width? ? (default_width + default_width_delta) : width
831
+ result_width = width
832
+ result_width = (default_width + width_delta) if default_width?
833
+ result_width = (max_width + width_delta) if max_width?
834
+ result_width
716
835
  end
717
836
 
718
837
  def calculated_height
719
- default_height? ? (default_height + default_height_delta) : height
838
+ result_height = height
839
+ result_height = (default_height + height_delta) if default_height?
840
+ result_height = (max_height + height_delta) if max_height?
841
+ result_height
720
842
  end
721
843
 
722
844
  def default_x_delta
@@ -729,12 +851,12 @@ module Glimmer
729
851
  y[1].to_f
730
852
  end
731
853
 
732
- def default_width_delta
854
+ def width_delta
733
855
  return 0 unless default_width? && width.is_a?(Array)
734
856
  width[1].to_f
735
857
  end
736
858
 
737
- def default_height_delta
859
+ def height_delta
738
860
  return 0 unless default_height? && height.is_a?(Array)
739
861
  height[1].to_f
740
862
  end
@@ -749,12 +871,12 @@ module Glimmer
749
871
  self.y = [:default, delta]
750
872
  end
751
873
 
752
- def default_width_delta=(delta)
874
+ def width_delta=(delta)
753
875
  return unless default_width?
754
876
  self.width = [:default, delta]
755
877
  end
756
878
 
757
- def default_height_delta=(delta)
879
+ def height_delta=(delta)
758
880
  return unless default_height?
759
881
  self.height = [:default, delta]
760
882
  end
@@ -801,7 +923,7 @@ module Glimmer
801
923
  if @name == 'pixel'
802
924
  @name = 'point'
803
925
  # optimized performance calculation for pixel points
804
- if !@properties[:foreground].is_a?(Color)
926
+ if !@properties[:foreground].is_a?(org.eclipse.swt.graphics.Color)
805
927
  if @properties[:foreground].is_a?(Array)
806
928
  @properties[:foreground] = ColorProxy.new(@properties[:foreground], ensure_bounds: false)
807
929
  end
@@ -818,13 +940,11 @@ module Glimmer
818
940
  # TODO regarding alpha, make sure to reset it to parent stored alpha once we allow setting shape properties on parents directly without shapes
819
941
  @properties['alpha'] ||= [255]
820
942
  @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
943
+ # TODO regarding transform, make sure to reset it to parent stored transform once we allow setting shape properties on parents directly without shapes
822
944
  # Also do that with all future-added properties
823
945
  @properties['transform'] = [nil] if @drawable.respond_to?(:transform) && !@properties.keys.map(&:to_s).include?('transform')
824
946
  @properties.each do |property, args|
825
- method_name = attribute_setter(property)
826
- converted_args = apply_property_arg_conversions(method_name, property, args)
827
- @properties[property] = converted_args
947
+ @properties[property] = apply_property_arg_conversions(property, args)
828
948
  end
829
949
  apply_shape_arg_conversions!
830
950
  apply_shape_arg_defaults!