glimmer-dsl-opal 0.25.4 → 0.26.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +24 -1
  3. data/README.md +40 -5
  4. data/VERSION +1 -1
  5. data/lib/glimmer/dsl/opal/menu_expression.rb +0 -3
  6. data/lib/glimmer/swt/combo_proxy.rb +0 -39
  7. data/lib/glimmer/swt/control_editor.rb +2 -2
  8. data/lib/glimmer/swt/date_time_proxy.rb +0 -37
  9. data/lib/glimmer/swt/dialog_proxy.rb +11 -4
  10. data/lib/glimmer/swt/display_proxy.rb +1 -83
  11. data/lib/glimmer/swt/shell_proxy.rb +28 -1
  12. data/lib/glimmer/swt/spinner_proxy.rb +0 -39
  13. data/lib/glimmer/swt/table_item_proxy.rb +0 -20
  14. data/lib/glimmer/swt/table_proxy.rb +4 -0
  15. data/lib/glimmer/swt/text_proxy.rb +1 -39
  16. data/lib/glimmer/swt/widget_proxy.rb +177 -58
  17. data/lib/glimmer/ui/custom_shell.rb +2 -0
  18. data/lib/glimmer/ui/custom_widget.rb +2 -0
  19. data/lib/glimmer-dsl-opal/samples/elaborate/tetris/model/block.rb +48 -0
  20. data/lib/glimmer-dsl-opal/samples/elaborate/tetris/model/game.rb +275 -0
  21. data/lib/glimmer-dsl-opal/samples/elaborate/tetris/model/past_game.rb +39 -0
  22. data/lib/glimmer-dsl-opal/samples/elaborate/tetris/model/tetromino.rb +329 -0
  23. data/lib/glimmer-dsl-opal/samples/elaborate/tetris/view/block.rb +36 -0
  24. data/lib/glimmer-dsl-opal/samples/elaborate/tetris/view/high_score_dialog.rb +122 -0
  25. data/lib/glimmer-dsl-opal/samples/elaborate/tetris/view/playfield.rb +56 -0
  26. data/lib/glimmer-dsl-opal/samples/elaborate/tetris/view/score_lane.rb +83 -0
  27. data/lib/glimmer-dsl-opal/samples/elaborate/tetris/view/tetris_menu_bar.rb +136 -0
  28. data/lib/glimmer-dsl-opal/samples/elaborate/tetris.rb +155 -0
  29. data/lib/glimmer-dsl-opal.rb +1 -0
  30. metadata +12 -2
@@ -153,45 +153,6 @@ module Glimmer
153
153
  }
154
154
  }
155
155
  },
156
- 'on_key_pressed' => {
157
- event: 'keydown',
158
- event_handler: -> (event_listener) {
159
- -> (event) {
160
- @last_key_pressed_event = event
161
- self.text = event.target.value
162
- # TODO generalize this solution to all widgets that support key presses
163
- # TODO support event.location once DOM3 is supported by opal-jquery
164
- event.define_singleton_method(:keyCode) {event.which}
165
- event.define_singleton_method(:key_code, &event.method(:keyCode))
166
- event.define_singleton_method(:character) {event.which.chr}
167
- event.define_singleton_method(:stateMask) do
168
- state_mask = 0
169
- state_mask |= SWTProxy[:alt] if event.alt_key
170
- state_mask |= SWTProxy[:ctrl] if event.ctrl_key
171
- state_mask |= SWTProxy[:shift] if event.shift_key
172
- state_mask |= SWTProxy[:command] if event.meta_key
173
- state_mask
174
- end
175
- event.define_singleton_method(:state_mask, &event.method(:stateMask))
176
- doit = true
177
- event.define_singleton_method(:doit=) do |value|
178
- doit = value
179
- end
180
- event.define_singleton_method(:doit) { doit }
181
- event_listener.call(event)
182
-
183
- # TODO Fix doit false, it's not stopping input
184
- unless doit
185
- event.prevent
186
- event.prevent_default
187
- event.stop_propagation
188
- event.stop_immediate_propagation
189
- end
190
-
191
- doit
192
- }
193
- }
194
- },
195
156
  }
