glimmer-dsl-swt 4.22.0.0 → 4.22.2.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 (67) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +207 -169
  3. data/README.md +10 -10
  4. data/RUBY_VERSION +1 -1
  5. data/VERSION +1 -1
  6. data/docs/reference/GLIMMER_COMMAND.md +21 -7
  7. data/docs/reference/GLIMMER_CONFIGURATION.md +14 -3
  8. data/docs/reference/GLIMMER_GIRB.md +1 -1
  9. data/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md +743 -113
  10. data/docs/reference/GLIMMER_SAMPLES.md +22 -8
  11. data/glimmer-dsl-swt.gemspec +0 -0
  12. data/lib/ext/glimmer/config.rb +41 -24
  13. data/lib/glimmer/data_binding/observable_widget.rb +6 -6
  14. data/lib/glimmer/data_binding/widget_binding.rb +2 -1
  15. data/lib/glimmer/dsl/swt/dsl.rb +1 -1
  16. data/lib/glimmer/dsl/swt/observe_expression.rb +2 -1
  17. data/lib/glimmer/dsl/swt/shape_expression.rb +1 -0
  18. data/lib/glimmer/dsl/swt/shine_data_binding_expression.rb +3 -8
  19. data/lib/glimmer/dsl/swt/transform_expression.rb +1 -1
  20. data/lib/glimmer/launcher.rb +16 -15
  21. data/lib/glimmer/rake_task/scaffold.rb +5 -16
  22. data/lib/glimmer/swt/color_proxy.rb +5 -5
  23. data/lib/glimmer/swt/custom/drawable.rb +4 -0
  24. data/lib/glimmer/swt/custom/shape/line.rb +0 -1
  25. data/lib/glimmer/swt/custom/shape/path.rb +2 -2
  26. data/lib/glimmer/swt/custom/shape/path_segment.rb +2 -2
  27. data/lib/glimmer/swt/custom/shape/point.rb +8 -1
  28. data/lib/glimmer/swt/custom/shape.rb +171 -69
  29. data/lib/glimmer/swt/display_proxy.rb +15 -10
  30. data/lib/glimmer/swt/image_proxy.rb +5 -5
  31. data/lib/glimmer/swt/message_box_proxy.rb +5 -5
  32. data/lib/glimmer/swt/shape_listener_proxy.rb +55 -0
  33. data/lib/glimmer/swt/shell_proxy.rb +1 -0
  34. data/lib/glimmer/swt/transform_proxy.rb +3 -3
  35. data/lib/glimmer/swt/tray_proxy.rb +4 -4
  36. data/lib/glimmer/swt/widget_proxy.rb +5 -7
  37. data/lib/glimmer/ui/custom_shape.rb +34 -10
  38. data/lib/glimmer/ui/custom_widget.rb +3 -8
  39. data/lib/glimmer-dsl-swt.rb +6 -2
  40. data/samples/elaborate/klondike_solitaire/model/column_pile.rb +0 -1
  41. data/samples/elaborate/klondike_solitaire/view/column_pile.rb +3 -16
  42. data/samples/elaborate/klondike_solitaire/view/dealing_pile.rb +1 -1
  43. data/samples/elaborate/klondike_solitaire/view/dealt_pile.rb +12 -5
  44. data/samples/elaborate/klondike_solitaire/view/empty_playing_card.rb +2 -1
  45. data/samples/elaborate/klondike_solitaire/view/foundation_pile.rb +2 -2
  46. data/samples/elaborate/klondike_solitaire/view/hidden_playing_card.rb +2 -2
  47. data/samples/elaborate/klondike_solitaire/view/klondike_solitaire_menu_bar.rb +60 -0
  48. data/samples/elaborate/klondike_solitaire/view/playing_card.rb +3 -2
  49. data/samples/elaborate/klondike_solitaire.rb +13 -55
  50. data/samples/elaborate/mandelbrot_fractal.rb +3 -1
  51. data/samples/elaborate/quarto/model/game.rb +124 -0
  52. data/samples/elaborate/quarto/model/piece/cube.rb +31 -0
  53. data/samples/elaborate/quarto/model/piece/cylinder.rb +31 -0
  54. data/samples/elaborate/quarto/model/piece.rb +70 -0
  55. data/samples/elaborate/quarto/view/available_pieces_area.rb +72 -0
  56. data/samples/elaborate/quarto/view/board.rb +65 -0
  57. data/samples/elaborate/quarto/view/cell.rb +85 -0
  58. data/samples/elaborate/quarto/view/cube.rb +73 -0
  59. data/samples/elaborate/quarto/view/cylinder.rb +72 -0
  60. data/samples/elaborate/quarto/view/message_box_panel.rb +114 -0
  61. data/samples/elaborate/quarto/view/piece.rb +56 -0
  62. data/samples/elaborate/quarto/view/selected_piece_area.rb +69 -0
  63. data/samples/elaborate/quarto.rb +188 -0
  64. data/samples/hello/hello_canvas_data_binding.rb +7 -7
  65. data/samples/hello/hello_custom_widget.rb +23 -5
  66. metadata +35 -40
  67. data/bin/glimmer_runner.rb +0 -4
