glimmer-dsl-swt 4.18.4.3 → 4.18.4.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +35 -0
  3. data/README.md +81 -5089
  4. data/VERSION +1 -1
  5. data/docs/reference/GLIMMER_COMMAND.md +591 -0
  6. data/docs/reference/GLIMMER_CONFIGURATION.md +183 -0
  7. data/docs/reference/GLIMMER_GIRB.md +30 -0
  8. data/docs/reference/GLIMMER_GUI_DSL_SYNTAX.md +3366 -0
  9. data/docs/reference/GLIMMER_PACKAGING_AND_DISTRIBUTION.md +202 -0
  10. data/docs/reference/GLIMMER_SAMPLES.md +676 -0
  11. data/docs/reference/GLIMMER_STYLE_GUIDE.md +14 -0
  12. data/glimmer-dsl-swt.gemspec +16 -8
  13. data/lib/glimmer/dsl/swt/custom_widget_expression.rb +3 -3
  14. data/lib/glimmer/dsl/swt/exec_expression.rb +1 -1
  15. data/lib/glimmer/dsl/swt/image_expression.rb +3 -0
  16. data/lib/glimmer/dsl/swt/observe_expression.rb +8 -5
  17. data/lib/glimmer/dsl/swt/pixel_expression.rb +38 -0
  18. data/lib/glimmer/dsl/swt/timer_exec_expression.rb +35 -0
  19. data/lib/glimmer/dsl/swt/widget_expression.rb +1 -0
  20. data/lib/glimmer/swt/color_proxy.rb +4 -3
  21. data/lib/glimmer/swt/custom/animation.rb +10 -8
  22. data/lib/glimmer/swt/custom/code_text.rb +24 -20
  23. data/lib/glimmer/swt/custom/drawable.rb +54 -6
  24. data/lib/glimmer/swt/custom/shape.rb +91 -60
  25. data/lib/glimmer/swt/display_proxy.rb +11 -10
  26. data/lib/glimmer/swt/image_proxy.rb +17 -6
  27. data/lib/glimmer/swt/properties.rb +35 -10
  28. data/lib/glimmer/swt/widget_proxy.rb +17 -3
  29. data/lib/glimmer/ui/custom_widget.rb +17 -0
  30. data/samples/elaborate/mandelbrot_fractal.rb +103 -0
  31. data/samples/elaborate/meta_sample.rb +1 -1
  32. data/samples/elaborate/tetris.rb +5 -18
  33. data/samples/elaborate/tetris/view/block.rb +1 -1
  34. data/samples/elaborate/tetris/view/playfield.rb +1 -1
  35. data/samples/hello/hello_canvas_animation.rb +1 -1
  36. data/samples/hello/hello_canvas_transform.rb +1 -1
  37. data/samples/hello/hello_table.rb +1 -1
  38. data/samples/hello/hello_table/baseball_park.png +0 -0
  39. metadata +14 -6
  40. data/samples/elaborate/meta_sample/meta_sample_logo.png +0 -0
  41. data/samples/hello/hello_canvas_transform/hello_canvas_transform_image.png +0 -0
@@ -24,22 +24,70 @@ 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
 
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
+
31
49
  def clear_shapes
32
- shapes.dup.each(&:dispose)
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(&:dispose) if requires_shape_disposal?
52
+ end
53
+
54
+ def deregister_shape_painting
55
+ @paint_listener_proxy&.deregister
33
56
  end
34
57
 
35
- def resetup_shape_painting
58
+ def setup_shape_painting
36
59
  # TODO consider performance optimization relating to order of shape rendering (affecting only further shapes not previous ones)
