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, block) ⇒ WidgetProxy

Returns a new instance of WidgetProxy.



107
108
109
110
111
112
113
114
115
116
# File 'lib/glimmer/swt/widget_proxy.rb', line 107

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

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object



698
699
700
701
702
703
704
# File 'lib/glimmer/swt/widget_proxy.rb', line 698

def method_missing(method, *args, &block)
  if method.to_s.start_with?('on_')
    handle_observation_request(method, block)
  else
    super(method, *args, &block)
  end
end

Instance Attribute Details

#argsObject (readonly)

Returns the value of attribute args.



34
35
36
# File 'lib/glimmer/swt/widget_proxy.rb', line 34

def args
  @args
end

#backgroundObject

Returns the value of attribute background.



34
35
36
# File 'lib/glimmer/swt/widget_proxy.rb', line 34

def background
  @background
end

#childrenObject (readonly)

Returns the value of attribute children.



34
35
36
# File 'lib/glimmer/swt/widget_proxy.rb', line 34

def children
  @children
end

#disposed?Object (readonly) Also known as: isDisposed, is_disposed

Returns the value of attribute disposed?.



34
35
36
# File 'lib/glimmer/swt/widget_proxy.rb', line 34

def disposed?
  @disposed?
end

#enabledObject

Returns the value of attribute enabled.



34
35
36
# File 'lib/glimmer/swt/widget_proxy.rb', line 34

def enabled
  @enabled
end

#focusObject

Returns the value of attribute focus.



34
35
36
# File 'lib/glimmer/swt/widget_proxy.rb', line 34

def focus
  @focus
end

#fontObject

Returns the value of attribute font.



34
35
36
# File 'lib/glimmer/swt/widget_proxy.rb', line 34

def font
  @font
end

#foregroundObject

Returns the value of attribute foreground.



34
35
36
# File 'lib/glimmer/swt/widget_proxy.rb', line 34

def foreground
  @foreground
end

Returns the value of attribute menu.



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

def menu
  @menu
end

Returns the value of attribute menu_requested.



34
35
36
# File 'lib/glimmer/swt/widget_proxy.rb', line 34

def menu_requested
  @menu_requested
end

#parentObject (readonly)

Returns the value of attribute parent.



34
35
36
# File 'lib/glimmer/swt/widget_proxy.rb', line 34

def parent
  @parent
end

#pathObject (readonly)

Returns the value of attribute path.



34
35
36
# File 'lib/glimmer/swt/widget_proxy.rb', line 34

def path
  @path
end

#renderedObject (readonly) Also known as: rendered?

Returns the value of attribute rendered.



34
35
36
# File 'lib/glimmer/swt/widget_proxy.rb', line 34

def rendered
  @rendered
end

Class Method Details

.for(keyword, parent, args, block) ⇒ Object

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



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

def for(keyword, parent, args, block)
  the_widget_class = widget_class(keyword)
  the_widget_class.respond_to?(:create) ? the_widget_class.create(keyword, parent, args, block) : the_widget_class.new(parent, args, block)
end

.max_id_number_for(name) ⇒ Object



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

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

.max_id_numbersObject



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

def max_id_numbers
  @max_id_numbers ||= reset_max_id_numbers!
end

.next_id_number_for(name) ⇒ Object



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

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

.reset_max_id_numbers!Object



73
74
75
# File 'lib/glimmer/swt/widget_proxy.rb', line 73

def reset_max_id_numbers!
  @max_id_numbers = {}
end

.underscored_widget_name(widget_proxy) ⇒ Object



77
78
79
# File 'lib/glimmer/swt/widget_proxy.rb', line 77

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

.widget_class(keyword) ⇒ Object



48
49
50
51
52
53
54
55
# File 'lib/glimmer/swt/widget_proxy.rb', line 48

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)


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

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

Instance Method Details

#add_content_on_render(&content_block) ⇒ Object



278
279
280
281
282
283
284
# File 'lib/glimmer/swt/widget_proxy.rb', line 278

def add_content_on_render(&content_block)
  if rendered?
    content_block.call
  else
    content_on_render_blocks << content_block
  end