@@ -25,6 +25,7 @@ require 'glimmer/swt/display_proxy'
25
25
  require 'glimmer/swt/color_proxy'
26
26
  require 'glimmer/swt/font_proxy'
27
27
  require 'glimmer/swt/transform_proxy'
28
+ require 'glimmer/swt/shape_listener_proxy'
28
29
 
29
30
  class Java::OrgEclipseSwtGraphics::GC
30
31
  def setLineDashOffset(value)
@@ -65,7 +66,7 @@ module Glimmer
65
66
  DropEvent = Struct.new(:doit, :x, :y, :dragged_shape, :dragged_shape_original_x, :dragged_shape_original_y, :dragging_x, :dragging_y, :drop_shapes, keyword_init: true)
66
67
 
67
68
  class << self
68
- attr_accessor :dragging, :dragging_x, :dragging_y, :dragged_shape, :dragged_shape_original_x, :dragged_shape_original_y
69
+ attr_accessor :dragging, :dragging_x, :dragging_y, :dragged_shape, :dragged_shape_original_x, :dragged_shape_original_y, :drop_shape_handling_count
69
70
  alias dragging? dragging
70
71
 
71
72
  def create(parent, keyword, *args, &property_block)
@@ -132,15 +133,13 @@ module Glimmer
132
133
  def flyweight_patterns
133
134
  @flyweight_patterns ||= {}
134
135
  end
135
-
136
- # shapes that have defined on_drop expecting to received a dragged shape
137
- def drop_shapes
138
- @drop_shapes ||= []
139
- end
140
136
  end
141
137
 
142
- attr_reader :drawable, :parent, :name, :args, :options, :shapes, :properties
138
+ attr_reader :drawable, :parent, :name, :args, :options, :shapes, :properties, :disposed, :widget_listener_proxies
143
139
  attr_accessor :extent
140
+ alias disposed? disposed
141
+ alias is_disposed disposed # for SWT widget compatibility
142
+ # TODO consider making shapes return a dup, always, in case consumers want to dispose
144
143
 
145
144
  def initialize(parent, keyword, *args, &property_block)
146
145
  @parent = parent
@@ -229,20 +228,47 @@ module Glimmer
229
228
  contain?(x, y)
230
229
  end
231
230
 
232
- def include_with_children?(x, y, except_child: nil)
233
- included = include?(x, y)
234
- included ||= expanded_shapes.reject {|shape| shape == except_child}.detect { |shape| shape.include?(x, y) }
231
+ def include_with_children?(x, y, except_shape: nil)
232
+ included_in_self = (!self.equal?(except_shape) && include?(x, y))
233
+ # TODO note that expanded shapes does not filter when reject below happens, keeping nested shapes
234
+ included_in_self || expanded_shapes(except_shape: except_shape).any? { |shape| shape.include?(x, y) }
235
+ end
236
+
237
+ def bounds_contain?(x, y)
238
+ x, y = inverse_transform_point(x, y)
239
+ bounds.contains(x, y)
240
+ end
241
+
242
+ # Recursively checks if other shape is included in this shape, beginning by comparing to self
243
+ # and then recursing into children shapes.
244
+ def include_shape?(other)
245
+ self == other || shapes.any? { |shape| shape.include_shape?(other) }
235
246
  end
236
247
 
248
+ # if there is a transform, apply on x, y point coordinates
249
+ def transform_point(x, y)
250
+ # keep in mind that transform is an array of a single element that is the transform object
251
+ current_transform = (transform || parent_shape_containers.map(&:transform).first)&.first
252
+ if current_transform
253
+ transform_array = [x, y].to_java(:float) # just placeholder data that gets overwritten with getElements
254
+ current_transform.transform(transform_array)
255
+ x = transform_array[0]
256
+ y = transform_array[1]
257
+ end
258
+ [x, y]
259
+ end
260
+
237
261
  # if there is a transform, invert it and apply on x, y point coordinates
238
262
  def inverse_transform_point(x, y)