37
- reset_gc if respond_to?(:reset_gc)
38
- shapes.each do |shape|
39
- shape.paint_listener_proxy&.unregister
40
- shape.setup_painting
60
+ if @paint_listener_proxy.nil?
61
+ shape_painter = lambda do |paint_event|
62
+ shape_painting_work = lambda do |paint_event|
63
+ paintable_shapes = @image_double_buffered ? image_buffered_shapes : shapes
64
+ paintable_shapes.each do |shape|
65
+ shape.paint(paint_event)
66
+ end
67
+ end
68
+ if @image_double_buffered
69
+ if @image_proxy_buffer.nil?
70
+ swt_image = Image.new(DisplayProxy.instance.swt_display, bounds.width, bounds.height)
71
+ @image_proxy_buffer = ImageProxy.new(swt_image: swt_image)
72
+ shape_painting_work.call(@image_proxy_buffer)
73
+ end
74
+ @image_proxy_buffer.shape(self).paint(paint_event)
75
+ else
76
+ shape_painting_work.call(paint_event)
77
+ end
78
+ end
79
+
80
+ # TODO consider making this logic polymorphic (image vs other)
81
+ if respond_to?(:swt_image)
82
+ shape_painter.call(self) # treat self as paint event since image has its own gc and doesn't do repaints (it's a one time deal for now though could be adjusted in the future.)
83
+ else
84
+ @paint_listener_proxy = on_swt_paint(&shape_painter)
85
+ end
86
+ else
87
+ redraw if @finished_add_content && !is_disposed
41
88
  end
42
89
  end
90
+ alias resetup_shape_painting setup_shape_painting
43
91
  end
44
92
 
45
93
  end
@@ -39,7 +39,7 @@ module Glimmer
39
39
 
40
40
  class << self
41
41
  def valid?(parent, keyword, *args, &block)
42
- gc_instance_methods.include?(method_name(keyword, args))
42
+ gc_instance_methods.include?(method_name(keyword, arg_options(args)))
43
43
  end
44
44
 
45
45
  def gc_instance_methods
@@ -62,14 +62,14 @@ module Glimmer
62
62
  options.nil? ? {} : options.symbolize_keys
63
63
  end
64
64
 
65
- def method_name(keyword, args)
66
- method_arg_options = arg_options(args)
65
+ def method_name(keyword, method_arg_options)
66
+ keyword = keyword.to_s
67
+ method_arg_options = method_arg_options.select {|key, value| %w[fill gradient round].include?(key.to_s)}
67
68
  unless flyweight_method_names.keys.include?([keyword, method_arg_options])
68
- keyword = keyword.to_s
69
- gradient = 'gradient_' if method_arg_options[:gradient]
70
- round = 'round_' if method_arg_options[:round]
71
- gc_instance_method_name_prefix = !['polyline', 'point', 'image', 'focus'].include?(keyword) && (method_arg_options[:fill] || method_arg_options[:gradient]) ? 'fill_' : 'draw_'
72
- flyweight_method_names[[keyword, method_arg_options]] = "#{gc_instance_method_name_prefix}#{gradient}#{round}#{keyword}"
69
+ gradient = 'Gradient' if method_arg_options[:gradient]
70
+ round = 'Round' if method_arg_options[:round]
71
+ gc_instance_method_name_prefix = !['polyline', 'point', 'image', 'focus'].include?(keyword) && (method_arg_options[:fill] || method_arg_options[:gradient]) ? 'fill' : 'draw'
72
+ flyweight_method_names[[keyword, method_arg_options]] = "#{gc_instance_method_name_prefix}#{gradient}#{round}#{keyword.capitalize}"
73
73
  end
74
74
  flyweight_method_names[[keyword, method_arg_options]]
75
75
  end
@@ -91,16 +91,19 @@ module Glimmer
91
91
  end
92
92
  end
93
93
 
94
- attr_reader :parent, :name, :args, :options, :paint_listener_proxy
94
+ attr_reader :parent, :name, :args, :options
95
95
 
96
96
  def initialize(parent, keyword, *args, &property_block)
97
97
  @parent = parent
98
98
  @name = keyword
99
- @method_name = self.class.method_name(keyword, args)
100
99
  @options = self.class.arg_options(args, extract: true)
100
+ @method_name = self.class.method_name(keyword, @options)
101
101
  @args = args
102
102
  @properties = {}
103
- @parent.shapes << self
103
+ @options.reject {|key, value| %w[fill gradient round].include?(key.to_s)}.each do |property, property_args|
104
+ @properties[property] = property_args
105
+ end
106
+ @parent.add_shape(self)
104
107
  post_add_content if property_block.nil?
105
108
  end
106
109
 
@@ -129,15 +132,20 @@ module Glimmer
129
132
  end
130
133
 
131
134
  def post_add_content