end

#add_css_class(css_class) ⇒ Object



575
576
577
# File 'lib/glimmer/swt/widget_proxy.rb', line 575

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

#add_css_classes(css_classes_to_add) ⇒ Object



579
580
581
# File 'lib/glimmer/swt/widget_proxy.rb', line 579

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



685
686
687
688
689
690
691
# File 'lib/glimmer/swt/widget_proxy.rb', line 685

def add_observer(observer, property_name)
  property_listener_installers = self.class&.ancestors&.to_a.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



711
712
713
714
715
716
717
718
719
720
721
# File 'lib/glimmer/swt/widget_proxy.rb', line 711

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_dom(layout: true) ⇒ Object



286
287
288
289
290
291
292
# File 'lib/glimmer/swt/widget_proxy.rb', line 286

def build_dom(layout: true)
  # TODO consider passing parent element instead and having table item include a table cell widget only for opal
  @dom = nil
  @dom = dom
  @dom = @parent.layout.dom(@dom) if @parent.respond_to?(:layout) && @parent.layout
  @dom
end

#can_handle_observation_request?(observation_request) ⇒ Boolean

Returns:

  • (Boolean)


636
637
638
639
640
641
642
643
644
645
646
647
# File 'lib/glimmer/swt/widget_proxy.rb', line 636

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



591
592
593
# File 'lib/glimmer/swt/widget_proxy.rb', line 591

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

#content(&block) ⇒ Object



294
295
296
# File 'lib/glimmer/swt/widget_proxy.rb', line 294

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

#content_on_render_blocksObject



270
271
272
# File 'lib/glimmer/swt/widget_proxy.rb', line 270

def content_on_render_blocks
  @content_on_render_blocks ||= []
end

#css_classesObject



158
159
160
# File 'lib/glimmer/swt/widget_proxy.rb', line 158

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

#default_observation_request_to_event_mappingObject



307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
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
375
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
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
# File 'lib/glimmer/swt/widget_proxy.rb', line 307