239
- current_transform = (transform || parent_shape_containers.map(&:transform).first)&.first
263
+ # keep in mind that transform is an array of a single element that is the transform object
264
+ current_transform = (transform || parent_shape_containers.map(&:transform).compact.first)&.first
240
265
  if current_transform
241
- transform_array = [1,2,3,4,5,6].to_java(:float)
266
+ transform_array = [1,2,3,4,5,6].to_java(:float) # just placeholder data that gets overwritten with getElements
242
267
  current_transform.getElements(transform_array)
243
268
  inverse_transform = TransformProxy.new(DisplayProxy.instance.swt_display, *transform_array.to_a)
244
- inverse_transform_array = [1,2,3,4,5,6].to_java(:float)
269
+ inverse_transform_array = [1,2,3,4,5,6].to_java(:float) # just placeholder data that gets overwritten with getElements
245
270
  inverse_transform.getElements(inverse_transform_array)
271
+ # TODO avoid Matrix usage directly by relying on SWT Transform#invert method instead (much simpler)
246
272
  matrix = Matrix[[inverse_transform_array[0], inverse_transform_array[1]], [inverse_transform_array[2], inverse_transform_array[3]]]
247
273
  result = matrix * Matrix.column_vector([x, y])
248
274
  x, y = result.to_a.flatten
@@ -315,6 +341,7 @@ module Glimmer
315
341
  end
316
342
 
317
343
  def content(&block)
344
+ # TODO consider supporting adding content without redraw (redraw: false)
318
345
  Glimmer::SWT::DisplayProxy.instance.auto_exec do
319
346
  Glimmer::DSL::Engine.add_content(self, Glimmer::DSL::SWT::ShapeExpression.new, @name, &block)
320
347
  calculated_args_changed!(children: false)
@@ -601,17 +628,27 @@ module Glimmer
601
628
  end
602
629
 
603
630
  def can_handle_observation_request?(observation_request)
604
- drawable.can_handle_observation_request?(observation_request)
605
- end
606
-
607
- def handle_observation_request(observation_request, &block)
608
- shape_block = lambda do |event|
609
- block.call(event) if include_with_children?(event.x, event.y)
631
+ observation_request = observation_request.to_s
632
+ observation_request.start_with?('on_') &&
633
+ (
634
+ observation_request == 'on_shape_disposed' ||
635
+ (
636
+ drawable.respond_to?(:can_handle_observation_request?) &&
637
+ drawable.can_handle_observation_request?(observation_request)
638
+ )
639
+ )
640
+ end
641
+
642
+ def handle_observation_request(observation_request, source_observation_request: nil, &block)
643
+ if observation_request.to_s == 'on_shape_disposed'
644
+ @on_shape_disposed_handlers ||= []
645
+ @on_shape_disposed_handlers << block
646
+ return ShapeListenerProxy.new(shape: self, drawable: drawable, shape_listener_block: block, observation_request: 'on_shape_disposed')
610
647
  end
611
648
  if observation_request == 'on_drop'
612
- Shape.drop_shapes << self
613
- handle_observation_request('on_mouse_up') do |event|
614
- if Shape.dragging && include_with_children?(event.x, event.y, except_child: Shape.dragged_shape)
649
+ drawable.drop_shapes << self
650
+ handle_observation_request('on_mouse_up', source_observation_request: 'on_drop') do |event|
651
+ if Shape.dragging && include_with_children?(event.x, event.y, except_shape: Shape.dragged_shape)
615
652
  drop_event = DropEvent.new(
616
653
  doit: true,
617
654
  dragged_shape: Shape.dragged_shape,
@@ -619,29 +656,56 @@ module Glimmer
619
656
  dragged_shape_original_y: Shape.dragged_shape_original_y,
620
657
  dragging_x: Shape.dragging_x,
621
658
  dragging_y: Shape.dragging_y,
622
- drop_shapes: Shape.drop_shapes,
659
+ drop_shapes: drawable.drop_shapes,
623
660
  x: event.x,
624
661
  y: event.y
625
662
  )
626
663
  begin
627
664
  block.call(drop_event)
628
665
  rescue => e
629
- Glimmer::Config.logger.error e.full_message
666
+ Glimmer::Config.logger.error {e.full_message}
630
667
  ensure
631
- Shape.dragging = false
632
- if !drop_event.doit && Shape.dragged_shape
633
- Shape.dragged_shape.x = Shape.dragged_shape_original_x
634
- Shape.dragged_shape.y = Shape.dragged_shape_original_y
668
+ if drop_event.doit
669
+ Shape.dragging = false
670
+ Shape.dragged_shape = nil
671
+ elsif Shape.drop_shape_handling_count.to_i >= drawable.drop_shapes.count && Shape.dragged_shape
672
+ cancel_dragging!
635
673
  end
