glimmer-dsl-swt 4.18.4.9 → 4.18.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +73 -0
  3. data/README.md +14 -5
  4. data/VERSION +1 -1
  5. data/bin/glimmer +3 -3
  6. data/docs/reference/GLIMMER_CONFIGURATION.md +7 -3
  7. data/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md +464 -149
  8. data/docs/reference/GLIMMER_SAMPLES.md +91 -4
  9. data/glimmer-dsl-swt.gemspec +24 -13
  10. data/lib/ext/glimmer/config.rb +3 -7
  11. data/lib/glimmer/data_binding/list_selection_binding.rb +13 -7
  12. data/lib/glimmer/data_binding/table_items_binding.rb +22 -17
  13. data/lib/glimmer/data_binding/tree_items_binding.rb +19 -15
  14. data/lib/glimmer/data_binding/widget_binding.rb +13 -15
  15. data/lib/glimmer/dsl/swt/{file_dialog_expression.rb → auto_exec_expression.rb} +6 -18
  16. data/lib/glimmer/dsl/swt/checkbox_group_selection_data_binding_expression.rb +9 -6
  17. data/lib/glimmer/dsl/swt/color_expression.rb +1 -1
  18. data/lib/glimmer/dsl/swt/combo_selection_data_binding_expression.rb +16 -14
  19. data/lib/glimmer/dsl/swt/custom_widget_expression.rb +4 -1
  20. data/lib/glimmer/dsl/swt/data_binding_expression.rb +2 -2
  21. data/lib/glimmer/dsl/swt/dialog_expression.rb +18 -9
  22. data/lib/glimmer/dsl/swt/dsl.rb +1 -0
  23. data/lib/glimmer/dsl/swt/exec_expression.rb +1 -1
  24. data/lib/glimmer/dsl/swt/font_expression.rb +1 -1
  25. data/lib/glimmer/dsl/swt/image_expression.rb +16 -2
  26. data/lib/glimmer/dsl/swt/list_selection_data_binding_expression.rb +11 -8
  27. data/lib/glimmer/dsl/swt/pixel_expression.rb +1 -1
  28. data/lib/glimmer/dsl/swt/radio_group_selection_data_binding_expression.rb +8 -5
  29. data/lib/glimmer/dsl/swt/shape_expression.rb +2 -2
  30. data/lib/glimmer/dsl/swt/shell_expression.rb +5 -2
  31. data/lib/glimmer/dsl/swt/widget_expression.rb +8 -4
  32. data/lib/glimmer/launcher.rb +3 -0
  33. data/lib/glimmer/rake_task/scaffold.rb +3 -0
  34. data/lib/glimmer/swt/color_proxy.rb +1 -1
  35. data/lib/glimmer/swt/custom/code_text.rb +33 -11
  36. data/lib/glimmer/swt/custom/drawable.rb +55 -0
  37. data/lib/glimmer/swt/custom/shape.rb +187 -43
  38. data/lib/glimmer/swt/custom/shape/arc.rb +60 -0
  39. data/lib/glimmer/{dsl/swt/directory_dialog_expression.rb → swt/custom/shape/focus.rb} +15 -20
  40. data/lib/glimmer/swt/custom/shape/image.rb +99 -0
  41. data/lib/glimmer/swt/custom/shape/line.rb +65 -0
  42. data/lib/glimmer/swt/custom/shape/oval.rb +61 -0
  43. data/lib/glimmer/swt/custom/shape/point.rb +54 -0
  44. data/lib/glimmer/swt/custom/shape/polygon.rb +73 -0
  45. data/lib/glimmer/swt/custom/shape/polyline.rb +74 -0
  46. data/lib/glimmer/swt/custom/shape/rectangle.rb +101 -0
  47. data/lib/glimmer/swt/custom/shape/text.rb +85 -0
  48. data/lib/glimmer/swt/date_time_proxy.rb +9 -3
  49. data/lib/glimmer/swt/dialog_proxy.rb +92 -0
  50. data/lib/glimmer/swt/display_proxy.rb +62 -2
  51. data/lib/glimmer/swt/expand_item_proxy.rb +18 -12
  52. data/lib/glimmer/swt/font_proxy.rb +13 -7
  53. data/lib/glimmer/swt/image_proxy.rb +15 -4
  54. data/lib/glimmer/swt/layout_data_proxy.rb +21 -15
  55. data/lib/glimmer/swt/layout_proxy.rb +19 -15
  56. data/lib/glimmer/swt/menu_proxy.rb +2 -2
  57. data/lib/glimmer/swt/message_box_proxy.rb +21 -7
  58. data/lib/glimmer/swt/properties.rb +3 -0
  59. data/lib/glimmer/swt/proxy_properties.rb +145 -0
  60. data/lib/glimmer/swt/scrolled_composite_proxy.rb +6 -2
  61. data/lib/glimmer/swt/shell_proxy.rb +96 -80
  62. data/lib/glimmer/swt/swt_proxy.rb +17 -0
  63. data/lib/glimmer/swt/tab_item_proxy.rb +5 -3
  64. data/lib/glimmer/swt/table_proxy.rb +32 -11
  65. data/lib/glimmer/swt/transform_proxy.rb +39 -35
  66. data/lib/glimmer/swt/tree_proxy.rb +11 -16
  67. data/lib/glimmer/swt/widget_listener_proxy.rb +6 -2
  68. data/lib/glimmer/swt/widget_proxy.rb +192 -141
  69. data/lib/glimmer/ui.rb +5 -0
  70. data/lib/glimmer/ui/custom_shell.rb +13 -7
  71. data/lib/glimmer/ui/custom_widget.rb +4 -5
  72. data/samples/elaborate/contact_manager.rb +7 -7
  73. data/samples/elaborate/login.rb +25 -21
  74. data/samples/elaborate/mandelbrot_fractal.rb +87 -31
  75. data/samples/elaborate/meta_sample.rb +1 -1
  76. data/samples/elaborate/tetris.rb +1 -0
  77. data/samples/elaborate/tic_tac_toe.rb +16 -14
  78. data/samples/elaborate/tic_tac_toe/board.rb +5 -5
  79. data/samples/elaborate/tic_tac_toe/cell.rb +5 -5
  80. data/samples/hello/hello_button.rb +7 -7
  81. data/samples/hello/hello_canvas.rb +143 -41
  82. data/samples/hello/hello_checkbox.rb +16 -14
  83. data/samples/hello/hello_checkbox_group.rb +11 -9
  84. data/samples/hello/hello_color_dialog.rb +66 -0
  85. data/samples/hello/hello_combo.rb +14 -12
  86. data/samples/hello/hello_computed.rb +7 -7
  87. data/samples/hello/hello_cursor.rb +2 -1
  88. data/samples/hello/hello_custom_shell.rb +17 -21
  89. data/samples/hello/hello_custom_widget.rb +4 -6
  90. data/samples/hello/hello_date_time.rb +14 -12
  91. data/samples/hello/hello_directory_dialog.rb +7 -7
  92. data/samples/hello/hello_expand_bar.rb +8 -8
  93. data/samples/hello/hello_file_dialog.rb +7 -7
  94. data/samples/hello/hello_font_dialog.rb +82 -0
  95. data/samples/hello/hello_group.rb +18 -16
  96. data/samples/hello/hello_list_multi_selection.rb +13 -11
  97. data/samples/hello/hello_list_single_selection.rb +13 -11
  98. data/samples/hello/hello_progress_bar.rb +125 -0
  99. data/samples/hello/hello_radio.rb +18 -16
  100. data/samples/hello/hello_radio_group.rb +14 -12
  101. data/samples/hello/hello_spinner.rb +7 -7
  102. data/samples/hello/hello_tab.rb +5 -5
  103. data/samples/hello/hello_table.rb +10 -5
  104. data/samples/hello/hello_tree.rb +485 -0
  105. metadata +22 -22
  106. data/lib/glimmer/swt/directory_dialog_proxy.rb +0 -65
  107. data/lib/glimmer/swt/file_dialog_proxy.rb +0 -66