def default_observation_request_to_event_mapping
  mouse_event_handler = -> (event_listener) {
    -> (event) {
      # TODO generalize this solution to all widgets that support key presses
      # TODO support event.location once DOM3 is supported by opal-jquery
      event.define_singleton_method(:button, &event.method(:which))
      event.define_singleton_method(:count) {1} # TODO support double-click count of 2 in the future by using ondblclick
      event.define_singleton_method(:x, &event.method(:page_x))
      event.define_singleton_method(:y, &event.method(:page_y))
      doit = true
      event.define_singleton_method(:doit=) do |value|
        doit = value
      end
      event.define_singleton_method(:doit) { doit }
      
      if event.which == 1
#               event.prevent # TODO consider if this is needed
        event_listener.call(event)
      end
      
      # TODO Imlement doit properly for all different kinds of events
#             unless doit
#               event.prevent
#               event.stop
#               event.stop_immediate
#             end
    }
  }
  context_menu_handler = -> (event_listener) {
    -> (event) {
      # TODO generalize this solution to all widgets that support key presses
      # TODO support event.location once DOM3 is supported by opal-jquery
      event.define_singleton_method(:button, &event.method(:which))
      event.define_singleton_method(:count) {1} # TODO support double-click count of 2 in the future by using ondblclick
      event.define_singleton_method(:x, &event.method(:page_x))
      event.define_singleton_method(:y, &event.method(:page_y))
      doit = true
      event.define_singleton_method(:doit=) do |value|
        doit = value
      end
      event.define_singleton_method(:doit) { doit }
      
      if event.which == 3
        event.prevent
        event_listener.call(event)
      end
      
      # TODO Imlement doit properly for all different kinds of events
#             unless doit
#               event.prevent
#               event.stop
#               event.stop_immediate
#             end
    }
  }
  {
    'on_focus_gained' => {
      event: 'focus',
    },
    'on_focus_lost' => {
      event: 'blur',
    },
    'on_mouse_up' => [
      {
        event: 'mouseup',
        event_handler: mouse_event_handler,
      },
      {
        event: 'contextmenu',
        event_handler: context_menu_handler,
      },
    ],
    'on_mouse_down' => [
      {
        event: 'mousedown',
        event_handler: mouse_event_handler,
      },
      {
        event: 'contextmenu',
        event_handler: context_menu_handler,
      },
    ],
    'on_swt_mouseup' => [
      {
        event: 'mouseup',
        event_handler: mouse_event_handler,
      },
      {
        event: 'contextmenu',
        event_handler: context_menu_handler,
      },
    ],
    'on_swt_mousedown' => [
      {
        event: 'mousedown',
        event_handler: mouse_event_handler,
      },
      {
        event: 'contextmenu',
        event_handler: context_menu_handler,
      },
    ],
    'on_key_pressed' => {
      event: 'keypress',
      event_handler: -> (event_listener) {
        -> (event) {
          # TODO generalize this solution to all widgets that support key presses
          # TODO support event.location once DOM3 is supported by opal-jquery
          event.define_singleton_method(:keyCode) {event.which}
          event.define_singleton_method(:key_code, &event.method(:keyCode))
          event.define_singleton_method(:character) {event.which.chr}
          event.define_singleton_method(:stateMask) do
            state_mask = 0
            state_mask |= SWTProxy[:alt] if event.alt_key
            state_mask |= SWTProxy[:ctrl] if event.ctrl_key
            state_mask |= SWTProxy[:shift] if event.shift_key
            state_mask |= SWTProxy[:command] if event.meta_key
            state_mask
          end
          event.define_singleton_method(:state_mask, &event.method(:stateMask))
          doit = true
          event.define_singleton_method(:doit=) do |value|
            doit = value
          end
          event.define_singleton_method(:doit) { doit }
          event_listener.call(event)
          
            # TODO Fix doit false, it's not stopping input
          unless doit
            event.prevent
            event.prevent_default
            event.stop_propagation
            event.stop_immediate_propagation
          end
          
          doit
        }
      }          },
    'on_key_released' => {
      event: 'keydown',
      event_handler: -> (event_listener) {
        -> (event) {
          # TODO generalize this solution to all widgets that support key presses
          # TODO support event.location once DOM3 is supported by opal-jquery
          event.define_singleton_method(:keyCode) {event.which}
          event.define_singleton_method(:key_code, &event.method(:keyCode))
          event.define_singleton_method(:character) {event.which.chr}
          event.define_singleton_method(:stateMask) do
            state_mask = 0
            state_mask |= SWTProxy[:alt] if event.alt_key
            state_mask |= SWTProxy[:ctrl] if event.ctrl_key
            state_mask |= SWTProxy[:shift] if event.shift_key
            state_mask |= SWTProxy[:command] if event.meta_key
            state_mask
          end
          event.define_singleton_method(:state_mask, &event.method(:stateMask))
          doit = true
          event.define_singleton_method(:doit=) do |value|
            doit = value
          end
          event.define_singleton_method(:doit) { doit }
          event_listener.call(event)
          
            # TODO Fix doit false, it's not stopping input
          unless doit
            event.prevent
            event.prevent_default
            event.stop_propagation
            event.stop_immediate_propagation
          end
          
          doit
        }
      }          },
    'on_swt_keydown' => {
      event: 'keypress',
      event_handler: -> (event_listener) {
        -> (event) {
          # TODO generalize this solution to all widgets that support key presses
          # TODO support event.location once DOM3 is supported by opal-jquery
          event.define_singleton_method(:keyCode) {event.which}
          event.define_singleton_method(:key_code, &event.method(:keyCode))
          event.define_singleton_method(:character) {event.which.chr}
          event.define_singleton_method(:stateMask) do
            state_mask = 0
            state_mask |= SWTProxy[:alt] if event.alt_key
            state_mask |= SWTProxy[:ctrl] if event.ctrl_key
            state_mask |= SWTProxy[:shift] if event.shift_key
            state_mask |= SWTProxy[:command] if event.meta_key
            state_mask
          end
          event.define_singleton_method(:state_mask, &event.method(:stateMask))
          doit = true
          event.define_singleton_method(:doit=) do |value|
            doit = value
          end
          event.define_singleton_method(:doit) { doit }
          event_listener.call(event)
          
            # TODO Fix doit false, it's not stopping input
          unless doit
            event.prevent
            event.prevent_default
            event.stop_propagation
            event.stop_immediate_propagation
          end
          
          doit
        }
      }          },
    'on_swt_keyup' => {
      event: 'keydown',
      event_handler: -> (event_listener) {
        -> (event) {
          # TODO generalize this solution to all widgets that support key presses
          # TODO support event.location once DOM3 is supported by opal-jquery
          event.define_singleton_method(:keyCode) {event.which}
          event.define_singleton_method(:key_code, &event.method(:keyCode))
          event.define_singleton_method(:character) {event.which.chr}
          event.define_singleton_method(:stateMask) do
            state_mask = 0
            state_mask |= SWTProxy[:alt] if event.alt_key
            state_mask |= SWTProxy[:ctrl] if event.ctrl_key
            state_mask |= SWTProxy[:shift] if event.shift_key
            state_mask |= SWTProxy[:command] if event.meta_key
            state_mask
          end
          event.define_singleton_method(:state_mask, &event.method(:stateMask))
          doit = true
          event.define_singleton_method(:doit=) do |value|
            doit = value
          end
          event.define_singleton_method(:doit) { doit }
          event_listener.call(event)
          
            # TODO Fix doit false, it's not stopping input
          unless doit
            event.prevent
            event.prevent_default
            event.stop_propagation
            event.stop_immediate_propagation
          end
          
          doit
        }
      }
    },
  }