132
- amend_method_name_options_based_on_properties
133
- setup_painting
134
- @content_added = true
135
+ unless @content_added
136
+ amend_method_name_options_based_on_properties!
137
+ @parent.setup_shape_painting unless @parent.is_a?(ImageProxy)
138
+ @content_added = true
139
+ end
135
140
  end
136
141
 
137
142
  def apply_property_arg_conversions(method_name, property, args)
138
143
  args = args.dup
139
144
  the_java_method = org.eclipse.swt.graphics.GC.java_class.declared_instance_methods.detect {|m| m.name == method_name}
140
- if (args.first.is_a?(Symbol) || args.first.is_a?(String))
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)
141
149
  if the_java_method.parameter_types.first == Color.java_class
142
150
  args[0] = ColorProxy.new(args[0])
143
151
  end
@@ -158,6 +166,7 @@ module Glimmer
158
166
  args[0] = args[0].swt_transform
159
167
  end
160
168
  if ['setBackgroundPattern', 'setForegroundPattern'].include?(method_name.to_s)
169
+ @parent.requires_shape_disposal = true
161
170
  args.each_with_index do |arg, i|
162
171
  if arg.is_a?(Symbol) || arg.is_a?(String)
163
172
  args[i] = ColorProxy.new(arg).swt_color
@@ -172,41 +181,49 @@ module Glimmer
172
181
  args
173
182
  end
174
183
 
175
- def apply_shape_arg_conversions(method_name, args)
176
- if args.size > 1 && (method_name.include?('polygon') || method_name.include?('polyline'))
177
- args[0] = args.dup
178
- 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] = []
179
188
  end
180
189
  end
181
190
 
182
- def apply_shape_arg_defaults(method_name, args)
183
- if method_name.include?('round_rectangle') && args.size.between?(4, 5)
184
- (6 - args.size).times {args << 60}
185
- elsif method_name.include?('rectangle') && gradient? && args.size == 4
186
- args << true
187
- elsif (method_name.include?('text') || method_name.include?('string')) && !@properties.keys.map(&:to_s).include?('background') && args.size == 3
188
- args << true
189
- end
190
- if method_name.include?('image') && args.first.is_a?(String)
191
- 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
192
198
  end
193
- if method_name.include?('image') && args.first.is_a?(ImageProxy)
194
- @image = args[0] = args[0].swt_image
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
195
211
  end
196
212
  end
197
213
 
198
214
  # Tolerates shape extra args added by user by mistake
199
215
  # (e.g. happens when switching from round rectangle to a standard one without removing all extra args)
200
- def tolerate_shape_extra_args(method_name, args)
216
+ def tolerate_shape_extra_args!
201
217
  the_java_method_arg_count = org.eclipse.swt.graphics.GC.java_class.declared_instance_methods.select do |m|
202
- m.name == method_name.camelcase(:lower)
218
+ m.name == @method_name.camelcase(:lower)
203
219
  end.map(&:parameter_types).map(&:size).max
204
- if args.size > the_java_method_arg_count
205
- args[the_java_method_arg_count..-1] = []
220
+ if @args.size > the_java_method_arg_count
221
+ @args[the_java_method_arg_count..-1] = []
206
222
  end
207
223
  end
208
224
 
209
- def amend_method_name_options_based_on_properties
225
+ def amend_method_name_options_based_on_properties!
226
+ return if @name == 'point'
210
227
  if has_some_background? && !has_some_foreground?
211
228
  @options[:fill] = true
212
229
  elsif !has_some_background? && has_some_foreground?
@@ -218,7 +235,7 @@ module Glimmer
218
235
  if @name == 'rectangle' && @args.size > 4 && @args.last.is_a?(Numeric)
219
236
  @options[:round] = true
220
237
  end
221
- @method_name = self.class.method_name(@name, @args + [@options])
238
+ @method_name = self.class.method_name(@name, @options)
222
239
  end
223
240
 
224
241
  def has_attribute?(attribute_name, *args)
@@ -228,7 +245,7 @@ module Glimmer
228
245
  def set_attribute(attribute_name, *args)
229
246
  @properties[attribute_name] = args
230
247
  if @content_added && !@parent.is_disposed
231
- @parent.resetup_shape_painting
248
+ @calculated_paint_args = false
232
249
  @parent.redraw
233
250
  end
234
251
  end
@@ -247,7 +264,6 @@ module Glimmer
247
264
  end