@@ -0,0 +1,74 @@
1
+ # Copyright (c) 2007-2021 Andy Maleh
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ require 'glimmer/swt/custom/shape'
23
+ require 'glimmer/swt/swt_proxy'
24
+ require 'glimmer/swt/display_proxy'
25
+ require 'glimmer/swt/color_proxy'
26
+ require 'glimmer/swt/font_proxy'
27
+ require 'glimmer/swt/transform_proxy'
28
+
29
+ module Glimmer
30
+ module SWT
31
+ module Custom
32
+ # Represents a shape (graphics) to be drawn on a control/widget/canvas/display
33
+ # That is because Shape is drawn on a parent as graphics and doesn't have an SWT widget for itself
34
+ class Shape
35
+ class Polyline < Shape
36
+ def parameter_names
37
+ [:point_array]
38
+ end
39
+
40
+ def point_count
41
+ point_array.count / 2
42
+ end
43
+
44
+ def x_array
45
+ point_array.each_with_index.select {|pair| pair.last.even?}.map(&:first)
46
+ end
47
+
48
+ def y_array
49
+ point_array.each_with_index.select {|pair| pair.last.odd?}.map(&:first)
50
+ end
51
+
52
+ def point_xy_array
53
+ x_array.zip(y_array)
54
+ end
55
+
56
+ def [](index)
57
+ index = 0 if index == point_count
58
+ org.eclipse.swt.graphics.Point.new(point_array[index * 2], point_array[index * 2 + 1])
59
+ end
60
+
61
+ def include?(x, y)
62
+ comparison_lines = point_xy_array.zip(point_xy_array.rotate(1))
63
+ comparison_lines.pop # ignore last pair since you don't want to compare last point with first point
64
+ comparison_lines.any? {|line| Line.include?(line.first.first, line.first.last, line.last.first, line.last.last, x, y)}
65
+ end
66
+
67
+ def move_by(x_delta, y_delta)
68
+ self.point_array = point_array.each_with_index.map {|coordinate, i| i.even? ? coordinate + x_delta : coordinate + y_delta}
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,101 @@
1
+ # Copyright (c) 2007-2021 Andy Maleh
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ require 'glimmer/swt/custom/shape'
23
+ require 'glimmer/swt/swt_proxy'
24
+ require 'glimmer/swt/display_proxy'
25
+ require 'glimmer/swt/color_proxy'
26
+ require 'glimmer/swt/font_proxy'
27
+ require 'glimmer/swt/transform_proxy'
28
+
29
+ module Glimmer
30
+ module SWT
31
+ module Custom
32
+ # Represents a shape (graphics) to be drawn on a control/widget/canvas/display
33
+ # That is because Shape is drawn on a parent as graphics and doesn't have an SWT widget for itself
34
+ class Shape
35
+ class Rectangle < Shape
36
+ def parameter_names
37
+ if @args.to_a.size >= 6
38
+ rectangle_round_parameter_names
39
+ elsif @args.to_a.size == 5
40
+ rectangle_gradient_parameter_names
41
+ elsif @args.to_a.size == 1
42
+ rectangle_rectangle_parameter_names
43
+ else
44
+ rectangle_parameter_names
45
+ end
46
+ end
47
+
48
+ def possible_parameter_names
49
+ # TODO refactor and improve this method through meta-programming (and share across other shapes)
50
+ (rectangle_round_parameter_names + rectangle_gradient_parameter_names + rectangle_parameter_names + rectangle_rectangle_parameter_names).uniq
51
+ end
52
+
53
+ def rectangle_round_parameter_names
54
+ [:x, :y, :width, :height, :arc_width, :arc_height]
55
+ end
56
+
57
+ def rectangle_gradient_parameter_names
58
+ [:x, :y, :width, :height, :vertical]
59
+ end
60
+
61
+ def rectangle_parameter_names
62
+ [:x, :y, :width, :height]
63
+ end
64
+
65
+ def rectangle_rectangle_parameter_names
66
+ # this receives a Rectangle object
67
+ [:rectangle]
68
+ end
69
+
70
+ def parameter_index(attribute_name)
71
+ ####TODO refactor and improve this method through meta-programming (and share across other shapes)
72
+ if rectangle_round_parameter_names.map(&:to_s).include?(attribute_name.to_s)
73
+ rectangle_round_parameter_names.map(&:to_s).index(attribute_name.to_s)
74
+ elsif rectangle_gradient_parameter_names.map(&:to_s).include?(attribute_name.to_s)
75
+ rectangle_gradient_parameter_names.map(&:to_s).index(attribute_name.to_s)
76
+ elsif rectangle_parameter_names.map(&:to_s).include?(attribute_name.to_s)
77
+ rectangle_parameter_names.map(&:to_s).index(attribute_name.to_s)
78
+ elsif rectangle_rectangle_parameter_names.map(&:to_s).include?(attribute_name.to_s)
79
+ rectangle_rectangle_parameter_names.map(&:to_s).index(attribute_name.to_s)
80
+ end
81
+ end
82
+
83
+ def point_xy_array
84
+ [[x, y], [x + width, y], [x + width, y + height], [x, y + height]]
85
+ end
86
+
87
+ # checks if drawn or filled rectangle includes the point denoted by x and y (if drawn, it only returns true if point lies on the edge)
88
+ def include?(x, y)
89
+ if filled?
90
+ contain?(x, y)
91
+ else
92
+ comparison_lines = point_xy_array.zip(point_xy_array.rotate(1))
93
+ comparison_lines.any? {|line| Line.include?(line.first.first, line.first.last, line.last.first, line.last.last, x, y)}
94
+ end
95
+ end
96
+
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,85 @@
1
+ # Copyright (c) 2007-2021 Andy Maleh
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ require 'glimmer/swt/custom/shape'
23
+ require 'glimmer/swt/swt_proxy'
24
+ require 'glimmer/swt/display_proxy'
25
+ require 'glimmer/swt/color_proxy'
26
+ require 'glimmer/swt/font_proxy'
27
+ require 'glimmer/swt/transform_proxy'
28
+
29
+ module Glimmer
30
+ module SWT
31
+ module Custom
32
+ # Represents a shape (graphics) to be drawn on a control/widget/canvas/display
33
+ # That is because Shape is drawn on a parent as graphics and doesn't have an SWT widget for itself
34
+ class Shape
35
+ class Text < Shape
36
+ attr_accessor :extent
37
+
38
+ def parameter_names
39
+ @parameter_names || text_parameter_names
40
+ end
41
+
42
+ def possible_parameter_names
43
+ # TODO refactor and improve this method through meta-programming (and share across other shapes)
44
+ (text_parameter_names + text_transparent_parameter_names + text_flags_parameter_names).uniq
45
+ end
46
+
47
+ def text_parameter_names
48
+ [:string, :x, :y]
49
+ end
50
+
51
+ def text_transparent_parameter_names
52
+ [:string, :x, :y, :is_transparent]
53
+ end
54
+
55
+ def text_flags_parameter_names
56
+ [:string, :x, :y, :flags]
57
+ end
58
+
59
+ def set_parameter_attribute(attribute_name, *args)
60
+ return super if @parameter_names.to_a.map(&:to_s).include?(attribute_name.to_s)
61
+ if text_parameter_names.map(&:to_s).include?(attribute_name.to_s)
62
+ @parameter_names = text_parameter_names
63
+ elsif text_transparent_parameter_names.map(&:to_s).include?(attribute_name.to_s)
64
+ @parameter_names = text_transparent_parameter_names
65
+ elsif text_flags_parameter_names.map(&:to_s).include?(attribute_name.to_s)
66
+ @parameter_names = text_flags_parameter_names
67
+ end
68
+ super
69
+ end
70
+
71
+ def width
72
+ extent&.x
73
+ end
74
+
75
+ def height
76
+ extent&.y
77
+ end
78
+
79
+ end
80
+
81
+ String = Text
82
+ end
83
+ end
84
+ end
85
+ end
@@ -43,7 +43,9 @@ module Glimmer
43
43
  end