end

#disposeObject



162
163
164
165
166
167
168
169
# File 'lib/glimmer/swt/widget_proxy.rb', line 162

def dispose
  remove_all_listeners
  Document.find(path).remove
  parent&.post_dispose_child(self)
  # TODO fire on_widget_disposed listener
#         children.each(:dispose) # TODO enable this safely
  @disposed = true
end

#dom_elementObject



599
600
601
602
# File 'lib/glimmer/swt/widget_proxy.rb', line 599

def dom_element
  # TODO consider making this pick an element in relation to its parent, allowing unhooked dom elements to be built if needed (unhooked to the visible page dom)
  Document.find(path)
end

#effective_observation_request_to_event_mappingObject



303
304
305
# File 'lib/glimmer/swt/widget_proxy.rb', line 303

def effective_observation_request_to_event_mapping
  default_observation_request_to_event_mapping.merge(observation_request_to_event_mapping)
end

#elementObject

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



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

def element
  'div'
end

#event_listener_proxiesObject



632
633
634
# File 'lib/glimmer/swt/widget_proxy.rb', line 632

def event_listener_proxies
  @event_listener_proxies ||= []
end

#get_data(key = nil) ⇒ Object Also known as: getData, data



152
153
154
# File 'lib/glimmer/swt/widget_proxy.rb', line 152

def get_data(key=nil)
  @data[key]
end

#handle_observation_request(keyword, original_event_listener) ⇒ Object



649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
# File 'lib/glimmer/swt/widget_proxy.rb', line 649

def handle_observation_request(keyword, original_event_listener)
  return unless effective_observation_request_to_event_mapping.keys.include?(keyword)
  event = nil
  delegate = nil
  effective_observation_request_to_event_mapping[keyword].to_collection.each do |mapping|
    observation_requests[keyword] ||= Set.new
    observation_requests[keyword] << original_event_listener
    event = mapping[:event]
    event_handler = mapping[:event_handler]
    event_element_css_selector = mapping[:event_element_css_selector]
    potential_event_listener = event_handler&.call(original_event_listener)
    event_listener = potential_event_listener || original_event_listener
    async_event_listener = lambda do |event|
      # TODO look into the issue with using async::task.new here. maybe put it in event listener (like not being able to call preventDefault or return false successfully )
      # maybe consider pushing inside the widget classes instead where needed only or implement universal doit support correctly to bypass this issue