636
- Shape.dragged_shape = nil
674
+ end
675
+ else
676
+ if Shape.drop_shape_handling_count.to_i >= drawable.drop_shapes.count
677
+ cancel_dragging!
637
678
  end
638
679
  end
639
680
  end
640
681
  else
641
- drawable.handle_observation_request(observation_request, &shape_block)
682
+ widget_listener_proxy = nil
683
+ shape_block = lambda do |event|
684
+ if @disposed
685
+ widget_listener_proxy.deregister
686
+ @widget_listener_proxies.delete(widget_listener_proxy)
687
+ else
688
+ Shape.drop_shape_handling_count += 1 if source_observation_request == 'on_drop' && event.x == Shape.dragging_x && event.y == Shape.dragging_y
689
+ if !event.respond_to?(:x) || !event.respond_to?(:y) || include_with_children?(event.x, event.y)
690
+ block.call(event)
691
+ elsif source_observation_request == 'on_drop' && Shape.drop_shape_handling_count.to_i >= drawable.drop_shapes.count
692
+ cancel_dragging!
693
+ end
694
+ end
695
+ end
696
+ widget_listener_proxy = drawable.respond_to?(:handle_observation_request) && drawable.handle_observation_request(observation_request, &shape_block)
697
+ @widget_listener_proxies ||= []
698
+ if widget_listener_proxy
699
+ @widget_listener_proxies << widget_listener_proxy
700
+ ShapeListenerProxy.new(shape: self, drawable: drawable, shape_listener_block: shape_block, observation_request: source_observation_request || observation_request, widget_listener_proxy: widget_listener_proxy)
701
+ end
642
702
  end
643
703
  end
644
704
 
705
+ def remove_shape_disposed_listener(listener_block)
706
+ @on_shape_disposed_handlers.delete(listener_block)
707
+ end
708
+
645
709
  # Sets data just like SWT widgets
646
710
  def set_data(key=nil, value)
647
711
  @data ||= {}
@@ -656,55 +720,75 @@ module Glimmer
656
720
  end
657
721
  alias getData get_data # for compatibility with SWT APIs
658
722
  alias data get_data # for compatibility with SWT APIs
723
+
724
+ def shell_proxy
725
+ drawable.shell_proxy
726
+ end
659
727
 
728
+ def respond_to?(method_name, *args, &block)
729
+ options = args.last if args.last.is_a?(Hash)
730
+ super_invocation = options && options[:super]
731
+ if !super_invocation && has_attribute?(method_name)
732
+ true
733
+ else
734
+ result = super
735
+ return true if result
736
+ can_handle_observation_request?(method_name)
737
+ end
738
+ end
739
+
660
740
  def method_missing(method_name, *args, &block)
661
741
  if method_name.to_s.end_with?('=')
662
742
  set_attribute(method_name, *args)
663
743
  elsif has_attribute?(method_name)
664
744
  get_attribute(method_name)
665
- else # TODO support proxying calls to handle_observation_request for listeners just like WidgetProxy
745
+ elsif block && can_handle_observation_request?(method_name)
746
+ handle_observation_request(method_name, &block)
747
+ else
666
748
  super
667
749
  end
668
750
  end
669
751
 
670
- def respond_to?(method_name, *args, &block)
671
- options = args.last if args.last.is_a?(Hash)
672
- super_invocation = options && options[:super]
673
- if !super_invocation && has_attribute?(method_name)
674
- true
675
- else
676
- super
677
- end
752
+ def deregister_drag_listeners
753
+ @on_drag_detected&.deregister
754
+ @on_drag_detected = nil
755
+ @drawable_on_mouse_move&.deregister
756
+ @drawable_on_mouse_move = nil
757
+ @drawable_on_mouse_up&.deregister
758
+ @drawable_on_mouse_up = nil
678
759
  end
679
-
760
+
761
+ # Enables dragging for drag and move within parent widget
762
+ # drag_and_move and drag_source are mutually exclusive
763
+ # if shape had drag_source true, it is disabled by deregistering its listeners
680
764
  def drag_and_move=(drag_and_move_value)
765
+ deregister_drag_listeners if @drag_source
681
766
  drag_and_move_old_value = @drag_and_move
682
767
  @drag_and_move = drag_and_move_value
683
768
  if @drag_and_move && !drag_and_move_old_value
684
- @on_drag_detected = handle_observation_request('on_drag_detected') do |event|
769
+ @on_drag_detected ||= handle_observation_request('on_drag_detected') do |event|
685
770
  Shape.dragging = true