44
44
 
45
45
  def date=(date_value)
46
- swt_widget.setDate(date_value.year, date_value.month - 1, date_value.day)
46
+ auto_exec do
47
+ swt_widget.setDate(date_value.year, date_value.month - 1, date_value.day)
48
+ end
47
49
  end
48
50
 
49
51
  def time
@@ -58,11 +60,15 @@ module Glimmer
58
60
  end
59
61
 
60
62
  def month
61
- swt_widget.month + 1
63
+ auto_exec do
64
+ swt_widget.month + 1
65
+ end
62
66
  end
63
67
 
64
68
  def month=(new_value)
65
- swt_widget.month = new_value - 1
69
+ auto_exec do
70
+ swt_widget.month = new_value - 1
71
+ end
66
72
  end
67
73
 
68
74
  def set_attribute(attribute_name, *args)
@@ -0,0 +1,92 @@
1
+ # Copyright (c) 2007-2021 Andy Maleh
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ require 'glimmer/swt/swt_proxy'
23
+ require 'glimmer/swt/widget_proxy'
24
+ require 'glimmer/swt/display_proxy'
25
+ require 'glimmer/swt/proxy_properties'
26
+
27
+ module Glimmer
28
+ module SWT
29
+ # Proxy for org.eclipse.swt.widgets.Dialog superclass
30
+ # of dialogs like FileDialog, DirectoryDialog, ColorDialog, and FontDialog
31
+ #
32
+ # (if you're seeking the `dialog` keyword, that's just a `shell` variation
33
+ # under ShellProxy instead.
34
+ #
35
+ # Automatically uses the current shell if one is open.
36
+ # Otherwise, it instantiates a new shell parent
37
+ #
38
+ # Optionally takes a shell as an argument
39
+ #
40
+ # Follows the Proxy Design Pattern
41
+ class DialogProxy
42
+ # TODO write rspec tests
43
+ include ProxyProperties
44
+
45
+ include_package 'org.eclipse.swt.widgets'
46
+ include_package 'org.eclipse.swt.printing'
47
+
48
+ class << self
49
+ include_package 'org.eclipse.swt.widgets'
50
+ include_package 'org.eclipse.swt.printing'
51
+
52
+ def dialog_class(keyword)
53
+ the_class = eval(keyword.camelcase(:upper))
54
+ the_class if the_class.ancestors.include?(org.eclipse.swt.widgets.Dialog)
55
+ end
56
+ end
57
+
58
+ attr_reader :swt_dialog
59
+
60
+ def initialize(keyword, *args, swt_dialog: nil)
61
+ DisplayProxy.instance.auto_exec do
62
+ dialog_class = self.class.dialog_class(keyword)
63
+ if swt_dialog
64
+ @swt_dialog = swt_dialog
65
+ else
66
+ style_args = args.select {|arg| arg.is_a?(Symbol) || arg.is_a?(String)}
67
+ if style_args.any?
68
+ style_arg_start_index = args.index(style_args.first)
69
+ style_arg_last_index = args.index(style_args.last)
70
+ args[style_arg_start_index..style_arg_last_index] = SWTProxy[style_args]
71
+ end
72
+ if args.first.respond_to?(:swt_widget) && args.first.swt_widget.is_a?(Shell)
73
+ args[0] = args[0].swt_widget
74
+ end
75
+ if !args.first.is_a?(Shell)
76
+ current_shell = DisplayProxy.instance.swt_display.shells.first
77
+ args.unshift(current_shell.nil? ? ShellProxy.new : current_shell)
78
+ end
79
+ parent = args[0]
80
+ @parent_proxy = parent.is_a?(Shell) ? ShellProxy.new(swt_widget: parent) : parent
81
+ @swt_dialog = dialog_class.new(*args)
82
+ end
83
+ end
84
+ end
85
+
86
+ def proxy_source_object
87
+ @swt_dialog
88
+ end
89
+
90
+ end
91
+ end
92
+ end
@@ -58,10 +58,16 @@ module Glimmer
58
58
  # Returns singleton instance