#             Async::Task.new do
        event_listener.call(event)
#             end
    end
    the_listener_dom_element = event_element_css_selector ? Element[event_element_css_selector] : listener_dom_element
    unless the_listener_dom_element.empty?
      the_listener_dom_element.on(event, &async_event_listener)
      # TODO ensure uniqueness of insertion (perhaps adding equals/hash method to event listener proxy)
      
      event_listener_proxies << EventListenerProxy.new(element_proxy: self, selector: selector, dom_element: the_listener_dom_element, event: event, listener: async_event_listener, original_event_listener: original_event_listener)
    end
  end
end

#has_style?(symbol) ⇒ Boolean

Returns:

  • (Boolean)


595
596
597
# File 'lib/glimmer/swt/widget_proxy.rb', line 595

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

#idObject



561
562
563
# File 'lib/glimmer/swt/widget_proxy.rb', line 561

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



566
567
568
# File 'lib/glimmer/swt/widget_proxy.rb', line 566

def id=(value)
  @id = value
end

#layout(*args) ⇒ Object



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

def layout(*args)
  # No Op (just a shim) TODO consider if it should be implemented
end

#listener_dom_elementObject



624
625
626
# File 'lib/glimmer/swt/widget_proxy.rb', line 624

def listener_dom_element
  Document.find(listener_path)
end

#listener_pathObject



620
621
622
# File 'lib/glimmer/swt/widget_proxy.rb', line 620

def listener_path
  path
end

#nameObject



557
558
559
# File 'lib/glimmer/swt/widget_proxy.rb', line 557

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

#observation_request_to_event_mappingObject

Subclasses must override with their own mappings



299
300
301
# File 'lib/glimmer/swt/widget_proxy.rb', line 299

def observation_request_to_event_mapping
  {}
end

#observation_requestsObject



628
629
630
# File 'lib/glimmer/swt/widget_proxy.rb', line 628

def observation_requests
  @observation_requests ||= {}
end

#pack(*args) ⇒ Object



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

def pack(*args)
  # No Op (just a shim) TODO consider if it should be implemented
end

#parent_dom_elementObject



242
243
244
# File 'lib/glimmer/swt/widget_proxy.rb', line 242

def parent_dom_element
  Document.find(parent_path)
end

#parent_pathObject



238
239
240
# File 'lib/glimmer/swt/widget_proxy.rb', line 238

def parent_path
  @parent.path
end

#post_add_contentObject

Executes at the closing of a parent widget curly braces after all children/properties have been added/set



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/glimmer/swt/widget_proxy.rb', line 130

def post_add_content
  if !menu.nil? && !is_a?(MenuProxy) && !is_a?(MenuItemProxy)
    on_mouse_down { |mouse_event|
      if mouse_event.button == 3 # right-click
        @menu_requested = true
        dom_element.css('position', 'relative')
        menu&.render
        menu.dom_element.css('position', 'absolute')
        menu.dom_element.css('left', mouse_event.x - parent.layout&.margin_width.to_i) # TODO - parent.layout&.margin_left.to_i)
        menu.dom_element.css('top', mouse_event.y - parent.layout&.margin_height.to_i - 5) # TODO - parent.layout&.margin_top.to_i)
        @menu_requested = false
      end
    }
  end
end

#post_dispose_child(child) ⇒ Object

Executes for the parent of a child that just got disposed



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

def post_dispose_child(child)
  @children&.delete(child)
end

#post_initialize_child(child) ⇒ Object

Executes for the parent of a child that just got added



119
120
121
122
# File 'lib/glimmer/swt/widget_proxy.rb', line 119

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

#property_type_convertersObject



723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
# File 'lib/glimmer/swt/widget_proxy.rb', line 723

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,
    :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_all_listenersObject



171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/glimmer/swt/widget_proxy.rb', line 171