686
771
  Shape.dragging_x = event.x
687
772
  Shape.dragging_y = event.y
773
+ Shape.drop_shape_handling_count = 0
688
774
  Shape.dragged_shape = self
689
775
  Shape.dragged_shape_original_x = x
690
776
  Shape.dragged_shape_original_y = y
691
777
  end
692
- @drawable_on_mouse_move = drawable.handle_observation_request('on_mouse_move') do |event|
693
- if Shape.dragging && Shape.dragged_shape == self
778
+ @drawable_on_mouse_move ||= drawable.handle_observation_request('on_mouse_move') do |event|
779
+ if Shape.dragging && Shape.dragged_shape.equal?(self)
694
780
  Shape.dragged_shape.move_by((event.x - Shape.dragging_x), (event.y - Shape.dragging_y))
695
781
  Shape.dragging_x = event.x
696
782
  Shape.dragging_y = event.y
697
783
  end
698
784
  end
699
- @drawable_on_mouse_up = drawable.handle_observation_request('on_mouse_up') do |event|
700
- if Shape.dragging && Shape.dragged_shape == self
785
+ @drawable_on_mouse_up ||= drawable.handle_observation_request('on_mouse_up') do |event|
786
+ if Shape.dragging && Shape.dragged_shape.equal?(self)
701
787
  Shape.dragging = false
702
788
  end
703
789
  end
704
790
  elsif !@drag_and_move && drag_and_move_old_value
705
- @on_drag_detected.deregister
706
- @drawable_on_mouse_move.deregister
707
- @drawable_on_mouse_up.deregister
791
+ deregister_drag_listeners
708
792
  end
709
793
  end
710
794
 
@@ -712,44 +796,55 @@ module Glimmer
712
796
  @drag_and_move
713
797
  end
714
798
 
799
+ # Makes shape a drag source (enables dragging for drag and drop)
800
+ # drag_source and drag_and_move are mutually exclusive
801
+ # if shape had drag_and_move true, it is disabled by deregistering its listeners
715
802
  def drag_source=(drag_source_value)
803
+ deregister_drag_listeners if @drag_and_move
716
804
  drag_source_old_value = @drag_source
717
805
  @drag_source = drag_source_value
718
806
  if @drag_source && !drag_source_old_value
719
- @on_drag_detected = handle_observation_request('on_drag_detected') do |event|
807
+ @on_drag_detected ||= handle_observation_request('on_drag_detected') do |event|
720
808
  Shape.dragging = true
721
809
  Shape.dragging_x = event.x
722
810
  Shape.dragging_y = event.y
811
+ Shape.drop_shape_handling_count = 0
723
812
  Shape.dragged_shape = self
724
813
  Shape.dragged_shape_original_x = x
725
814
  Shape.dragged_shape_original_y = y
726
815
  end
727
- @drawable_on_mouse_move = drawable.handle_observation_request('on_mouse_move') do |event|
728
- if Shape.dragging && Shape.dragged_shape == self
816
+ @drawable_on_mouse_move ||= drawable.handle_observation_request('on_mouse_move') do |event|
817
+ if Shape.dragging && Shape.dragged_shape.equal?(self)
729
818
  Shape.dragged_shape.move_by((event.x - Shape.dragging_x), (event.y - Shape.dragging_y))
730
819
  Shape.dragging_x = event.x
731
820
  Shape.dragging_y = event.y
732
821
  end
733
822
  end
734
- @drawable_on_mouse_up = drawable.handle_observation_request('on_mouse_up') do |event|
735
- if Shape.dragging && Shape.dragged_shape == self && !Shape.drop_shapes.detect {|shape| shape.include_with_children?(event.x, event.y, except_child: Shape.dragged_shape)}
736
- Shape.dragging = false
737
- Shape.dragged_shape.x = Shape.dragged_shape_original_x
738
- Shape.dragged_shape.y = Shape.dragged_shape_original_y
739
- Shape.dragged_shape = nil
740
- end
823
+ @drawable_on_mouse_up ||= drawable.handle_observation_request('on_mouse_up') do |event|
824
+ cancel_dragging! if Shape.dragging && Shape.dragged_shape.equal?(self) && !any_potential_drop_targets?(event.x, event.y)
741
825
  end
742
826
  elsif !@drag_source && drag_source_old_value
743
- @on_drag_detected.deregister
744
- @drawable_on_mouse_move.deregister
745
- @drawable_on_mouse_up.deregister
827
+ deregister_drag_listeners
746
828
  end
747
829
  end
748
-
830
+
749
831
  def drag_source
750
832
  @drag_source
751
833
  end