248
265
 
249
266
  def dispose
250
- paint_listener_proxy&.unregister
251
267
  @background_pattern&.dispose
252
268
  @background_pattern = nil
253
269
  @foreground_pattern&.dispose
@@ -257,36 +273,51 @@ module Glimmer
257
273
  @parent.shapes.delete(self)
258
274
  end
259
275
 
260
- def setup_painting
261
- # TODO consider moving this method to parent (making the logic polymorphic)
262
- return if @parent.is_disposed
263
- if parent.respond_to?(:swt_display)
264
- @paint_listener_proxy = @parent.on_swt_paint(&method(:paint))
265
- elsif parent.respond_to?(:swt_image)
266
- paint(parent) # treat parent as paint event since you don't do repaints with images, it's a one time deal.
267
- elsif parent.respond_to?(:swt_widget)
268
- @paint_listener_proxy = @parent.on_paint_control(&method(:paint))
269
- end
270
- end
271
-
272
276
  def paint(paint_event)
273
- @properties['background'] = [@parent.background] if fill? && !has_some_background?
274
- @properties['foreground'] = [@parent.foreground] if @parent.respond_to?(:foreground) && draw? && !has_some_foreground?
275
- @properties['font'] = [@parent.font] if @parent.respond_to?(:font) && draw? && !@properties.keys.map(&:to_s).include?('font')
276
- @properties['transform'] = [nil] if @parent.respond_to?(:transform) && !@properties.keys.map(&:to_s).include?('transform')
277
+ calculate_paint_args!
277
278
  @properties.each do |property, args|
278
279
  method_name = attribute_setter(property)
279
- converted_args = apply_property_arg_conversions(method_name, property, args)
280
- paint_event.gc.send(method_name, *converted_args)
280
+ # TODO consider optimization of not setting a background/foreground/font if it didn't change from last shape
281
+ paint_event.gc.send(method_name, *args)
281
282
  if property == 'transform' && args.first.is_a?(TransformProxy)
282
283
  args.first.swt_transform.dispose
283
284
  end
284
285
  end
285
- apply_shape_arg_conversions(@method_name, @args)
286
- apply_shape_arg_defaults(@method_name, @args)
287
- tolerate_shape_extra_args(@method_name, @args)
288
286
  paint_event.gc.send(@method_name, *@args)
289
287
  end
288
+
289
+ def calculate_paint_args!
290
+ unless @calculated_paint_args
291
+ if @name == 'point'
292
+ # optimized performance calculation for pixel points
293
+ if !@properties[:foreground].is_a?(Color)
294
+ if @properties[:foreground].is_a?(Array)
295
+ @properties[:foreground] = ColorProxy.new(@properties[:foreground], ensure_bounds: false)
296
+ end
297
+ if @properties[:foreground].is_a?(Symbol) || @properties[:foreground].is_a?(String)
298
+ @properties[:foreground] = ColorProxy.new(@properties[:foreground], ensure_bounds: false)
299
+ end
300
+ if @properties[:foreground].is_a?(ColorProxy)
301
+ @properties[:foreground] = @properties[:foreground].swt_color
302
+ end
303
+ end
304
+ else
305
+ @properties['background'] = [@parent.background] if fill? && !has_some_background?
306
+ @properties['foreground'] = [@parent.foreground] if @parent.respond_to?(:foreground) && draw? && !has_some_foreground?
307
+ @properties['font'] = [@parent.font] if @parent.respond_to?(:font) && draw? && !@properties.keys.map(&:to_s).include?('font')
308
+ @properties['transform'] = [nil] if @parent.respond_to?(:transform) && !@properties.keys.map(&:to_s).include?('transform')
309
+ @properties.each do |property, args|
310
+ method_name = attribute_setter(property)
311
+ converted_args = apply_property_arg_conversions(method_name, property, args)
312
+ @properties[property] = converted_args
313
+ end
314
+ apply_shape_arg_conversions!
315
+ apply_shape_arg_defaults!
316
+ tolerate_shape_extra_args!
317
+ @calculated_paint_args = true
318
+ end
319
+ end
320
+ end
290
321
 
291
322
  end
292
323
 
@@ -81,15 +81,15 @@ module Glimmer
81
81
  end
82
82
 