196
157
  end
197
158
 
@@ -59,26 +59,6 @@ module Glimmer
59
59
  @text_array ||= []
60
60
  end
61
61
 
62
- def get_data(key = nil)
63
- if key.nil?
64
- @data
65
- else
66
- data_hash[key]
67
- end
68
- end
69
-
70
- def set_data(key = nil, data_value)
71
- if key.nil?
72
- @data = data_value
73
- else
74
- data_hash[key] = data_value
75
- end
76
- end
77
-
78
- def data_hash
79
- @data_hash ||= {}
80
- end
81
-
82
62
  def parent_path
83
63
  parent.items_path
84
64
  end
@@ -61,6 +61,10 @@ module Glimmer
61
61
  on_focus_lost {
62
62
  table_proxy.finish_edit!
63
63
  }
64
+ on_modify_text do |event|
65
+ # No Op, just record @text changes on key up
66
+ # TODO find a better solution than this in the future
67
+ end
64
68
  on_key_pressed { |key_event|
65
69
  if key_event.keyCode == swt(:cr)
66
70
  table_proxy.finish_edit!
@@ -21,6 +21,7 @@ module Glimmer
21
21
  event_handler: -> (event_listener) {
22
22
  -> (event) {
23
23
  # TODO consider unifying this event handler with on_key_pressed by relying on its result instead of hooking another keyup event
24
+ # TODO add all attributes for on_modify_text modify event
24
25
  if @last_key_pressed_event.nil? || @last_key_pressed_event.doit
25
26
  @text = event.target.value
26
27
  event_listener.call(event)
@@ -34,45 +35,6 @@ module Glimmer
34
35
  }
35
36
  }
36
37
  },
37
- 'on_key_pressed' => {
38
- event: 'keydown',
39
- event_handler: -> (event_listener) {
40
- -> (event) {
41
- @last_key_pressed_event = event
42
- @text = event.target.value
43
- # TODO generalize this solution to all widgets that support key presses
44
- # TODO support event.location once DOM3 is supported by opal-jquery
45
- event.define_singleton_method(:keyCode) {event.which}
46
- event.define_singleton_method(:key_code, &event.method(:keyCode))
47
- event.define_singleton_method(:character) {event.which.chr}
48
- event.define_singleton_method(:stateMask) do
49
- state_mask = 0
50
- state_mask |= SWTProxy[:alt] if event.alt_key
51
- state_mask |= SWTProxy[:ctrl] if event.ctrl_key
52
- state_mask |= SWTProxy[:shift] if event.shift_key
53
- state_mask |= SWTProxy[:command] if event.meta_key
54
- state_mask
55
- end
56
- event.define_singleton_method(:state_mask, &event.method(:stateMask))
57
- doit = true
58
- event.define_singleton_method(:doit=) do |value|
59
- doit = value
60
- end
61
- event.define_singleton_method(:doit) { doit }
62
- event_listener.call(event)
63
-
64
- # TODO Fix doit false, it's not stopping input
65
- unless doit
66
- event.prevent
67
- event.prevent_default
68
- event.stop_propagation
69
- event.stop_immediate_propagation
70
- end
71
-
72
- doit
73
- }
74
- }
75
- },
76
38
  }
77
39
  end
78
40
 
@@ -31,6 +31,25 @@ module Glimmer
31
31
  include Glimmer
32
32
  include PropertyOwner
33
33
 