752
834
 
835
+ def any_potential_drop_targets?(x, y)
836
+ drawable.drop_shapes.any? { |shape| shape.include_with_children?(x, y, except_shape: Shape.dragged_shape) }
837
+ end
838
+
839
+ def cancel_dragging!
840
+ Shape.dragging = false
841
+ if Shape.dragged_shape
842
+ Shape.dragged_shape.x = Shape.dragged_shape_original_x
843
+ Shape.dragged_shape.y = Shape.dragged_shape_original_y
844
+ Shape.dragged_shape = nil
845
+ end
846
+ end
847
+
753
848
  def pattern(*args, type: nil)
754
849
  instance_variable_name = "@#{type}_pattern"
755
850
  the_pattern = instance_variable_get(instance_variable_name)
@@ -772,7 +867,11 @@ module Glimmer
772
867
  end
773
868
 
774
869
  def dispose(dispose_images: true, dispose_patterns: true, redraw: true)
775
- shapes.each { |shape| shape.is_a?(Shape::Path) && shape.dispose } # TODO look into why I'm only disposing paths
870
+ return if drawable.respond_to?(:shell_proxy) && drawable&.shell_proxy&.last_shell_closing?
871
+ return if @disposed
872
+ @disposed = true
873
+ deregister_drag_listeners
874
+ @widget_listener_proxies&.each(&:deregister)
776
875
  if dispose_patterns
777
876
  @background_pattern&.dispose
778
877
  @background_pattern = nil
@@ -783,7 +882,10 @@ module Glimmer
783
882
  @image&.dispose
784
883
  @image = nil
785
884
  end
885
+ shapes.dup.each { |shape| shape.dispose(dispose_images: dispose_images, dispose_patterns: dispose_patterns, redraw: false) }
786
886
  @parent.shapes.delete(self)
887
+ drawable.drop_shapes.delete(self)
888
+ @on_shape_disposed_handlers&.each {|handler| handler.call(self)} # TODO pass a custom event argument to handler
787
889
  drawable.redraw if redraw && !drawable.is_a?(ImageProxy)
788
890
  end
789
891
 
@@ -901,7 +1003,9 @@ module Glimmer
901
1003
  @calculated_args ||= calculate_args!
902
1004
  unless container?
903
1005
  # 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
904
- paint_event.gc.send(@method_name, *@calculated_args) unless (parent.is_a?(Shape) && !parent.calculated_args?)
1006
+ passed_args = @calculated_args.dup
1007
+ passed_args[0] = passed_args[0].to_java(:int) if @method_name == 'drawPolyline' # a weird fix needed for Linux JRuby 9.3.1.0 only (seems to lack a feature from Mac JRuby that automatically converts to appropriate java array type)
1008
+ paint_event.gc.send(@method_name, *passed_args) unless (parent.is_a?(Shape) && !parent.calculated_args?)
905
1009
  @original_gc_properties.each do |method_name, value|
906
1010
  paint_event.gc.send(method_name, value)
907
1011
  end
@@ -924,7 +1028,7 @@ module Glimmer
924
1028
  old_extent = @extent
925
1029
  if ['text', 'string'].include?(@name)
926
1030
  extent_args = [string]
927
- extent_flags = SWTProxy[:draw_transparent] if current_parameter_name?(:is_transparent) && is_transparent
1031
+ extent_flags = SWTProxy[:draw_transparent, :draw_delimiter] if current_parameter_name?(:is_transparent) && is_transparent
928
1032
  extent_flags = flags if current_parameter_name?(:flags)
929
1033
  extent_args << extent_flags unless extent_flags.nil?
930
1034
  self.extent = paint_event.gc.send("#{@name}Extent", *extent_args)
@@ -935,10 +1039,10 @@ module Glimmer
935
1039
  end
936
1040
  end
937
1041
 
938
- def expanded_shapes
1042
+ def expanded_shapes(except_shape: nil)
939
1043
  if shapes.to_a.any?
940
1044
  shapes.map do |shape|
941
- [shape] + shape.expanded_shapes
1045
+ shape.equal?(except_shape) ? [] : ([shape] + shape.expanded_shapes(except_shape: except_shape))
942
1046
  end.flatten
943
1047
  else
944
1048
  []
@@ -946,7 +1050,6 @@ module Glimmer
946
1050
  end
947
1051
 
948
1052
  def calculated_args_changed!(children: true)
949
- # TODO add a children: true option to enable setting to false to avoid recalculating children args
950
1053
  @calculated_args = nil
951
1054
  shapes.each(&:calculated_args_changed!) if children
952
1055
  end