83
83
  def async_exec(&block)
84
- @swt_display.async_exec(&block)
84
+ @swt_display.asyncExec(&block)
85
85
  end
86
86
 
87
87
  def sync_exec(&block)
88
- @swt_display.sync_exec(&block)
88
+ @swt_display.syncExec(&block)
89
89
  end
90
90
 
91
- def timer_exec(&block)
92
- @swt_display.timer_exec(&block)
91
+ def timer_exec(delay_in_millis, &block)
92
+ @swt_display.timerExec(delay_in_millis, &block)
93
93
  end
94
94
 
95
95
  def on_widget_disposed(&block)
@@ -137,12 +137,13 @@ module Glimmer
137
137
  add_swt_event_filter(constant_name, &block)
138
138
  elsif observation_request.start_with?('on_')
139
139
  event_name = observation_request.sub(/^on_/, '')
140
- if OBSERVED_MENU_ITEMS.include?(event_name)
141
- if OS.mac?
142
- system_menu = swt_display.getSystemMenu
143
- menu_item = system_menu.getItems.find {|menu_item| menu_item.getID == SWTProxy["ID_#{event_name.upcase}"]}
144
- menu_item.addListener(SWTProxy[:Selection], &block)
145
- end
140
+ if OBSERVED_MENU_ITEMS.include?(event_name) && OS.mac?
141
+ system_menu = swt_display.getSystemMenu
142
+ menu_item = system_menu.getItems.find {|menu_item| menu_item.getID == SWTProxy["ID_#{event_name.upcase}"]}
143
+ display_mac_event_registration = menu_item.addListener(SWTProxy[:Selection], &block)
144
+ # TODO enable this code and test on the Mac to ensure automatic cleanup of mac event registrations in custom widgets
145
+ # Glimmer::UI::CustomWidget.current_custom_widgets.last&.observer_registrations&.push(display_mac_event_registration)
146
+ display_mac_event_registration
146
147
  end
147
148
  end
148
149
  end
@@ -32,7 +32,7 @@ module Glimmer
32
32
  class ImageProxy
33
33
  include Custom::Drawable
34
34
  include Properties
35
-
35
+
36
36
  class << self
37
37
  def create(*args)
38
38
  if args.size == 1 && args.first.is_a?(ImageProxy)
@@ -53,6 +53,7 @@ module Glimmer
53
53
  # Takes the same args as the SWT Image class
54
54
  # Alternatively, takes a file path string or a uri:classloader file path string (generated by JRuby when invoking `File.expand_path` inside a JAR file)
55
55
  # and returns an image object.
56
+ # Last but not least, it could serve as a parent for nesting shapes underneath to build an image with the Canvas Shape DSL
56
57
  def initialize(*args, &content)
57
58
  @args = args
58
59
  @parent_proxy = nil
@@ -62,7 +63,7 @@ module Glimmer
62
63
  end
63
64
  options = @args.last.is_a?(Hash) ? @args.delete_at(-1) : {}
64
65
  options[:swt_image] = @args.first if @args.size == 1 && @args.first.is_a?(Image)
65
- @file_path = @args.first if @args.size == 1 && @args.first.is_a?(String)
66
+ @file_path = @args.first if @args.first.is_a?(String)
66
67
  @args = @args.first if @args.size == 1 && @args.first.is_a?(Array)
67
68
  if options&.keys&.include?(:swt_image)
68
69
  @swt_image = options[:swt_image]
@@ -78,23 +79,33 @@ module Glimmer
78
79
  height = (@image_data.height.to_f / @image_data.width.to_f)*width.to_f if !width.nil? && height.nil?
79
80
  width = (@image_data.width.to_f / @image_data.height.to_f)*height.to_f if !height.nil? && width.nil?
80
81
  scale_to(width, height) unless width.nil? || height.nil?
81
- else
82
+ elsif !@args.first.is_a?(ImageProxy) && !@args.first.is_a?(Image)
82
83
  @args.prepend(DisplayProxy.instance.swt_display) unless @args.first.is_a?(Display)
83
84
  @swt_image = Image.new(*@args)
84
85
  @original_image_data = @image_data = @swt_image.image_data
85
86
  end
86
- @swt_image.singleton_class.alias_method(:dispose_without_glimmer, :dispose)
87
87
  proxy = self
