glimmer-dsl-swt 4.18.4.6 → 4.18.4.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +43 -0
- data/README.md +20 -11
- data/VERSION +1 -1
- data/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md +273 -66
- data/docs/reference/GLIMMER_SAMPLES.md +144 -41
- data/glimmer-dsl-swt.gemspec +13 -5
- data/lib/glimmer/data_binding/widget_binding.rb +16 -3
- data/lib/glimmer/dsl/swt/color_expression.rb +1 -1
- data/lib/glimmer/dsl/swt/custom_widget_expression.rb +4 -1
- data/lib/glimmer/dsl/swt/data_binding_expression.rb +2 -1
- data/lib/glimmer/dsl/swt/image_expression.rb +14 -3
- data/lib/glimmer/dsl/swt/radio_group_selection_data_binding_expression.rb +1 -0
- data/lib/glimmer/dsl/swt/shell_expression.rb +4 -1
- data/lib/glimmer/dsl/swt/widget_expression.rb +4 -1
- data/lib/glimmer/swt/color_proxy.rb +5 -4
- data/lib/glimmer/swt/custom/animation.rb +1 -0
- data/lib/glimmer/swt/custom/code_text.rb +22 -0
- data/lib/glimmer/swt/custom/drawable.rb +80 -4
- data/lib/glimmer/swt/custom/radio_group.rb +2 -1
- data/lib/glimmer/swt/custom/shape.rb +80 -46
- data/lib/glimmer/swt/image_proxy.rb +30 -8
- data/lib/glimmer/swt/scrolled_composite_proxy.rb +15 -6
- data/lib/glimmer/swt/shell_proxy.rb +2 -0
- data/lib/glimmer/swt/swt_proxy.rb +1 -0
- data/lib/glimmer/swt/tab_item_proxy.rb +1 -0
- data/lib/glimmer/swt/widget_proxy.rb +24 -5
- data/lib/glimmer/ui/custom_shell.rb +3 -3
- data/samples/elaborate/mandelbrot_fractal.rb +348 -39
- data/samples/elaborate/meta_sample.rb +1 -1
- data/samples/elaborate/tetris.rb +5 -5
- data/samples/hello/hello_combo.rb +1 -1
- data/samples/hello/hello_cursor.rb +57 -0
- data/samples/hello/hello_list_multi_selection.rb +1 -1
- data/samples/hello/hello_list_single_selection.rb +1 -1
- data/samples/hello/hello_progress_bar.rb +129 -0
- data/samples/hello/hello_table.rb +1 -1
- data/samples/hello/hello_table/baseball_park.png +0 -0
- metadata +11 -3
data/glimmer-dsl-swt.gemspec
CHANGED
@@ -2,22 +2,28 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: glimmer-dsl-swt 4.18.4.
|
5
|
+
# stub: glimmer-dsl-swt 4.18.4.11 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "glimmer-dsl-swt".freeze
|
9
|
-
s.version = "4.18.4.
|
9
|
+
s.version = "4.18.4.11"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib".freeze]
|
13
13
|
s.authors = ["AndyMaleh".freeze]
|
14
|
-
s.date = "2021-02-
|
14
|
+
s.date = "2021-02-19"
|
15
15
|
s.description = "Glimmer DSL for SWT (JRuby Desktop Development GUI Framework) is a native-GUI cross-platform desktop development library written in JRuby, an OS-threaded faster JVM version of Ruby. Glimmer's main innovation is a declarative Ruby DSL that enables productive and efficient authoring of desktop application user-interfaces by relying on the robust Eclipse SWT library. Glimmer additionally innovates by having built-in data-binding support, which greatly facilitates synchronizing the GUI with domain models, thus achieving true decoupling of object oriented components and enabling developers to solve business problems (test-first) without worrying about GUI concerns, or alternatively drive development GUI-first, and then write clean business models (test-first) afterwards. Not only does Glimmer provide a large set of GUI widgets, but it also supports drawing Canvas Graphics like Shapes and Animations. To get started quickly, Glimmer offers scaffolding options for Apps, Gems, and Custom Widgets. Glimmer also includes native-executable packaging support, sorely lacking in other libraries, thus enabling the delivery of desktop apps written in Ruby as truly native DMG/PKG/APP files on the Mac + App Store, MSI/EXE files on Windows, and Gem Packaged Shell Scripts on Linux.".freeze
|
16
16
|
s.email = "andy.am@gmail.com".freeze
|
17
17
|
s.executables = ["glimmer".freeze, "girb".freeze]
|
18
18
|
s.extra_rdoc_files = [
|
19
|
-
"
|
20
|
-
"
|
19
|
+
"README.md",
|
20
|
+
"docs/reference/GLIMMER_COMMAND.md",
|
21
|
+
"docs/reference/GLIMMER_CONFIGURATION.md",
|
22
|
+
"docs/reference/GLIMMER_GIRB.md",
|
23
|
+
"docs/reference/GLIMMER_GUI_DSL_SYNTAX.md",
|
24
|
+
"docs/reference/GLIMMER_PACKAGING_AND_DISTRIBUTION.md",
|
25
|
+
"docs/reference/GLIMMER_SAMPLES.md",
|
26
|
+
"docs/reference/GLIMMER_STYLE_GUIDE.md"
|
21
27
|
]
|
22
28
|
s.files = [
|
23
29
|
"CHANGELOG.md",
|
@@ -171,6 +177,7 @@ Gem::Specification.new do |s|
|
|
171
177
|
"samples/hello/hello_combo.rb",
|
172
178
|
"samples/hello/hello_computed.rb",
|
173
179
|
"samples/hello/hello_computed/contact.rb",
|
180
|
+
"samples/hello/hello_cursor.rb",
|
174
181
|
"samples/hello/hello_custom_shell.rb",
|
175
182
|
"samples/hello/hello_custom_widget.rb",
|
176
183
|
"samples/hello/hello_date_time.rb",
|
@@ -186,6 +193,7 @@ Gem::Specification.new do |s|
|
|
186
193
|
"samples/hello/hello_menu_bar.rb",
|
187
194
|
"samples/hello/hello_message_box.rb",
|
188
195
|
"samples/hello/hello_pop_up_context_menu.rb",
|
196
|
+
"samples/hello/hello_progress_bar.rb",
|
189
197
|
"samples/hello/hello_radio.rb",
|
190
198
|
"samples/hello/hello_radio_group.rb",
|
191
199
|
"samples/hello/hello_sash_form.rb",
|
@@ -32,10 +32,12 @@ module Glimmer
|
|
32
32
|
include Observer
|
33
33
|
|
34
34
|
attr_reader :widget, :property
|
35
|
-
def initialize(widget, property, translator = nil)
|
35
|
+
def initialize(widget, property, translator = nil, sync_exec: false, async_exec: false)
|
36
36
|
@widget = widget
|
37
37
|
@property = property
|
38
38
|
@translator = translator || proc {|value| value} #TODO check on this it doesn't seem used
|
39
|
+
@sync_exec = sync_exec
|
40
|
+
@async_exec = async_exec
|
39
41
|
|
40
42
|
if @widget.respond_to?(:on_widget_disposed)
|
41
43
|
@widget.on_widget_disposed do |dispose_event|
|
@@ -54,8 +56,10 @@ module Glimmer
|
|
54
56
|
end
|
55
57
|
@widget.set_attribute(@property, converted_value) unless evaluate_property == converted_value
|
56
58
|
end
|
57
|
-
if Config.auto_sync_exec? && Config.require_sync_exec?
|
59
|
+
if @sync_exec || Config.auto_sync_exec? && Config.require_sync_exec?
|
58
60
|
SWT::DisplayProxy.instance.sync_exec(&update_operation)
|
61
|
+
elsif @async_exec
|
62
|
+
SWT::DisplayProxy.instance.async_exec(&update_operation)
|
59
63
|
else
|
60
64
|
update_operation.call
|
61
65
|
end
|
@@ -66,7 +70,16 @@ module Glimmer
|
|
66
70
|
unregister_all_observables
|
67
71
|
return
|
68
72
|
end
|
69
|
-
|
73
|
+
read_operation = lambda do
|
74
|
+
@widget.get_attribute(@property)
|
75
|
+
end
|
76
|
+
if @sync_exec || Config.auto_sync_exec? && Config.require_sync_exec?
|
77
|
+
SWT::DisplayProxy.instance.sync_exec(&read_operation)
|
78
|
+
elsif @async_exec
|
79
|
+
SWT::DisplayProxy.instance.async_exec(&read_operation)
|
80
|
+
else
|
81
|
+
read_operation.call
|
82
|
+
end
|
70
83
|
end
|
71
84
|
end
|
72
85
|
end
|
@@ -46,11 +46,14 @@ module Glimmer
|
|
46
46
|
|
47
47
|
def interpret(parent, keyword, *args, &block)
|
48
48
|
options = args.last.is_a?(Hash) ? args.pop : {}
|
49
|
-
UI::CustomWidget.for(keyword).new(parent, *args, options, &block)
|
49
|
+
UI::CustomWidget.for(keyword).new(parent, *args, options, &block).tap do |new_custom_widget|
|
50
|
+
new_custom_widget.body_root.paint_pixel_by_pixel(&block) if block&.parameters&.count == 2
|
51
|
+
end
|
50
52
|
end
|
51
53
|
|
52
54
|
def add_content(parent, &block)
|
53
55
|
# TODO consider avoiding source_location
|
56
|
+
return if block&.parameters&.count == 2
|
54
57
|
if block.source_location == parent.content&.__getobj__.source_location
|
55
58
|
parent.content.call(parent) unless parent.content.called?
|
56
59
|
else
|
@@ -22,6 +22,7 @@
|
|
22
22
|
require 'glimmer/dsl/expression'
|
23
23
|
require 'glimmer/data_binding/model_binding'
|
24
24
|
require 'glimmer/data_binding/widget_binding'
|
25
|
+
require 'glimmer/swt/display_proxy'
|
25
26
|
|
26
27
|
module Glimmer
|
27
28
|
module DSL
|
@@ -41,7 +42,7 @@ module Glimmer
|
|
41
42
|
|
42
43
|
def interpret(parent, keyword, *args, &block)
|
43
44
|
model_binding = args[0]
|
44
|
-
widget_binding_parameters = [parent, keyword]
|
45
|
+
widget_binding_parameters = [parent, keyword, {async_exec: model_binding.binding_options[:async_exec], sync_exec: model_binding.binding_options[:sync_exec]}]
|
45
46
|
widget_binding = DataBinding::WidgetBinding.new(*widget_binding_parameters)
|
46
47
|
widget_binding.call(model_binding.evaluate_property)
|
47
48
|
#TODO make this options observer dependent and all similar observers in widget specific data binding handlers
|
@@ -20,7 +20,9 @@
|
|
20
20
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
21
|
|
22
22
|
require 'glimmer/dsl/expression'
|
23
|
+
require 'glimmer/dsl/top_level_expression'
|
23
24
|
require 'glimmer/swt/image_proxy'
|
25
|
+
require 'glimmer/swt/widget_proxy'
|
24
26
|
|
25
27
|
module Glimmer
|
26
28
|
module DSL
|
@@ -28,19 +30,28 @@ module Glimmer
|
|
28
30
|
# image expression
|
29
31
|
# Note: Cannot be a static expression because it clashes with image property expression
|
30
32
|
class ImageExpression < Expression
|
33
|
+
include TopLevelExpression
|
31
34
|
include ParentExpression
|
32
35
|
|
33
36
|
def can_interpret?(parent, keyword, *args, &block)
|
34
37
|
(keyword == 'image') and
|
35
|
-
(parent.nil? or parent.respond_to?('image='))
|
38
|
+
(parent.nil? or parent.respond_to?('image=') or args.first.is_a?(Numeric))
|
36
39
|
end
|
37
40
|
|
38
41
|
def interpret(parent, keyword, *args, &block)
|
39
|
-
args.
|
40
|
-
|
42
|
+
options = args.last.is_a?(Hash) ? args.last : {}
|
43
|
+
coordinate_args = args.size == (options.empty? ? 2 : 3)
|
44
|
+
args.unshift(parent) unless parent.nil? || options[:top_level]
|
45
|
+
@create_pixel_by_pixel = coordinate_args && block&.parameters&.count == 2
|
46
|
+
if @create_pixel_by_pixel
|
47
|
+
Glimmer::SWT::ImageProxy.create_pixel_by_pixel(*args, &block)
|
48
|
+
else
|
49
|
+
Glimmer::SWT::ImageProxy.create(*args, &block)
|
50
|
+
end
|
41
51
|
end
|
42
52
|
|
43
53
|
def add_content(parent, &block)
|
54
|
+
return if @create_pixel_by_pixel || block&.parameters&.count == 2
|
44
55
|
super
|
45
56
|
parent.post_add_content
|
46
57
|
end
|
@@ -51,6 +51,7 @@ module Glimmer
|
|
51
51
|
widget_binding.call(model_binding.evaluate_property)
|
52
52
|
widget_binding.observe(model, model_binding.property_name_expression)
|
53
53
|
|
54
|
+
raise(Glimmer::Error, "No radios found! Make sure radio selection is data-bound to a property having property_options as non-empty array!") if parent.items.empty?
|
54
55
|
parent.on_widget_selected do
|
55
56
|
model_binding.call(widget_binding.evaluate_property)
|
56
57
|
end
|
@@ -32,7 +32,7 @@ module Glimmer
|
|
32
32
|
include ParentExpression
|
33
33
|
|
34
34
|
def can_interpret?(parent, keyword, *args, &block)
|
35
|
-
|
35
|
+
super and
|
36
36
|
(parent.nil? or parent.is_a?(Glimmer::SWT::ShellProxy))
|
37
37
|
end
|
38
38
|
|
@@ -41,6 +41,9 @@ module Glimmer
|
|
41
41
|
Glimmer::SWT::ShellProxy.send(:new, *args)
|
42
42
|
end
|
43
43
|
end
|
44
|
+
class WindowExpression < ShellExpression
|
45
|
+
# Alias
|
46
|
+
end
|
44
47
|
end
|
45
48
|
end
|
46
49
|
end
|
@@ -40,10 +40,13 @@ module Glimmer
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def interpret(parent, keyword, *args, &block)
|
43
|
-
Glimmer::SWT::WidgetProxy.create(keyword, parent, args)
|
43
|
+
Glimmer::SWT::WidgetProxy.create(keyword, parent, args).tap do |new_widget_proxy|
|
44
|
+
new_widget_proxy.paint_pixel_by_pixel(&block) if block&.parameters&.count == 2
|
45
|
+
end
|
44
46
|
end
|
45
47
|
|
46
48
|
def add_content(parent, &block)
|
49
|
+
return if block&.parameters&.count == 2
|
47
50
|
super
|
48
51
|
parent.post_add_content
|
49
52
|
parent.finish_add_content!
|
@@ -33,7 +33,7 @@ module Glimmer
|
|
33
33
|
include_package 'org.eclipse.swt.graphics'
|
34
34
|
|
35
35
|
class << self
|
36
|
-
def
|
36
|
+
def create(*args)
|
37
37
|
flyweight_color_proxies[args] ||= new(*args)
|
38
38
|
end
|
39
39
|
|
@@ -59,8 +59,10 @@ module Glimmer
|
|
59
59
|
# rgba is 4 arguments representing Red, Green, Blue, and Alpha numeric values
|
60
60
|
#
|
61
61
|
def initialize(*args)
|
62
|
+
@options = args.last.is_a?(Hash) ? args.pop : {}
|
62
63
|
@args = args
|
63
|
-
|
64
|
+
@args = @args.first if @args.first.is_a?(Array)
|
65
|
+
ensure_arg_values_within_valid_bounds unless @options[:ensure_bounds] == false
|
64
66
|
end
|
65
67
|
|
66
68
|
def swt_color
|
@@ -75,8 +77,7 @@ module Glimmer
|
|
75
77
|
@swt_color = @args.first
|
76
78
|
end
|
77
79
|
when 3..4
|
78
|
-
|
79
|
-
@swt_color = Color.new(*[red, green, blue, alpha].compact)
|
80
|
+
@swt_color = Color.new(*@args)
|
80
81
|
end
|
81
82
|
end
|
82
83
|
@swt_color
|
@@ -64,6 +64,18 @@ module Glimmer
|
|
64
64
|
respond_to?(method_name)
|
65
65
|
end
|
66
66
|
|
67
|
+
def can_handle_observation_request?(observation_request)
|
68
|
+
@styled_text_proxy.can_handle_observation_request?(observation_request)
|
69
|
+
rescue
|
70
|
+
super
|
71
|
+
end
|
72
|
+
|
73
|
+
def handle_observation_request(observation_request, &block)
|
74
|
+
@styled_text_proxy.handle_observation_request(observation_request, &block)
|
75
|
+
rescue
|
76
|
+
super
|
77
|
+
end
|
78
|
+
|
67
79
|
def root_block=(block)
|
68
80
|
body_root.content(&block)
|
69
81
|
end
|
@@ -153,6 +165,7 @@ module Glimmer
|
|
153
165
|
top_margin 5
|
154
166
|
right_margin 5
|
155
167
|
bottom_margin 5
|
168
|
+
tabs 2
|
156
169
|
|
157
170
|
if default_behavior
|
158
171
|
on_key_pressed { |event|
|
@@ -166,6 +179,15 @@ module Glimmer
|
|
166
179
|
jump_to_end_of_line
|
167
180
|
end
|
168
181
|
}
|
182
|
+
on_verify_text { |verify_event|
|
183
|
+
if verify_event.text == "\n"
|
184
|
+
line_index = verify_event.widget.get_line_at_offset(verify_event.widget.get_caret_offset)
|
185
|
+
line = verify_event.widget.get_line(line_index)
|
186
|
+
line_indent = line.match(/^([ ]*)/)[1].to_s.size
|
187
|
+
verify_event.text += ' '*line_indent
|
188
|
+
verify_event.text += ' '*2 if line.strip.end_with?('{') || line.strip.match(/do([ ]*[|][^|]*[|])?$/) || line.start_with?('class') || line.start_with?('module') || line.strip.start_with?('def')
|
189
|
+
end
|
190
|
+
}
|
169
191
|
end
|
170
192
|
|
171
193
|
on_modify_text { |event|
|
@@ -24,12 +24,75 @@ module Glimmer
|
|
24
24
|
module Custom
|
25
25
|
# Represents SWT drawable controls (widgets like canvas) and display
|
26
26
|
module Drawable
|
27
|
+
attr_accessor :requires_shape_disposal, :image_double_buffered
|
28
|
+
alias requires_shape_disposal? requires_shape_disposal
|
29
|
+
alias image_double_buffered? image_double_buffered
|
30
|
+
|
31
|
+
include_package 'org.eclipse.swt.graphics'
|
32
|
+
|
27
33
|
def shapes
|
28
34
|
@shapes ||= []
|
29
35
|
end
|
30
36
|
|
31
|
-
def
|
32
|
-
|
37
|
+
def image_buffered_shapes
|
38
|
+
@image_buffered_shapes ||= []
|
39
|
+
end
|
40
|
+
|
41
|
+
def add_shape(shape)
|
42
|
+
if !@image_double_buffered || shape.args.first == @image_proxy_buffer
|
43
|
+
shapes << shape
|
44
|
+
else
|
45
|
+
image_buffered_shapes << shape
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def clear_shapes(dispose_images: true, dispose_patterns: true)
|
50
|
+
# Optimize further by having a collection of disposable_shapes independent of shapes, which is much smaller and only has shapes that require disposal (shapes with patterns or image)
|
51
|
+
shapes.dup.each {|s| s.dispose(dispose_images: dispose_images, dispose_patterns: dispose_patterns) } if requires_shape_disposal?
|
52
|
+
end
|
53
|
+
|
54
|
+
def paint_pixel_by_pixel(width = nil, height = nil, &each_pixel_color)
|
55
|
+
if @image_double_buffered
|
56
|
+
work = lambda do |paint_event|
|
57
|
+
width ||= swt_drawable.bounds.width
|
58
|
+
height ||= swt_drawable.bounds.height
|
59
|
+
@image_proxy_buffer ||= ImageProxy.create_pixel_by_pixel(width, height, &each_pixel_color)
|
60
|
+
@image_proxy_buffer.shape(self).paint(paint_event)
|
61
|
+
end
|
62
|
+
else
|
63
|
+
work = lambda do |paint_event_or_image|
|
64
|
+
the_gc = paint_event_or_image.gc
|
65
|
+
current_foreground = nil
|
66
|
+
width ||= swt_drawable.bounds.width
|
67
|
+
height ||= swt_drawable.bounds.height
|
68
|
+
height.times do |y|
|
69
|
+
width.times do |x|
|
70
|
+
new_foreground = each_pixel_color.call(x, y)
|
71
|
+
new_foreground = Glimmer::SWT::ColorProxy.create(new_foreground, ensure_bounds: false) unless new_foreground.is_a?(ColorProxy) || new_foreground.is_a?(Color)
|
72
|
+
new_foreground = new_foreground.swt_color if new_foreground.is_a?(Glimmer::SWT::ColorProxy)
|
73
|
+
the_gc.foreground = current_foreground = new_foreground unless new_foreground == current_foreground
|
74
|
+
the_gc.draw_point x, y
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
if respond_to?(:gc)
|
80
|
+
work.call(self)
|
81
|
+
else
|
82
|
+
on_swt_paint(&work)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def swt_drawable
|
87
|
+
swt_drawable = nil
|
88
|
+
if respond_to?(:swt_image)
|
89
|
+
swt_drawable = swt_image
|
90
|
+
elsif respond_to?(:swt_display)
|
91
|
+
swt_drawable = swt_display
|
92
|
+
elsif respond_to?(:swt_widget)
|
93
|
+
swt_drawable = swt_widget
|
94
|
+
end
|
95
|
+
swt_drawable
|
33
96
|
end
|
34
97
|
|
35
98
|
def deregister_shape_painting
|
@@ -40,8 +103,21 @@ module Glimmer
|
|
40
103
|
# TODO consider performance optimization relating to order of shape rendering (affecting only further shapes not previous ones)
|
41
104
|
if @paint_listener_proxy.nil?
|
42
105
|
shape_painter = lambda do |paint_event|
|
43
|
-
|
44
|
-
|
106
|
+
shape_painting_work = lambda do |paint_event|
|
107
|
+
paintable_shapes = @image_double_buffered ? image_buffered_shapes : shapes
|
108
|
+
paintable_shapes.each do |shape|
|
109
|
+
shape.paint(paint_event)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
if @image_double_buffered
|
113
|
+
if @image_proxy_buffer.nil?
|
114
|
+
swt_image = Image.new(DisplayProxy.instance.swt_display, bounds.width, bounds.height)
|
115
|
+
@image_proxy_buffer = ImageProxy.new(swt_image: swt_image)
|
116
|
+
shape_painting_work.call(@image_proxy_buffer)
|
117
|
+
end
|
118
|
+
@image_proxy_buffer.shape(self).paint(paint_event)
|
119
|
+
else
|
120
|
+
shape_painting_work.call(paint_event)
|
45
121
|
end
|
46
122
|
end
|
47
123
|
|
@@ -73,7 +73,8 @@ module Glimmer
|
|
73
73
|
end
|
74
74
|
|
75
75
|
def can_handle_observation_request?(observation_request)
|
76
|
-
radios.first&.can_handle_observation_request?(observation_request)
|
76
|
+
radios.first&.can_handle_observation_request?(observation_request) or
|
77
|
+
super(observation_request)
|
77
78
|
end
|
78
79
|
|
79
80
|
def handle_observation_request(observation_request, &block)
|
@@ -103,7 +103,7 @@ module Glimmer
|
|
103
103
|
@options.reject {|key, value| %w[fill gradient round].include?(key.to_s)}.each do |property, property_args|
|
104
104
|
@properties[property] = property_args
|
105
105
|
end
|
106
|
-
@parent.
|
106
|
+
@parent.add_shape(self)
|
107
107
|
post_add_content if property_block.nil?
|
108
108
|
end
|
109
109
|
|
@@ -133,8 +133,8 @@ module Glimmer
|
|
133
133
|
|
134
134
|
def post_add_content
|
135
135
|
unless @content_added
|
136
|
-
amend_method_name_options_based_on_properties
|
137
|
-
@parent.setup_shape_painting
|
136
|
+
amend_method_name_options_based_on_properties!
|
137
|
+
@parent.setup_shape_painting unless @parent.is_a?(ImageProxy)
|
138
138
|
@content_added = true
|
139
139
|
end
|
140
140
|
end
|
@@ -142,7 +142,10 @@ module Glimmer
|
|
142
142
|
def apply_property_arg_conversions(method_name, property, args)
|
143
143
|
args = args.dup
|
144
144
|
the_java_method = org.eclipse.swt.graphics.GC.java_class.declared_instance_methods.detect {|m| m.name == method_name}
|
145
|
-
if
|
145
|
+
if ['setBackground', 'setForeground'].include?(method_name.to_s) && args.first.is_a?(Array)
|
146
|
+
args[0] = ColorProxy.new(args[0])
|
147
|
+
end
|
148
|
+
if args.first.is_a?(Symbol) || args.first.is_a?(String)
|
146
149
|
if the_java_method.parameter_types.first == Color.java_class
|
147
150
|
args[0] = ColorProxy.new(args[0])
|
148
151
|
end
|
@@ -163,6 +166,7 @@ module Glimmer
|
|
163
166
|
args[0] = args[0].swt_transform
|
164
167
|
end
|
165
168
|
if ['setBackgroundPattern', 'setForegroundPattern'].include?(method_name.to_s)
|
169
|
+
@parent.requires_shape_disposal = true
|
166
170
|
args.each_with_index do |arg, i|
|
167
171
|
if arg.is_a?(Symbol) || arg.is_a?(String)
|
168
172
|
args[i] = ColorProxy.new(arg).swt_color
|
@@ -177,41 +181,48 @@ module Glimmer
|
|
177
181
|
args
|
178
182
|
end
|
179
183
|
|
180
|
-
def apply_shape_arg_conversions
|
181
|
-
if args.size > 1 && (
|
182
|
-
args[0] = args.dup
|
183
|
-
args[1..-1] = []
|
184
|
+
def apply_shape_arg_conversions!
|
185
|
+
if @args.size > 1 && (['polygon', 'polyline'].include?(@name))
|
186
|
+
@args[0] = @args.dup
|
187
|
+
@args[1..-1] = []
|
184
188
|
end
|
185
189
|
end
|
186
190
|
|
187
|
-
def apply_shape_arg_defaults
|
188
|
-
if
|
189
|
-
(6 - args.size).times {args << 60}
|
190
|
-
elsif
|
191
|
-
args << true
|
192
|
-
elsif (
|
193
|
-
args << true
|
194
|
-
end
|
195
|
-
if method_name.include?('image') && args.first.is_a?(String)
|
196
|
-
args[0] = ImageProxy.new(args[0])
|
191
|
+
def apply_shape_arg_defaults!
|
192
|
+
if @name.include?('rectangle') && round? && @args.size.between?(4, 5)
|
193
|
+
(6 - @args.size).times {@args << 60}
|
194
|
+
elsif @name.include?('rectangle') && gradient? && @args.size == 4
|
195
|
+
@args << true
|
196
|
+
elsif (@name.include?('text') || @name.include?('String')) && !@properties.keys.map(&:to_s).include?('background') && @args.size == 3
|
197
|
+
@args << true
|
197
198
|
end
|
198
|
-
if
|
199
|
-
@
|
199
|
+
if @name.include?('image')
|
200
|
+
@parent.requires_shape_disposal = true
|
201
|
+
if @args.size == 1
|
202
|
+
@args[1] = 0
|
203
|
+
@args[2] = 0
|
204
|
+
end
|
205
|
+
if @args.first.is_a?(String)
|
206
|
+
@args[0] = ImageProxy.new(@args[0])
|
207
|
+
end
|
208
|
+
if @args.first.is_a?(ImageProxy)
|
209
|
+
@image = @args[0] = @args[0].swt_image
|
210
|
+
end
|
200
211
|
end
|
201
212
|
end
|
202
213
|
|
203
214
|
# Tolerates shape extra args added by user by mistake
|
204
215
|
# (e.g. happens when switching from round rectangle to a standard one without removing all extra args)
|
205
|
-
def tolerate_shape_extra_args
|
216
|
+
def tolerate_shape_extra_args!
|
206
217
|
the_java_method_arg_count = org.eclipse.swt.graphics.GC.java_class.declared_instance_methods.select do |m|
|
207
|
-
m.name == method_name.camelcase(:lower)
|
218
|
+
m.name == @method_name.camelcase(:lower)
|
208
219
|
end.map(&:parameter_types).map(&:size).max
|
209
|
-
if args.size > the_java_method_arg_count
|
210
|
-
args[the_java_method_arg_count..-1] = []
|
220
|
+
if @args.size > the_java_method_arg_count
|
221
|
+
@args[the_java_method_arg_count..-1] = []
|
211
222
|
end
|
212
223
|
end
|
213
224
|
|
214
|
-
def amend_method_name_options_based_on_properties
|
225
|
+
def amend_method_name_options_based_on_properties!
|
215
226
|
return if @name == 'point'
|
216
227
|
if has_some_background? && !has_some_foreground?
|
217
228
|
@options[:fill] = true
|
@@ -252,16 +263,20 @@ module Glimmer
|
|
252
263
|
the_pattern
|
253
264
|
end
|
254
265
|
|
255
|
-
def dispose
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
266
|
+
def dispose(dispose_images: true, dispose_patterns: true)
|
267
|
+
if dispose_patterns
|
268
|
+
@background_pattern&.dispose
|
269
|
+
@background_pattern = nil
|
270
|
+
@foreground_pattern&.dispose
|
271
|
+
@foreground_pattern = nil
|
272
|
+
end
|
273
|
+
if dispose_images
|
274
|
+
@image&.dispose
|
275
|
+
@image = nil
|
276
|
+
end
|
262
277
|
@parent.shapes.delete(self)
|
263
278
|
end
|
264
|
-
|
279
|
+
|
265
280
|
def paint(paint_event)
|
266
281
|
calculate_paint_args!
|
267
282
|
@properties.each do |property, args|
|
@@ -276,20 +291,39 @@ module Glimmer
|
|
276
291
|
end
|
277
292
|
|
278
293
|
def calculate_paint_args!
|
279
|
-
unless @
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
294
|
+
unless @calculated_paint_args
|
295
|
+
if @name == 'point'
|
296
|
+
# optimized performance calculation for pixel points
|
297
|
+
if !@properties[:foreground].is_a?(Color)
|
298
|
+
if @properties[:foreground].is_a?(Array)
|
299
|
+
@properties[:foreground] = ColorProxy.new(@properties[:foreground], ensure_bounds: false)
|
300
|
+
end
|
301
|
+
if @properties[:foreground].is_a?(Symbol) || @properties[:foreground].is_a?(String)
|
302
|
+
@properties[:foreground] = ColorProxy.new(@properties[:foreground], ensure_bounds: false)
|
303
|
+
end
|
304
|
+
if @properties[:foreground].is_a?(ColorProxy)
|
305
|
+
@properties[:foreground] = @properties[:foreground].swt_color
|
306
|
+
end
|
307
|
+
end
|
308
|
+
else
|
309
|
+
@properties['background'] = [@parent.background] if fill? && !has_some_background?
|
310
|
+
@properties['foreground'] = [@parent.foreground] if @parent.respond_to?(:foreground) && draw? && !has_some_foreground?
|
311
|
+
# TODO regarding alpha, make sure to reset it to parent stored alpha once we allow setting shape properties on parents directly without shapes
|
312
|
+
@properties['alpha'] ||= [255]
|
313
|
+
@properties['font'] = [@parent.font] if @parent.respond_to?(:font) && draw? && !@properties.keys.map(&:to_s).include?('font')
|
314
|
+
# TODO regarding transform, make sure to reset it to parent stored alpha once we allow setting shape properties on parents directly without shapes
|
315
|
+
# Also do that with all future-added properties
|
316
|
+
@properties['transform'] = [nil] if @parent.respond_to?(:transform) && !@properties.keys.map(&:to_s).include?('transform')
|
317
|
+
@properties.each do |property, args|
|
318
|
+
method_name = attribute_setter(property)
|
319
|
+
converted_args = apply_property_arg_conversions(method_name, property, args)
|
320
|
+
@properties[property] = converted_args
|
321
|
+
end
|
322
|
+
apply_shape_arg_conversions!
|
323
|
+
apply_shape_arg_defaults!
|
324
|
+
tolerate_shape_extra_args!
|
325
|
+
@calculated_paint_args = true
|
288
326
|
end
|
289
|
-
apply_shape_arg_conversions(@method_name, @args)
|
290
|
-
apply_shape_arg_defaults(@method_name, @args)
|
291
|
-
tolerate_shape_extra_args(@method_name, @args)
|
292
|
-
@calculated_paint_args = true
|
293
327
|
end
|
294
328
|
end
|
295
329
|
|