59
59
  def instance(*args)
60
60
  if @instance.nil? || @instance.swt_display.nil? || @instance.swt_display.isDisposed
61
+ @thread = Thread.current
61
62
  @instance = new(*args)
62
63
  end
63
64
  @instance
64
65
  end
66
+
67
+ def thread
68
+ instance # ensure instance
69
+ @thread
70
+ end
65
71
  end
66
72
 
67
73
  # SWT Display object wrapped
@@ -71,6 +77,7 @@ module Glimmer
71
77
  Display.app_name ||= 'Glimmer'
72
78
  @swt_display = Display.new(*args)
73
79
  @swt_display.set_data('proxy', self)
80
+ @execs_in_progress = {}
74
81
  on_swt_Dispose {
75
82
  clear_shapes
76
83
  }
@@ -80,18 +87,71 @@ module Glimmer
80
87
  Glimmer::DSL::Engine.add_content(self, Glimmer::DSL::SWT::DisplayExpression.new, &block)
81
88
  end
82
89
 
90
+ # asynchronously executes the block (required from threads other than first GUI thread)
91
+ # does not return the value produced by the block since it is async, running after the return
83
92
  def async_exec(&block)
84
- @swt_display.asyncExec(&block)
93
+ @swt_display.asyncExec do
94
+ execs_in_progress << :async_exec
95
+ begin
96
+ result = block.call
97
+ ensure
98
+ execs_in_progress.pop
99
+ end
100
+ end
85
101
  end