88
88
  # TODO consider adding a get_data/set_data method to conform with other SWT widgets
89
89
  @swt_image.singleton_class.define_method(:dispose) do
90
90
  proxy.clear_shapes
91
- dispose_without_glimmer
91
+ super
92
92
  end
93
93
  post_add_content if content.nil?
94
94
  end
95
95
 
96
96
  def post_add_content
97
- @parent&.image = swt_image
97
+ if shapes.any?
98
+ setup_shape_painting
99
+ end
100
+ if @parent.respond_to?('image=')
101
+ @parent&.image = swt_image
102
+ end
103
+ end
104
+
105
+ def shape(parent_proxy = nil, args = nil)
106
+ parent_proxy ||= @parent_proxy
107
+ args ||= [self] # TODO consider passing args if available
108
+ @shape ||= Glimmer::SWT::Custom::Shape.new(parent_proxy, 'image', *args)
98
109
  end
99
110
 
100
111
  def input_stream
@@ -22,28 +22,53 @@
22
22
  module Glimmer
23
23
  module SWT
24
24
  module Properties
25
+ class << self
26
+ def ruby_attribute_setter(attribute_name)
27
+ @ruby_attribute_setters ||= {}
28
+ @ruby_attribute_setters[attribute_name] ||= "#{normalized_attribute(attribute_name)}="
29
+ end
30
+
31
+ def attribute_setter(attribute_name)
32
+ @attribute_setters ||= {}
33
+ @attribute_setters[attribute_name] ||= "set#{normalized_attribute(attribute_name).camelcase(:upper)}"
34
+ end
35
+
36
+ def attribute_getter(attribute_name)
37
+ @attribute_getters ||= {}
38
+ @attribute_getters[attribute_name] ||= "get#{normalized_attribute(attribute_name).camelcase(:upper)}"
39
+ end
40
+
41
+ def normalized_attribute(attribute_name)
42
+ @normalized_attributes ||= {}
43
+ if @normalized_attributes[attribute_name].nil?
44
+ attribute_name = attribute_name.to_s if attribute_name.is_a?(Symbol)
45
+ attribute_name = attribute_name.underscore unless attribute_name.downcase?
46
+ attribute_name = attribute_name.sub(/^get_/, '') if attribute_name.start_with?('get_')
47
+ attribute_name = attribute_name.sub(/^set_/, '') if attribute_name.start_with?('set_')
48
+ attribute_name = attribute_name.sub(/=$/, '') if attribute_name.end_with?('=')
49
+ @normalized_attributes[attribute_name] = attribute_name
50
+ end
51
+ @normalized_attributes[attribute_name]
52
+ end
53
+ alias ruby_attribute_getter normalized_attribute
54
+ end
55
+
25
56
  def ruby_attribute_setter(attribute_name)
26
- "#{normalized_attribute(attribute_name)}="
57
+ Glimmer::SWT::Properties.ruby_attribute_setter(attribute_name)
27
58
  end
28
59
 
29
60
  def attribute_setter(attribute_name)
30
- "set#{normalized_attribute(attribute_name).camelcase(:upper)}"
61
+ Glimmer::SWT::Properties.attribute_setter(attribute_name)
31
62
  end
32
63
 
33
64
  def attribute_getter(attribute_name)
34
- "get#{normalized_attribute(attribute_name).camelcase(:upper)}"
65
+ Glimmer::SWT::Properties.attribute_getter(attribute_name)
35
66
  end
36
67
 
37
68
  def normalized_attribute(attribute_name)
38
- attribute_name = attribute_name.to_s if attribute_name.is_a?(Symbol)
39
- attribute_name = attribute_name.underscore unless attribute_name.downcase?
40
- attribute_name = attribute_name.sub(/^get_/, '') if attribute_name.start_with?('get_')
41
- attribute_name = attribute_name.sub(/^set_/, '') if attribute_name.start_with?('set_')
42
- attribute_name = attribute_name.sub(/=$/, '') if attribute_name.end_with?('=')
43
- attribute_name
69
+ Glimmer::SWT::Properties.normalized_attribute(attribute_name)
44
70
  end
45
71
  alias ruby_attribute_getter normalized_attribute
46
-
47
72
  end
48
73
  end
49
74
  end