@@ -980,7 +1083,6 @@ module Glimmer
980
1083
 
981
1084
  # args translated to absolute coordinates
982
1085
  def calculate_args!
983
- # TODO add conditions for parent having default width/height too
984
1086
  return @args if parent.is_a?(Drawable) && !default_x? && !default_y? && !default_width? && !default_height? && !max_width? && !max_height?
985
1087
  calculated_args_dependencies = [
986
1088
  x,
@@ -68,6 +68,11 @@ module Glimmer
68
68
  instance # ensure instance
69
69
  @thread
70
70
  end
71
+
72
+ # Current custom widgets, shells, and shapes being rendered. Useful to yoke all observers evaluated during rendering of their custom widgets/shells/shapes for automatical disposal on_widget_disposed/on_shape_disposed
73
+ def current_custom_widgets_and_shapes
74
+ @current_custom_widgets_and_shapes ||= []
75
+ end
71
76
  end
72
77
 
73
78
  # SWT Display object wrapped
@@ -160,21 +165,21 @@ module Glimmer
160
165
  @swt_display.isDisposed
161
166
  end
162
167
 
163
- def method_missing(method, *args, &block)
164
- if can_handle_observation_request?(method)
165
- handle_observation_request(method, &block)
168
+ def method_missing(method_name, *args, &block)
169
+ if block && can_handle_observation_request?(method_name)
170
+ handle_observation_request(method_name, &block)
166
171
  else
167
- swt_display.send(method, *args, &block)
172
+ swt_display.send(method_name, *args, &block)
168
173
  end
169
174
  rescue => e
170
- Glimmer::Config.logger.debug {"Neither DisplayProxy nor #{swt_display.class.name} can handle the method ##{method}"}
175
+ Glimmer::Config.logger.debug {"Neither DisplayProxy nor #{swt_display.class.name} can handle the method ##{method_name}"}
171
176
  super
172
177
  end
173
178
 
174
- def respond_to?(method, *args, &block)
179
+ def respond_to?(method_name, *args, &block)
175
180
  super ||
176
- can_handle_observation_request?(method) ||
177
- swt_display.respond_to?(method, *args, &block)
181
+ can_handle_observation_request?(method_name) ||
182
+ swt_display.respond_to?(method_name, *args, &block)
178
183
  end
179
184
 
180
185
  def can_handle_observation_request?(observation_request)
@@ -195,7 +200,7 @@ module Glimmer
195
200
  if observation_request.start_with?('on_swt_')
196
201
  constant_name = observation_request.sub(/^on_swt_/, '')
197
202
  swt_event_reg = add_swt_event_filter(constant_name, &block)
198
- Glimmer::UI::CustomWidget.current_custom_widgets.last&.observer_registrations&.push(swt_event_reg)
203
+ DisplayProxy.current_custom_widgets_and_shapes.last&.observer_registrations&.push(swt_event_reg)
199
204
  swt_event_reg
200
205
  elsif observation_request.start_with?('on_')
201
206
  event_name = observation_request.sub(/^on_/, '')
@@ -205,7 +210,7 @@ module Glimmer
205
210
  menu_item = system_menu.getItems.find {|menu_item| menu_item.getID == SWTProxy["ID_#{event_name.upcase}"]}
206
211
  listener = ConcreteListener.new(&block)
207
212
  display_mac_event_registration = menu_item.addListener(SWTProxy[:Selection], listener)
208
- Glimmer::UI::CustomWidget.current_custom_widgets.last&.observer_registrations&.push(display_mac_event_registration)
213
+ DisplayProxy.current_custom_widgets_and_shapes.last&.observer_registrations&.push(display_mac_event_registration)
209
214
  display_mac_event_registration
210
215
  end
211
216
  end
@@ -197,15 +197,15 @@ module Glimmer
197
197
  end
198
198
  end
199
199
 
200
- def method_missing(method, *args, &block)
201
- swt_image.send(method, *args, &block)
200
+ def method_missing(method_name, *args, &block)
201
+ swt_image.send(method_name, *args, &block)
202
202
  rescue => e
203
- Glimmer::Config.logger.debug {"Neither ImageProxy nor #{swt_image.class.name} can handle the method ##{method}"}
203
+ Glimmer::Config.logger.debug {"Neither ImageProxy nor #{swt_image.class.name} can handle the method ##{method_name}"}
204
204
  super
205
205
  end
206
206
 
207
- def respond_to?(method, *args, &block)
208
- super || swt_image.respond_to?(method, *args, &block)
207
+ def respond_to?(method_name, *args, &block)
208
+ super || swt_image.respond_to?(method_name, *args, &block)
209
209
  end
210
210
  end
211
211
  end
@@ -80,23 +80,23 @@ module Glimmer
80
80
  end
81
81
  end
82
82
 
83
- def method_missing(method, *args, &block)
83
+ def method_missing(method_name, *args, &block)
84
84
  DisplayProxy.instance.auto_exec do
85
- swt_widget.send(method, *args, &block)
85
+ swt_widget.send(method_name, *args, &block)
86
86
  end
87
87
  rescue => e
88
88
  begin
89
89
  super
90
90
  rescue Exception => inner_error
91
- Glimmer::Config.logger.error {"Neither MessageBoxProxy nor #{swt_widget.class.name} can handle the method ##{method}"}
91
+ Glimmer::Config.logger.error {"Neither MessageBoxProxy nor #{swt_widget.class.name} can handle the method ##{method_name}"}
92
92
  Glimmer::Config.logger.error {e.full_message}
93
93
  raise inner_error
94
94
  end
95
95
  end
96
96
 
97
- def respond_to?(method, *args, &block)
97
+ def respond_to?(method_name, *args, &block)
98
98
  super ||
99
- swt_widget.respond_to?(method, *args, &block)
99
+ swt_widget.respond_to?(method_name, *args, &block)
100
100
  end
101
101
  end
102
102
  end
@@ -0,0 +1,55 @@
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
+ module Glimmer
23
+ module SWT
24
+ # Proxy for widget listeners
25
+ #
26
+ # Follows the Proxy Design Pattern
27
+ class ShapeListenerProxy
28
+
29
+ attr_reader :shape, :observation_request, :widget_listener_proxy
30
+
31
+ def initialize(shape: nil, drawable: nil, shape_listener_block: nil, observation_request: nil, widget_listener_proxy: nil)
32
+ @shape = shape
33
+ @drawable = drawable
34
+ @shape_listener_block = shape_listener_block
35
+ @observation_request = observation_request
36
+ @widget_listener_proxy = widget_listener_proxy
37
+ end
38
+
39
+ # Deregisters shape listener
40
+ def deregister
41
+ if @observation_request == 'on_drop'
42
+ @widget_listener_proxy.deregister
43
+ @shape.widget_listener_proxies.delete(@widget_listener_proxy)
44
+ @drawable.drop_shapes.delete(shape)
45
+ elsif @observation_request == 'on_shape_disposed'
46
+ @shape.remove_shape_disposed_listener(@shape_listener_block)
47
+ else
48
+ @widget_listener_proxy.deregister
49
+ @shape.widget_listener_proxies.delete(@widget_listener_proxy)
50
+ end
51
+ end
52
+ alias unregister deregister # TODO consider dropping unregister (and in Observer too)
53
+ end
54
+ end
55
+ end
@@ -105,6 +105,7 @@ module Glimmer
105
105
  @swt_widget.setLocation(location_x, location_y)
106
106
  end
107
107
  end
108
+ alias center_in_display center_within_display
108
109
 
109
110
  # Opens shell and starts SWT's UI thread event loop
110
111
  def open
@@ -111,14 +111,14 @@ module Glimmer
111
111
  begin
112
112
  super
113
113
  rescue Exception => inner_e
114
- Glimmer::Config.logger.error {"Neither TransformProxy nor #{@swt_transform.class.name} can handle the method ##{method}"}
114
+ Glimmer::Config.logger.error {"Neither TransformProxy nor #{@swt_transform.class.name} can handle the method ##{method_name}"}
115
115
  Glimmer::Config.logger.error {e.full_message}
116
116
  end
117
117
  end
118
118
 
119
- def respond_to?(method, *args, &block)
119
+ def respond_to?(method_name, *args, &block)
120
120
  super ||
121
- @swt_transform.respond_to?(method, *args, &block)
121
+ @swt_transform.respond_to?(method_name, *args, &block)
122
122
  end
123
123
  end
124
124
  end
@@ -41,12 +41,12 @@ module Glimmer
41
41
  @swt_widget = display_proxy.getSystemTray
42
42
  end
43
43
 
44
- def method_missing(method, *args, &block)
45
- @swt_widget.send(method, *args, &block)
44
+ def method_missing(method_name, *args, &block)
45
+ @swt_widget.send(method_name, *args, &block)
46
46
  end
47
47
 
48
- def respond_to?(method, *args, &block)
49
- super || @swt_widget.respond_to?(method, *args, &block)
48
+ def respond_to?(method_name, *args, &block)
49
+ super || @swt_widget.respond_to?(method_name, *args, &block)
50
50
  end
51
51
 
52
52
  def post_initialize_child(child)