34
+ Event = Struct.new(:widget, keyword_init: true)
35
+
36
+ JS_KEY_CODE_TO_SWT_KEY_CODE_MAP = {
37
+ 16 => SWTProxy[:shift],
38
+ 17 => SWTProxy[:ctrl],
39
+ 18 => SWTProxy[:alt],
40
+ 37 => SWTProxy[:arrow_left],
41
+ 38 => SWTProxy[:arrow_up],
42
+ 39 => SWTProxy[:arrow_right],
43
+ 40 => SWTProxy[:arrow_down],
44
+ }
45
+
46
+ JS_LOCATION_TO_SWT_KEY_LOCATION_MAP = {
47
+ 0 => SWTProxy[:none],
48
+ 1 => SWTProxy[:left],
49
+ 2 => SWTProxy[:right],
50
+ 3 => SWTProxy[:keypad],
51
+ }
52
+
34
53
  SWT_CURSOR_TO_CSS_CURSOR_MAP = {
35
54
  wait: 'wait',
36
55
  sizenwse: 'nwse-resize',
@@ -140,7 +159,6 @@ module Glimmer
140
159
  # TODO consider changing children to an array (why is it a Set if order matters?)
141
160
  @children = Set.new # TODO consider moving to composite
142
161
  @enabled = true
143
- @data = {}
144
162
  DEFAULT_INITIALIZERS[self.class.underscored_widget_name(self).to_s.to_sym]&.call(self)
145
163
  @parent.post_initialize_child(self) # TODO rename to post_initialize_child to be closer to glimmer-dsl-swt terminology
146
164
  end
@@ -172,18 +190,30 @@ module Glimmer
172
190
  end
173
191
  end
174
192
 
175
- def set_data(key=nil, value)
176
- @data[key] = value
193
+ def set_data(key = nil, value)
194
+ if key.nil?
195
+ @data = value
196
+ else
197
+ swt_data[key] = value
198
+ end
177
199
  end
178
200
  alias setData set_data
179
201
  alias data= set_data
180
202
 
181
- def get_data(key=nil)
182
- @data[key]
203
+ def get_data(key = nil)
204
+ if key.nil?
205
+ @data
206
+ else
207
+ swt_data[key]
208
+ end
183
209
  end
184
210
  alias getData get_data
185
211
  alias data get_data
186
212
 
213
+ def swt_data
214
+ @swt_data ||= {}
215
+ end
216
+
187
217
  def css_classes
188
218
  dom_element.attr('class').to_s.split
189
219
  end
@@ -192,9 +222,9 @@ module Glimmer
192
222
  remove_all_listeners
193
223
  Document.find(path).remove
194
224
  parent&.post_dispose_child(self)
195
- # TODO fire on_widget_disposed listener
196
225
  # children.each(:dispose) # TODO enable this safely
197
226
  @disposed = true
227
+ listeners_for('widget_disposed').each {|listener| listener.call(Event.new(widget: self))}
198
228
  end
199
229
 
200
230
  def remove_all_listeners
@@ -360,7 +390,6 @@ module Glimmer
360
390
  mouse_event_handler = -> (event_listener) {
361
391
  -> (event) {
362
392
  # TODO generalize this solution to all widgets that support key presses
363
- # TODO support event.location once DOM3 is supported by opal-jquery
364
393
  event.define_singleton_method(:widget) {myself}
365
394
  event.define_singleton_method(:button, &event.method(:which))
366
395
  event.define_singleton_method(:count) {1} # TODO support double-click count of 2 in the future by using ondblclick
@@ -388,7 +417,6 @@ module Glimmer
388
417
  mouse_move_event_handler = -> (event_listener) {
389
418
  -> (event) {
390
419
  # TODO generalize this solution to all widgets that support key presses
391
- # TODO support event.location once DOM3 is supported by opal-jquery
392
420
  event.define_singleton_method(:widget) {myself}
393
421
  event.define_singleton_method(:button, &event.method(:which))
394
422
  event.define_singleton_method(:count) {1} # TODO support double-click count of 2 in the future by using ondblclick
@@ -413,7 +441,6 @@ module Glimmer
413
441
  context_menu_handler = -> (event_listener) {
414
442
  -> (event) {
415
443
  # TODO generalize this solution to all widgets that support key presses
416
- # TODO support event.location once DOM3 is supported by opal-jquery
417
444
  event.define_singleton_method(:widget) {myself}
418
445
  event.define_singleton_method(:button, &event.method(:which))
419
446
  event.define_singleton_method(:count) {1} # TODO support double-click count of 2 in the future by using ondblclick
@@ -494,10 +521,15 @@ module Glimmer
494
521
  event: 'keypress',
495
522
  event_handler: -> (event_listener) {
496
523
  -> (event) {
497
- # TODO generalize this solution to all widgets that support key presses
498
- # TODO support event.location once DOM3 is supported by opal-jquery
499
524
  event.define_singleton_method(:widget) {myself}
500
- event.define_singleton_method(:keyCode) {event.which}
525
+ event.define_singleton_method(:keyLocation) do
526
+ location = `#{event.to_n}.originalEvent.location`
527
+ JS_LOCATION_TO_SWT_KEY_LOCATION_MAP[location] || location
528
+ end
529
+ event.define_singleton_method(:key_location, &event.method(:keyLocation))
530
+ event.define_singleton_method(:keyCode) {
531
+ JS_KEY_CODE_TO_SWT_KEY_CODE_MAP[event.which] || event.which
532
+ }
501
533
  event.define_singleton_method(:key_code, &event.method(:keyCode))
502
534
  event.define_singleton_method(:character) {event.which.chr}
503
535
  event.define_singleton_method(:stateMask) do
@@ -528,50 +560,18 @@ module Glimmer
528
560
  }
529
561
  } },
530
562
  'on_key_released' => {
531
- event: 'keydown',
563
+ event: 'keyup',
532
564
  event_handler: -> (event_listener) {
533
565
  -> (event) {
534
- # TODO generalize this solution to all widgets that support key presses
535
- # TODO support event.location once DOM3 is supported by opal-jquery
536
- event.define_singleton_method(:widget) {myself}
537
- event.define_singleton_method(:keyCode) {event.which}
538
- event.define_singleton_method(:key_code, &event.method(:keyCode))
539
- event.define_singleton_method(:character) {event.which.chr}
540
- event.define_singleton_method(:stateMask) do
541
- state_mask = 0
542
- state_mask |= SWTProxy[:alt] if event.alt_key
543
- state_mask |= SWTProxy[:ctrl] if event.ctrl_key
544
- state_mask |= SWTProxy[:shift] if event.shift_key
545
- state_mask |= SWTProxy[:command] if event.meta_key
546
- state_mask
547
- end
548
- event.define_singleton_method(:state_mask, &event.method(:stateMask))
549
- doit = true
550
- event.define_singleton_method(:doit=) do |value|
551
- doit = value
552
- end
553
- event.define_singleton_method(:doit) { doit }
554
- event_listener.call(event)
555
-
556
- # TODO Fix doit false, it's not stopping input
557
- unless doit
558
- event.prevent
559
- event.prevent_default
560
- event.stop_propagation
561
- event.stop_immediate_propagation
566
+ event.define_singleton_method(:keyLocation) do
567
+ location = `#{event.to_n}.originalEvent.location`
568
+ JS_LOCATION_TO_SWT_KEY_LOCATION_MAP[location] || location
562
569
  end
563
-
564
- doit
565
- }
566
- } },
567
- 'on_swt_keydown' => {
568
- event: 'keypress',
569
- event_handler: -> (event_listener) {
570
- -> (event) {
571
- # TODO generalize this solution to all widgets that support key presses
572
- # TODO support event.location once DOM3 is supported by opal-jquery
570
+ event.define_singleton_method(:key_location, &event.method(:keyLocation))
573
571
  event.define_singleton_method(:widget) {myself}
574
- event.define_singleton_method(:keyCode) {event.which}
572
+ event.define_singleton_method(:keyCode) {
573
+ JS_KEY_CODE_TO_SWT_KEY_CODE_MAP[event.which] || event.which
574
+ }
575
575
  event.define_singleton_method(:key_code, &event.method(:keyCode))
576
576
  event.define_singleton_method(:character) {event.which.chr}
577
577
  event.define_singleton_method(:stateMask) do
@@ -600,15 +600,106 @@ module Glimmer
600
600
 
601
601
  doit
602
602
  }
603
- } },
603
+ }
604
+ },
605
+ 'on_swt_keydown' => [
606
+ {
607
+ event: 'keypress',
608
+ event_handler: -> (event_listener) {
609
+ -> (event) {
610
+ event.define_singleton_method(:keyLocation) do
611
+ location = `#{event.to_n}.originalEvent.location`
612
+ JS_LOCATION_TO_SWT_KEY_LOCATION_MAP[location] || location
613
+ end
614
+ event.define_singleton_method(:key_location, &event.method(:keyLocation))
615
+ event.define_singleton_method(:keyCode) {
616
+ JS_KEY_CODE_TO_SWT_KEY_CODE_MAP[event.which] || event.which
617
+ }
618
+ event.define_singleton_method(:key_code, &event.method(:keyCode))
619
+ event.define_singleton_method(:character) {event.which.chr}
620
+ event.define_singleton_method(:stateMask) do
621
+ state_mask = 0
622
+ state_mask |= SWTProxy[:alt] if event.alt_key
623
+ state_mask |= SWTProxy[:ctrl] if event.ctrl_key
624
+ state_mask |= SWTProxy[:shift] if event.shift_key
625
+ state_mask |= SWTProxy[:command] if event.meta_key
626
+ state_mask
627
+ end
628
+ event.define_singleton_method(:state_mask, &event.method(:stateMask))
629
+ doit = true
630
+ event.define_singleton_method(:doit=) do |value|
631
+ doit = value
632
+ end
633
+ event.define_singleton_method(:doit) { doit }
634
+ event_listener.call(event)
635
+
636
+ # TODO Fix doit false, it's not stopping input
637
+ unless doit
638
+ event.prevent
639
+ event.prevent_default
640
+ event.stop_propagation
641
+ event.stop_immediate_propagation
642
+ end
643
+
644
+ doit
645
+ }
646
+ }
647
+ },
648
+ {
649
+ event: 'keydown',
650
+ event_handler: -> (event_listener) {
651
+ -> (event) {
652
+ event.define_singleton_method(:keyLocation) do
653
+ location = `#{event.to_n}.originalEvent.location`
654
+ JS_LOCATION_TO_SWT_KEY_LOCATION_MAP[location] || location
655
+ end
656
+ event.define_singleton_method(:key_location, &event.method(:keyLocation))
657
+ event.define_singleton_method(:keyCode) {
658
+ JS_KEY_CODE_TO_SWT_KEY_CODE_MAP[event.which] || event.which
659
+ }
660
+ event.define_singleton_method(:key_code, &event.method(:keyCode))
661
+ event.define_singleton_method(:character) {event.which.chr}
662
+ event.define_singleton_method(:stateMask) do
663
+ state_mask = 0
664
+ state_mask |= SWTProxy[:alt] if event.alt_key
665
+ state_mask |= SWTProxy[:ctrl] if event.ctrl_key
666
+ state_mask |= SWTProxy[:shift] if event.shift_key
667
+ state_mask |= SWTProxy[:command] if event.meta_key
668
+ state_mask
669
+ end
670
+ event.define_singleton_method(:state_mask, &event.method(:stateMask))
671
+ doit = true
672
+ event.define_singleton_method(:doit=) do |value|
673
+ doit = value
674
+ end
675
+ event.define_singleton_method(:doit) { doit }
676
+ event_listener.call(event) if event.which != 13 && (event.which == 127 || event.which <= 40)
677
+
678
+ # TODO Fix doit false, it's not stopping input
679
+ unless doit
680
+ event.prevent
681
+ event.prevent_default
682
+ event.stop_propagation
683
+ event.stop_immediate_propagation
684
+ end
685
+ doit
686
+ }
687
+ }
688
+ }
689
+ ],
604
690
  'on_swt_keyup' => {
605
- event: 'keydown',
691
+ event: 'keyup',
606
692
  event_handler: -> (event_listener) {
607
693
  -> (event) {
608
- # TODO generalize this solution to all widgets that support key presses
609
- # TODO support event.location once DOM3 is supported by opal-jquery
694
+ event.define_singleton_method(:keyLocation) do
695
+ location = `#{event.to_n}.originalEvent.location`
696
+ JS_LOCATION_TO_SWT_KEY_LOCATION_MAP[location] || location
697
+ end
698
+ event.define_singleton_method(:key_location, &event.method(:keyLocation))
610
699
  event.define_singleton_method(:widget) {myself}
611
- event.define_singleton_method(:keyCode) {event.which}
700
+ event.define_singleton_method(:keyCode) {
701
+ JS_KEY_CODE_TO_SWT_KEY_CODE_MAP[event.which] || event.which
702
+ }
612
703
  event.define_singleton_method(:key_code, &event.method(:keyCode))
613
704
  event.define_singleton_method(:character) {event.which.chr}
614
705
  event.define_singleton_method(:stateMask) do
@@ -733,6 +824,14 @@ module Glimmer
733
824
  @event_handling_suspended
734
825
  end
735
826
 
827
+ def listeners
828
+ @listeners ||= {}
829
+ end
830
+
831
+ def listeners_for(listener_event)
832
+ listeners[listener_event.to_s] ||= []
833
+ end
834
+
736
835
  def can_handle_observation_request?(observation_request)
737
836
  # TODO sort this out for Opal
738
837
  observation_request = observation_request.to_s
@@ -747,6 +846,15 @@ module Glimmer
747
846
  end
748
847
 
749
848
  def handle_observation_request(keyword, original_event_listener)
849
+ case keyword
850
+ when 'on_widget_disposed'
851
+ listeners_for(keyword.sub(/^on_/, '')) << original_event_listener.to_proc
852
+ else
853
+ handle_javascript_observation_request(keyword, original_event_listener)
854
+ end
855
+ end
856
+
857
+ def handle_javascript_observation_request(keyword, original_event_listener)
750
858
  return unless effective_observation_request_to_event_mapping.keys.include?(keyword)
751
859
  event = nil
752
860
  delegate = nil
@@ -886,6 +994,18 @@ module Glimmer
886
994
  # }
887
995
  # end,
888
996
  # },
997
+ MenuItemProxy => {
998
+ :selection => lambda do |observer|
999
+ on_widget_selected { |selection_event|
1000
+ # TODO look into validity of this and perhaps move toggle logic to MenuItemProxy
1001
+ if check?
1002
+ observer.call(!selection)
1003
+ else
1004
+ observer.call(selection)
1005
+ end
1006
+ }
1007
+ end
1008
+ },
889
1009
  ScaleProxy => {
890
1010
  :selection => lambda do |observer|
891
1011
  on_widget_selected { |selection_event|
@@ -1021,7 +1141,6 @@ require 'glimmer/swt/combo_proxy'
1021
1141
  require 'glimmer/swt/c_combo_proxy'
1022
1142
  require 'glimmer/swt/checkbox_proxy'
1023
1143
  require 'glimmer/swt/composite_proxy'
1024
- require 'glimmer/swt/dialog_proxy'
1025
1144
  require 'glimmer/swt/date_time_proxy'
1026
1145
  require 'glimmer/swt/group_proxy'
1027
1146
  require 'glimmer/swt/label_proxy'