def remove_all_listeners
  effective_observation_request_to_event_mapping.keys.each do |keyword|
    effective_observation_request_to_event_mapping[keyword].to_collection.each do |mapping|
      observation_requests[keyword].to_a.each do |event_listener|
        event = mapping[:event]
        event_handler = mapping[:event_handler]
        event_element_css_selector = mapping[:event_element_css_selector]
        the_listener_dom_element = event_element_css_selector ? Element[event_element_css_selector] : listener_dom_element
        the_listener_dom_element.off(event)
        # TODO improve to precisely remove the listeners that were added, no more no less. (or use the event_listener_proxies method instead or in collaboration)
      end
    end
  end
end

#remove_css_class(css_class) ⇒ Object



583
584
585
# File 'lib/glimmer/swt/widget_proxy.rb', line 583

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

#remove_css_classes(css_classes_to_remove) ⇒ Object



587
588
589
# File 'lib/glimmer/swt/widget_proxy.rb', line 587

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

#remove_event_listener_proxiesObject



678
679
680
681
682
683
# File 'lib/glimmer/swt/widget_proxy.rb', line 678

def remove_event_listener_proxies
  event_listener_proxies.each do |event_listener_proxy|
    event_listener_proxy.unregister
  end
  event_listener_proxies.clear
end

#render(custom_parent_dom_element: nil, brand_new: false) ⇒ Object Also known as: redraw



246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
# File 'lib/glimmer/swt/widget_proxy.rb', line 246

def render(custom_parent_dom_element: nil, brand_new: false)
  the_parent_dom_element = custom_parent_dom_element || parent_dom_element
  old_element = dom_element
  brand_new = @dom.nil? || old_element.empty? || brand_new
  build_dom(layout: !custom_parent_dom_element) # TODO handle custom parent layout by passing parent instead of parent dom element
  if brand_new
    the_parent_dom_element.append(@dom) # TODO make a method attach to allow subclasses to override if needed
  else
    old_element.replace_with(@dom)
    old_element.replace_with(@dom)
  end
  observation_requests&.each do |keyword, event_listener_set|
    event_listener_set.each do |event_listener|
      handle_observation_request(keyword, event_listener)
    end
  end
  children.each do |child|
    child.render
  end
  @rendered = true
  content_on_render_blocks.each { |content_block| content(&content_block) } unless skip_content_on_render_blocks?
end

#selectorObject

Subclasses can override with their own selector



571
572
573
# File 'lib/glimmer/swt/widget_proxy.rb', line 571

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

#set_attribute(attribute_name, *args) ⇒ Object



693
694
695
696
# File 'lib/glimmer/swt/widget_proxy.rb', line 693

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

#set_data(key = nil, value) ⇒ Object Also known as: setData, data=



146
147
148
# File 'lib/glimmer/swt/widget_proxy.rb', line 146

def set_data(key=nil, value)
  @data[key] = value
end

#set_focusObject Also known as: setFocus



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

def set_focus
  self.focus = true
end

#skip_content_on_render_blocks?Boolean

Returns:

  • (Boolean)


274
275
276
# File 'lib/glimmer/swt/widget_proxy.rb', line 274

def skip_content_on_render_blocks?
  false
end

#style_elementObject

TODO consider adding a default #dom method implementation for the common case, automatically relying on #element and other methods to build the dom html



606
607
608
609
610
611
612
613
614
615
616
617
618
# File 'lib/glimmer/swt/widget_proxy.rb', line 606

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

#swt_widgetObject



706
707
708
709
# File 'lib/glimmer/swt/widget_proxy.rb', line 706

def swt_widget
  # only added for compatibility/adaptibility with Glimmer DSL for SWT
  self
end

#widget_property_listener_installersObject



774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
# File 'lib/glimmer/swt/widget_proxy.rb', line 774

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,
#           },
    DateTimeProxy => {
      :date_time => lambda do |observer|
        on_widget_selected { |selection_event|
          observer.call(date_time)
        }
      end
    },
    RadioProxy => { #radio?
      :selection => lambda do |observer|
        on_widget_selected { |selection_event|
          observer.call(selection)
        }
      end
    },
    TableProxy => {
      :selection => lambda do |observer|
        on_widget_selected { |selection_event|
          observer.call(selection_event.table_item.get_data)  # TODO ensure selection doesn't conflict with editing
        }
      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