Class: Glimmer::SWT::WidgetProxy

Inherits:
Object
  • Object
show all
Includes:
Glimmer, PropertyOwner
Defined in:
lib/glimmer/swt/widget_proxy.rb

Constant Summary collapse

DEFAULT_INITIALIZERS =
{
  "composite" => lambda do |composite_proxy|
    if composite_proxy.layout.nil?
      layout = GridLayoutProxy.new(composite_proxy, [])
      composite_proxy.layout = layout
      layout.margin_width = 15
      layout.margin_height = 15
    end
  end,
#         "scrolled_composite" => lambda do |scrolled_composite|
#           scrolled_composite.expand_horizontal = true
#           scrolled_composite.expand_vertical = true
#         end,
#         "table" => lambda do |table|
#           table.setHeaderVisible(true)
#           table.setLinesVisible(true)
#         end,
  "table_column" => lambda do |table_column_proxy|
    table_column_proxy.width = 80
  end,
#         "group" => lambda do |group_proxy|
#           group_proxy.layout = GridLayoutProxy.new(group_proxy, []) if group.layout.nil?
#         end,
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from PropertyOwner

#attribute_getter, #attribute_setter, #get_attribute

Constructor Details

#initialize(parent, args) ⇒ WidgetProxy

Returns a new instance of WidgetProxy.



100
101
102
103
104
105
106
107
# File 'lib/glimmer/swt/widget_proxy.rb', line 100

def initialize(parent, args)
  @parent = parent        
  @args = args
  @children = Set.new # TODO consider moving to composite
  @enabled = true
  DEFAULT_INITIALIZERS[self.class.underscored_widget_name(self)]&.call(self)
  @parent.add_child(self) # TODO rename to post_initialize_child to be closer to glimmer-dsl-swt terminology        
end

Instance Attribute Details

#argsObject (readonly)

Returns the value of attribute args.



32
33
34
# File 'lib/glimmer/swt/widget_proxy.rb', line 32

def args
  @args
end

#backgroundObject

Returns the value of attribute background.



32
33
34
# File 'lib/glimmer/swt/widget_proxy.rb', line 32

def background
  @background
end

#childrenObject (readonly)

Returns the value of attribute children.



32
33
34
# File 'lib/glimmer/swt/widget_proxy.rb', line 32

def children
  @children
end

#enabledObject

Returns the value of attribute enabled.



32
33
34
# File 'lib/glimmer/swt/widget_proxy.rb', line 32

def enabled
  @enabled
end

#fontObject

Returns the value of attribute font.



32
33
34
# File 'lib/glimmer/swt/widget_proxy.rb', line 32

def font
  @font
end

#foregroundObject

Returns the value of attribute foreground.



32
33
34
# File 'lib/glimmer/swt/widget_proxy.rb', line 32

def foreground
  @foreground
end

#parentObject (readonly)

Returns the value of attribute parent.



32
33
34
# File 'lib/glimmer/swt/widget_proxy.rb', line 32

def parent
  @parent
end

#pathObject (readonly)

Returns the value of attribute path.



32
33
34
# File 'lib/glimmer/swt/widget_proxy.rb', line 32

def path
  @path
end

Class Method Details

.for(keyword, parent, args) ⇒ Object

Factory Method that translates a Glimmer DSL keyword into a WidgetProxy object



36
37
38
39
# File 'lib/glimmer/swt/widget_proxy.rb', line 36

def for(keyword, parent, args)
  the_widget_class = widget_class(keyword)
  the_widget_class.new(parent, args)
end

.max_id_number_for(name) ⇒ Object



58
59
60
# File 'lib/glimmer/swt/widget_proxy.rb', line 58

def max_id_number_for(name)
  @max_id_numbers[name] = max_id_numbers[name] || 0
end

.max_id_numbersObject



62
63
64
# File 'lib/glimmer/swt/widget_proxy.rb', line 62

def max_id_numbers
  @max_id_numbers ||= reset_max_id_numbers!
end

.next_id_number_for(name) ⇒ Object



54
55
56
# File 'lib/glimmer/swt/widget_proxy.rb', line 54

def next_id_number_for(name)
  @max_id_numbers[name] = max_id_number_for(name) + 1
end

.reset_max_id_numbers!Object



66
67
68
# File 'lib/glimmer/swt/widget_proxy.rb', line 66

def reset_max_id_numbers!
  @max_id_numbers = {}
end

.underscored_widget_name(widget_proxy) ⇒ Object



70
71
72
# File 'lib/glimmer/swt/widget_proxy.rb', line 70

def underscored_widget_name(widget_proxy)
  widget_proxy.class.name.split(/::|\./).last.sub(/Proxy$/, '').underscore
end

.widget_class(keyword) ⇒ Object



41
42
43
44
45
46
47
48
# File 'lib/glimmer/swt/widget_proxy.rb', line 41

def widget_class(keyword)
  class_name_alternative = keyword.camelcase(:upper)
  class_name_main = "#{class_name_alternative}Proxy"
  Glimmer::SWT.const_get(class_name_main.to_sym) rescue Glimmer::SWT.const_get(class_name_alternative.to_sym)
rescue => e
  puts "Widget #{keyword} was not found!"
  nil
end

.widget_exists?(keyword) ⇒ Boolean

Returns:

  • (Boolean)


50
51
52
# File 'lib/glimmer/swt/widget_proxy.rb', line 50

def widget_exists?(keyword)
  !!widget_class(keyword)
end

Instance Method Details

#add_child(child) ⇒ Object



126
127
128
129
# File 'lib/glimmer/swt/widget_proxy.rb', line 126

def add_child(child)
  @children << child
  child.render
end

#add_css_class(css_class) ⇒ Object



212
213
214
# File 'lib/glimmer/swt/widget_proxy.rb', line 212

def add_css_class(css_class)
  dom_element.add_class(css_class)
end

#add_css_classes(css_classes_to_add) ⇒ Object



216
217
218
# File 'lib/glimmer/swt/widget_proxy.rb', line 216

def add_css_classes(css_classes_to_add)
  css_classes_to_add.each {|css_class| add_css_class(css_class)}
end

#add_observer(observer, property_name) ⇒ Object



297
298
299
300
301
302
303
# File 'lib/glimmer/swt/widget_proxy.rb', line 297

def add_observer(observer, property_name)
  property_listener_installers = self.class.ancestors.map {|ancestor| widget_property_listener_installers[ancestor]}.compact
  widget_listener_installers = property_listener_installers.map{|installer| installer[property_name.to_s.to_sym]}.compact if !property_listener_installers.empty?
  widget_listener_installers.to_a.each do |widget_listener_installer|
    widget_listener_installer.call(observer)
  end
end

#apply_property_type_converters(attribute_name, args) ⇒ Object



310
311
312
313
314
315
316
317
318
319
320
# File 'lib/glimmer/swt/widget_proxy.rb', line 310

def apply_property_type_converters(attribute_name, args)
  if args.count == 1
    value = args.first
    converter = property_type_converters[attribute_name.to_sym]
    args[0] = converter.call(value) if converter
  end
#         if args.count == 1 && args.first.is_a?(ColorProxy)
#           g_color = args.first
#           args[0] = g_color.swt_color
#         end
end

#build_domObject



179
180
181
182
183
# File 'lib/glimmer/swt/widget_proxy.rb', line 179

def build_dom
  @dom = nil
  @dom = dom
  @dom = @parent.layout.dom(@dom) if @parent.respond_to?(:layout) && @parent.layout        
end

#can_handle_observation_request?(observation_request) ⇒ Boolean

Returns:

  • (Boolean)


266
267
268
269
270
271
272
273
274
275
276
277
# File 'lib/glimmer/swt/widget_proxy.rb', line 266

def can_handle_observation_request?(observation_request)        
  # TODO sort this out for Opal
  observation_request = observation_request.to_s
  if observation_request.start_with?('on_swt_')
    constant_name = observation_request.sub(/^on_swt_/, '')
    SWTProxy.has_constant?(constant_name)
  elsif observation_request.start_with?('on_')
#           event = observation_request.sub(/^on_/, '')
#           can_add_listener?(event) || can_handle_drag_observation_request?(observation_request) || can_handle_drop_observation_request?(observation_request)
    true # TODO filter by valid listeners only in the future
  end
end

#clear_css_classesObject



228
229
230
# File 'lib/glimmer/swt/widget_proxy.rb', line 228

def clear_css_classes
  css_classes.each {|css_class| remove_css_class(css_class)}
end

#content(&block) ⇒ Object



185
186
187
# File 'lib/glimmer/swt/widget_proxy.rb', line 185

def content(&block)
  Glimmer::DSL::Engine.add_content(self, Glimmer::DSL::Opal::WidgetExpression.new, &block)
end

#css_classesObject



109
110
111
# File 'lib/glimmer/swt/widget_proxy.rb', line 109

def css_classes
  dom_element.attr('class').to_s.split
end

#disposeObject



113
114
115
# File 'lib/glimmer/swt/widget_proxy.rb', line 113

def dispose
  Document.find(path).remove
end

#dom_elementObject



236
237
238
# File 'lib/glimmer/swt/widget_proxy.rb', line 236

def dom_element
  Document.find(path)
end

#elementObject

Root element representing widget. Must be overridden by subclasses if different from div



122
123
124
# File 'lib/glimmer/swt/widget_proxy.rb', line 122

def element
  'div'
end

#handle_observation_request(keyword, &event_listener) ⇒ Object



279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
# File 'lib/glimmer/swt/widget_proxy.rb', line 279

def handle_observation_request(keyword, &event_listener)        
  return unless observation_request_to_event_mapping.keys.include?(keyword)
  @observation_requests ||= {}
  @observation_requests[keyword] ||= Set.new
  event = nil
  delegate = nil
  [observation_request_to_event_mapping[keyword]].flatten.each do |mapping|          
    @observation_requests[keyword] << event_listener
    event = mapping[:event]
    event_handler = mapping[:event_handler]
    potential_event_listener = event_handler&.call(event_listener)
    event_listener = potential_event_listener || event_listener
    delegate = listener_dom_element.on(event, &event_listener)
  end
  # TODO update code below for new WidgetProxy API
  EventListenerProxy.new(element_proxy: self, event: event, selector: selector, delegate: delegate)
end

#has_style?(symbol) ⇒ Boolean

Returns:

  • (Boolean)


232
233
234
# File 'lib/glimmer/swt/widget_proxy.rb', line 232

def has_style?(symbol)
  @args.include?(symbol) # not a very solid implementation. Bring SWT constants eventually
end

#idObject



198
199
200
# File 'lib/glimmer/swt/widget_proxy.rb', line 198

def id
  @id ||= "#{name}-#{WidgetProxy.next_id_number_for(name)}"
end

#id=(value) ⇒ Object

Sets id explicitly. Useful in cases of wanting to maintain a stable id



203
204
205
# File 'lib/glimmer/swt/widget_proxy.rb', line 203

def id=(value)
  @id = value
end

#listener_dom_elementObject



262
263
264
# File 'lib/glimmer/swt/widget_proxy.rb', line 262

def listener_dom_element
  Document.find(listener_path)      
end

#listener_pathObject



258
259
260
# File 'lib/glimmer/swt/widget_proxy.rb', line 258

def listener_path
  path
end

#nameObject



194
195
196
# File 'lib/glimmer/swt/widget_proxy.rb', line 194

def name
  self.class.name.split('::').last.underscore.sub(/_proxy$/, '').gsub('_', '-')
end

#observation_request_to_event_mappingObject

Subclasses must override with their own mappings



190
191
192
# File 'lib/glimmer/swt/widget_proxy.rb', line 190

def observation_request_to_event_mapping
  {}
end

#parent_dom_elementObject



254
255
256
# File 'lib/glimmer/swt/widget_proxy.rb', line 254

def parent_dom_element
  Document.find(parent_path)
end

#parent_pathObject



154
155
156
# File 'lib/glimmer/swt/widget_proxy.rb', line 154

def parent_path
  @parent.path
end

#property_type_convertersObject



322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
# File 'lib/glimmer/swt/widget_proxy.rb', line 322

def property_type_converters
  color_converter = lambda do |value|
    if value.is_a?(Symbol) || value.is_a?(String)
      ColorProxy.new(value)
    else
      value
    end
  end
  @property_type_converters ||= {
    :background => color_converter,
#           :background_image => lambda do |value|
#             if value.is_a?(String)
#               if value.start_with?('uri:classloader')
#                 value = value.sub(/^uri\:classloader\:\//, '')
#                 object = java.lang.Object.new
#                 value = object.java_class.resource_as_stream(value)
#                 value = java.io.BufferedInputStream.new(value)
#               end
#               image_data = ImageData.new(value)
#               on_event_Resize do |resize_event|
#                 new_image_data = image_data.scaledTo(@swt_widget.getSize.x, @swt_widget.getSize.y)
#                 @swt_widget.getBackgroundImage&.dispose
#                 @swt_widget.setBackgroundImage(Image.new(@swt_widget.getDisplay, new_image_data))
#               end
#               Image.new(@swt_widget.getDisplay, image_data)
#             else
#               value
#             end
#           end,
    :foreground => color_converter,
#           :font => lambda do |value|
#             if value.is_a?(Hash)
#               font_properties = value
#               FontProxy.new(self, font_properties).swt_font
#             else
#               value
#             end
#           end,
#           :items => lambda do |value|
#             value.to_java :string
#           end,
    :text => lambda do |value|
#             if swt_widget.is_a?(Browser)
#               value.to_s
#             else
        value.to_s
#             end
    end,
#           :visible => lambda do |value|
#             !!value
#           end,
  }      
end

#remove_css_class(css_class) ⇒ Object



220
221
222
# File 'lib/glimmer/swt/widget_proxy.rb', line 220

def remove_css_class(css_class)
  dom_element.remove_class(css_class)
end

#remove_css_classes(css_classes_to_remove) ⇒ Object



224
225
226
# File 'lib/glimmer/swt/widget_proxy.rb', line 224

def remove_css_classes(css_classes_to_remove)
  css_classes_to_remove.each {|css_class| remove_css_class(css_class)}
end

#renderObject Also known as: redraw



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/glimmer/swt/widget_proxy.rb', line 158

def render
  old_element = dom_element
  brand_new = @dom.nil? || old_element.empty?
  build_dom
  if brand_new
    Document.find(parent_path).append(@dom)
  else
    old_element.replace_with(@dom)
  end
  @observation_requests&.clone&.each do |keyword, event_listener_set|
    event_listener_set.each do |event_listener|
      @observation_requests[keyword].delete(event_listener)
      handle_observation_request(keyword, &event_listener)
    end
  end
  children.each do |child|
    child.render
  end        
end

#selectorObject

Subclasses can override with their own selector



208
209
210
# File 'lib/glimmer/swt/widget_proxy.rb', line 208

def selector
  "#{name}##{id}"
end

#set_attribute(attribute_name, *args) ⇒ Object



305
306
307
308
# File 'lib/glimmer/swt/widget_proxy.rb', line 305

def set_attribute(attribute_name, *args)
  apply_property_type_converters(attribute_name, args)
  super(attribute_name, *args) # PropertyOwner
end

#style_elementObject



240
241
242
243
244
245
246
247
248
249
250
251
252
# File 'lib/glimmer/swt/widget_proxy.rb', line 240

def style_element
  style_element_id = "#{id}-style"
  style_element_selector = "style##{style_element_id}"
  element = dom_element.find(style_element_selector)
  if element.empty?
    new_element = Element.new(:style)
    new_element.attr('id', style_element_id)
    new_element.attr('class', "#{name.gsub('_', '-')}-instance-style widget-instance-style")
    dom_element.prepend(new_element)
    element = dom_element.find(style_element_selector)
  end
  element
end

#widget_property_listener_installersObject



376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
# File 'lib/glimmer/swt/widget_proxy.rb', line 376

def widget_property_listener_installers
  @swt_widget_property_listener_installers ||= {
#           WidgetProxy => {
#             :focus => lambda do |observer|
#               on_focus_gained { |focus_event|
#                 observer.call(true)
#               }
#               on_focus_lost { |focus_event|
#                 observer.call(false)
#               }
#             end,
#           },
    TextProxy => {
      :text => lambda do |observer|
        on_modify_text { |modify_event|
          observer.call(text)
        }
      end,
#             :caret_position => lambda do |observer|
#               on_event_keydown { |event|
#                 observer.call(getCaretPosition)
#               }
#               on_event_keyup { |event|
#                 observer.call(getCaretPosition)
#               }
#               on_event_mousedown { |event|
#                 observer.call(getCaretPosition)
#               }
#               on_event_mouseup { |event|
#                 observer.call(getCaretPosition)
#               }
#             end,
#             :selection => lambda do |observer|
#               on_event_keydown { |event|
#                 observer.call(getSelection)
#               }
#               on_event_keyup { |event|
#                 observer.call(getSelection)
#               }
#               on_event_mousedown { |event|
#                 observer.call(getSelection)
#               }
#               on_event_mouseup { |event|
#                 observer.call(getSelection)
#               }
#             end,
#             :selection_count => lambda do |observer|
#               on_event_keydown { |event|
#                 observer.call(getSelectionCount)
#               }
#               on_event_keyup { |event|
#                 observer.call(getSelectionCount)
#               }
#               on_event_mousedown { |event|
#                 observer.call(getSelectionCount)
#               }
#               on_event_mouseup { |event|
#                 observer.call(getSelectionCount)
#               }
#             end,
#             :top_index => lambda do |observer|
#               @last_top_index = getTopIndex
#               on_paint_control { |event|
#                 if getTopIndex != @last_top_index
#                   @last_top_index = getTopIndex
#                   observer.call(@last_top_index)
#                 end
#               }
#             end,
    },
#           Java::OrgEclipseSwtCustom::StyledText => {
#             :text => lambda do |observer|
#               on_modify_text { |modify_event|
#                 observer.call(getText)
#               }
#             end,
#           },
#           Button => { #radio?
#             :selection => lambda do |observer|
#               on_widget_selected { |selection_event|
#                 observer.call(getSelection)
#               }
#             end
#           },
#           Java::OrgEclipseSwtWidgets::MenuItem => {
#             :selection => lambda do |observer|
#               on_widget_selected { |selection_event|
#                 observer.call(getSelection)
#               }
#             end
#           },
#           Java::OrgEclipseSwtWidgets::Spinner => {
#             :selection => lambda do |observer|
#               on_widget_selected { |selection_event|
#                 observer.call(getSelection)
#               }
#             end
#           },
  }
end