glimmer-dsl-swt 4.18.5.5 → 4.18.7.0

Sign up to get free protection for your applications and to get access to all the features.
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!