86
102
 
103
+ # synchronously executes the block (required from threads other than first GUI thread)
104
+ # returns the value produced by the block
87
105
  def sync_exec(&block)
88
- @swt_display.syncExec(&block)
106
+ result = nil
107
+ @swt_display.syncExec do
108
+ execs_in_progress << :sync_exec
109
+ begin
110
+ result = block.call
111
+ ensure
112
+ execs_in_progress.pop
113
+ end
114
+ end
115
+ result
89
116
  end
90
117
 
91
118
  def timer_exec(delay_in_millis, &block)
92
119
  @swt_display.timerExec(delay_in_millis, &block)
93
120
  end
94
121
 
122
+ # Indicates whether `sync_exec` is required because of running in a different thread from the GUI thread
123
+ # `async_exec` could be used as an alternative to `sync_exec` when required.
124
+ def sync_exec_required?
125
+ Thread.current != DisplayProxy.thread
126
+ end
127
+
128
+ def async_exec_in_progress?
129
+ execs_in_progress.last == :async_exec
130
+ end
131
+
132
+ def sync_exec_in_progress?
133
+ execs_in_progress.include?(:sync_exec)
134
+ end
135
+
136
+ def execs_in_progress
137
+ @execs_in_progress[Thread.current] ||= []
138
+ end
139
+
140
+ # Invoke block with `sync_exec` only when necessary (running from a separate thread)
141
+ # Override sync_exec as `true` to force using or `false` to force avoiding
142
+ # Override async_exec as `true` to force using or `:unless_in_progress` to force using only if no `async_exec` is in progress
143
+ # Disable auto execution of `sync_exec` via `Glimmer::Config.auto_sync_exec = false`
144
+ # Otherwise, runs normally, thus allowing SWT to decide how to batch/optimize GUI updates
145
+ def auto_exec(override_sync_exec: nil, override_async_exec: nil, &block)
146
+ if override_sync_exec || override_sync_exec.nil? && !override_async_exec && sync_exec_required? && Config.auto_sync_exec? && !sync_exec_in_progress? && !async_exec_in_progress?
147
+ sync_exec(&block)
148
+ elsif override_async_exec || override_async_exec.to_s == 'unless_in_progress' && !async_exec_in_progress?
149
+ async_exec(&block)
150
+ else
151
+ block.call
152
+ end
153
+ end
154
+
95
155
  def on_widget_disposed(&block)
96
156
  on_swt_Dispose(&block)
97
157
  end