glimmer-dsl-opal 0.25.3 → 0.26.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7730a7073849e1cb3cf05073368a974a7cc493fa44621b3fd58d180e76c25c89
4
- data.tar.gz: 7588d6730c8f81b27e8aff908bfe3c7f4daff093c004661abbb0c4fb0a2b4756
3
+ metadata.gz: dd9df390a04a8efb59afa0dcfe42a88d3a2ebcc89b19f51b5daf325e85495898
4
+ data.tar.gz: f842142ce4346af198197cacaa1695eddc9f15f684c4b4250ebed41872d9253f
5
5
  SHA512:
6
- metadata.gz: f50d2e39e990b86392e4fc719737b19337083380c874e426186dbbfe9ad7b60445a76fa93a8f5cf6d5055576f60209423b940e5efce3fee28f5081a99a61c2a3
7
- data.tar.gz: 70634d53b24b7a82fcc8ca50b6b502d8b8b4260d204e89682a953e9bdbae81c7688867c8552082f323b1526170cd40a7a85222f637f8d8fb765c2658ce306e29
6
+ metadata.gz: 1090a9d0bf0cab0bb673e32ce5711e3d034866e4d195995db125b40a43fa798f09f6944ba2e2bfbb38d06731248717bc38fd166d50c543e6271564aa8e80f978
7
+ data.tar.gz: 57e6aa38f7829508d5a6f0a54814ada1d58c79fda05f56d353a069271960727b9d92c2bb642839215a6942958d267d00e9befc7b5f688755037fe46fcd7b8f53
data/CHANGELOG.md CHANGED
@@ -1,5 +1,29 @@
1
1
  # Change Log
2
2
 
3
+ ## 0.26.2
4
+
5
+ - Support key_event.key_location to distinguish between left and right alt/shift/command/ctrl buttons
6
+ - Use right/left alt/shift keys in Tetris for rotate right and rotate left
7
+
8
+ ## 0.26.1
9
+
10
+ - Support display on_swt_keydown event keyCode/key_code values for arrow keys and alt/shift/ctrl
11
+ - Use arrow keys for movement in Tetris
12
+ - Use alt/shift keys for rotate right in Tetris
13
+
14
+ ## 0.26.0
15
+
16
+ - Tetris elaborate sample (minimal initial version of the one in Glimmer DSL for SWT)
17
+ - Support `menu_item` `selection` attribute data-binding for `:check` and `:radio` SWT styles
18
+ - Set 'custom_shell' data for custom shell on its body_root
19
+ - Provide parent_proxy on custom widgets as an alternative to parent for compatibility with Glimmer DSL for SWT
20
+ - Have custom widgets derive their parent from body root if not passed in explicitly
21
+
22
+ ## 0.25.4
23
+
24
+ - Upgrade to opal-async 1.4.0
25
+ - Update Hello, Custom Widget! to utilize `Array#async_cycle` instead of `Array#cycle`
26
+
3
27
  ## 0.25.3
4
28
 
5
29
  - Fix `c_combo`'s data-binding of selection receiving model changes
data/README.md CHANGED
@@ -12,6 +12,8 @@ Use in one of two ways:
12
12
 
13
13
  Glimmer DSL for Opal successfully reuses the entire [Glimmer](https://github.com/AndyObtiva/glimmer) core DSL engine in [Opal Ruby](https://opalrb.com/) inside a web browser, and as such inherits the full range of Glimmer desktop [data-binding](https://github.com/AndyObtiva/glimmer#data-binding) capabilities for the web (including Shine syntax using `<=>` and `<=` for bidirectional [two-way] and unidirectional [one-way] data-binding respectively).
14
14
 
15
+ (note that auto-webification of desktop apps that involve multiple threads might involve extra changes to the code to utilize web async calls due to the async nature of transpiled JavaScript code)
16
+
15
17
  #### Hello, Table! Sample
16
18
 
17
19
  Code: [lib/glimmer-dsl-opal/samples/hello/hello_table.rb](lib/glimmer-dsl-opal/samples/hello/hello_table.rb)
@@ -143,7 +145,7 @@ Hello, Table! Game Booked
143
145
 
144
146
  NOTE: Glimmer DSL for Opal is an alpha project. Please help make better by contributing, adopting for small or low risk projects, and providing feedback. It is still an early alpha, so the more feedback and issues you report the better.
145
147
 
146
- **Alpha Version** 0.25.3 only supports bare-minimum capabilities for the included [samples](https://github.com/AndyObtiva/glimmer-dsl-opal#samples) (originally written for [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt))
148
+ **Alpha Version** 0.26.2 only supports bare-minimum capabilities for the included [samples](https://github.com/AndyObtiva/glimmer-dsl-opal#samples) (originally written for [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt))
147
149
 
148
150
  Other [Glimmer](https://github.com/AndyObtiva/glimmer) DSL gems:
149
151
  - [glimmer-dsl-swt](https://github.com/AndyObtiva/glimmer-dsl-swt): Glimmer DSL for SWT (JRuby Desktop Development GUI Framework)
@@ -194,6 +196,7 @@ Other [Glimmer](https://github.com/AndyObtiva/glimmer) DSL gems:
194
196
  - [Elaborate Samples](#elaborate-samples)
195
197
  - [Login](#login)
196
198
  - [Contact Manager](#contact-manager)
199
+ - [Tetris](#tetris)
197
200
  - [Tic Tac Toe](#tic-tac-toe)
198
201
  - [User Profile](#user-profile)
199
202
  - [Weather](#weather)
@@ -232,8 +235,8 @@ Alternatively, web developers may directly use [Glimmer DSL for Opal](https://ru
232
235
 
233
236
  ## Pre-requisites
234
237
 
235
- - Rails 5: [https://github.com/rails/rails/tree/5-2-stable](https://github.com/rails/rails/tree/5-2-stable)
236
- - Opal 1.0.4: [https://github.com/opal/opal](https://github.com/opal/opal)
238
+ - Rails 5.2: [https://github.com/rails/rails/tree/5-2-stable](https://github.com/rails/rails/tree/5-2-stable)
239
+ - Opal 1.0.5: [https://github.com/opal/opal](https://github.com/opal/opal)
237
240
  - Opal-Rails 1.1.2: [https://github.com/opal/opal-rails](https://github.com/opal/opal-rails)
238
241
  - jQuery 3: [https://code.jquery.com/](https://code.jquery.com/) (jQuery 3.5.1 is included in the [glimmer-dsl-opal](https://rubygems.org/gems/glimmer-dsl-opal) gem)
239
242
  - jQuery-UI 1.12: [https://code.jquery.com/](https://jqueryui.com/) (jQuery-UI 1.12.1 is included in the [glimmer-dsl-opal](https://rubygems.org/gems/glimmer-dsl-opal) gem)
@@ -250,7 +253,7 @@ Please follow the following steps to setup.
250
253
  Install a Rails 5 gem:
251
254
 
252
255
  ```
253
- gem install rails -v5.2.4.4
256
+ gem install rails -v5.2.6
254
257
  ```
255
258
 
256
259
  Start a new Rails 5 app:
@@ -262,11 +265,11 @@ rails new glimmer_app_server
262
265
  Add the following to `Gemfile`:
263
266
 
264
267
  ```
265
- gem 'opal', '1.0.4'
268
+ gem 'opal', '1.0.5'
266
269
  gem 'opal-rails', '1.1.2'
267
- gem 'opal-async', '~> 1.3.0'
270
+ gem 'opal-async', '~> 1.4.0'
268
271
  gem 'opal-jquery', '~> 0.4.4'
269
- gem 'glimmer-dsl-opal', '~> 0.25.3'
272
+ gem 'glimmer-dsl-opal', '~> 0.26.2'
270
273
  gem 'glimmer-dsl-xml', '~> 1.2.0', require: false
271
274
  gem 'glimmer-dsl-css', '~> 1.2.0', require: false
272
275
 
@@ -1035,7 +1038,7 @@ Add the following require statement to `app/assets/javascripts/application.rb`
1035
1038
  require 'glimmer-dsl-opal/samples/hello/hello_custom_widget'
1036
1039
  ```
1037
1040
 
1038
- Or add the Glimmer code directly if you prefer to play around with it:
1041
+ Or add the Glimmer code directly if you prefer to play around with it (note that the Opal version needs `Array#async_cycle` from the opal-async gem instead of `Array#cycle` due to the async nature of JavaScript):
1039
1042
 
1040
1043
  ```ruby
1041
1044
  # This class declares a `greeting_label` custom widget (by convention)
@@ -1060,7 +1063,7 @@ class GreetingLabel
1060
1063
  return if colors.nil?
1061
1064
 
1062
1065
  Thread.new { # imported from Glimmer DSL for SWT. In Opal, avoid Threads and sleep to avoid blocking GUI.
1063
- colors.cycle { |color|
1066
+ colors.async_cycle { |color|
1064
1067
  async_exec {
1065
1068
  self.color = color
1066
1069
  }
@@ -2582,6 +2585,40 @@ Glimmer DSL for Opal Contact Manager Edit Done
2582
2585
 
2583
2586
  ![Glimmer DSL for Opal Contact Manager Edit Done](images/glimmer-dsl-opal-contact-manager-edit-done.png)
2584
2587
 
2588
+ #### Tetris
2589
+
2590
+ This is a minimal initial version of the [Tetris seen in Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt/blob/master/docs/reference/GLIMMER_SAMPLES.md#glimmer-tetris).
2591
+
2592
+ Note that while the Glimmer GUI DSL code is mostly the same, some of the behavioral code around threads is changed
2593
+ into async Opal code via the [opal-async](https://github.com/AndyObtiva/opal-async) gem due to the async nature of transpiled JavaScript.
2594
+
2595
+ Still, this sample has done the remarkable feat of reusing all of the Tetris model/view logic from Glimmer DSL for SWT mostly unchanged.
2596
+
2597
+ Add the following require statement to `app/assets/javascripts/application.rb`
2598
+
2599
+ ```ruby
2600
+ require 'glimmer-dsl-opal/samples/elaborate/tetris'
2601
+ ```
2602
+
2603
+ Glimmer app on the desktop (using [`glimmer-dsl-swt`](https://github.com/AndyObtiva/glimmer-dsl-swt) gem):
2604
+
2605
+ ![Glimmer DSL for SWT Tetris](https://github.com/AndyObtiva/glimmer-dsl-swt/raw/master/images/glimmer-tetris.png)
2606
+
2607
+ Glimmer app on the web (using `glimmer-dsl-opal` gem):
2608
+
2609
+ Start the Rails server:
2610
+ ```
2611
+ rails s
2612
+ ```
2613
+
2614
+ Visit `http://localhost:3000`
2615
+
2616
+ You should see "Tetris" (a minimal version of the one in Glimmer DSL for SWT)
2617
+
2618
+ ![Glimmer DSL for Opal Tetris](images/glimmer-dsl-opal-tetris.png)
2619
+
2620
+ ![Glimmer DSL for Opal Tetris Video](images/glimmer-dsl-opal-tetris.gif)
2621
+
2585
2622
  #### Tic Tac Toe
2586
2623
 
2587
2624
  Add the following require statement to `app/assets/javascripts/application.rb`
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.25.3
1
+ 0.26.2
@@ -37,9 +37,6 @@ module Glimmer
37
37
  if parent.is_a?(Glimmer::SWT::WidgetProxy)
38
38
  return true
39
39
  else
40
- puts 'parent'
41
- puts parent.class
42
- puts parent
43
40
  raise Glimmer::Error, "menu may only be nested under a widget (like shell or another menu)!"
44
41
  end
45
42
  end
@@ -27,8 +27,8 @@ module Glimmer
27
27
  ATTRIBUTES = [:grabHorizontal, :grabVertical, :horizontalAlignment, :verticalAlignment, :minimumWidth, :minimumHeight]
28
28
  attr_accessor(*ATTRIBUTES)
29
29
  ATTRIBUTES.each do |attribute|
30
- alias_method attribute.underscore, attribute
31
- alias_method "#{attribute.underscore}=", "#{attribute}="
30
+ alias_method attribute.to_s.underscore, attribute
31
+ alias_method "#{attribute.to_s.underscore}=", "#{attribute}="
32
32
  end
33
33
 
34
34
  # TODO consider supporting a java_attr_accessor to get around having to generate all the aliases manually
@@ -19,12 +19,13 @@
19
19
  # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
20
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
21
 
22
- require 'glimmer/swt/widget_proxy'
23
22
  require 'glimmer/swt/display_proxy'
23
+ require 'glimmer/swt/widget_proxy'
24
+ require 'glimmer/swt/shell_proxy'
24
25
 
25
26
  module Glimmer
26
27
  module SWT
27
- class DialogProxy < CompositeProxy
28
+ class DialogProxy < ShellProxy
28
29
  STYLE = <<~CSS
29
30
  .ui-dialog .ui-dialog-content {
30
31
  background: rgb(235, 235, 235);
@@ -86,7 +87,7 @@ module Glimmer
86
87
  @open
87
88
  end
88
89
 
89
- def open
90
+ def open(async: true)
90
91
  owned_proc = Glimmer::Util::ProcTracker.new(owner: self, invoked_from: :open) {
91
92
  shell.open(async: false) unless shell.open?
92
93
  unless @init
@@ -113,8 +114,13 @@ module Glimmer
113
114
  dom_element.dialog('open')
114
115
  end
115
116
  @open = true
117
+ listeners_for('swt_show').each {|listener| listener.call(Event.new(widget: self))}
116
118
  }
117
- DisplayProxy.instance.async_exec(owned_proc)
119
+ if async
120
+ DisplayProxy.instance.async_exec(owned_proc)
121
+ else
122
+ owned_proc.call
123
+ end
118
124
  end
119
125
 
120
126
  def hide
@@ -129,6 +135,7 @@ module Glimmer
129
135
  dom_element.remove
130
136
  @open = false
131
137
  @init = false
138
+ listeners_for('swt_close').each {|listener| listener.call(Event.new(widget: self))}
132
139
  Element['.dialog-overlay'].add_class('hide') unless DisplayProxy.instance.dialogs.any?(&:open?)
133
140
  parent.children.delete(self)
134
141
  shell.close if shell.children.empty?
@@ -1,8 +1,25 @@
1
1
  require 'glimmer/swt/widget_proxy'
2
+ require 'glimmer/swt/swt_proxy'
2
3
 
3
4
  module Glimmer
4
5
  module SWT
5
6
  class DisplayProxy < WidgetProxy
7
+ JS_KEY_CODE_TO_SWT_KEY_CODE_MAP = {
8
+ 16 => SWTProxy[:shift],
9
+ 17 => SWTProxy[:ctrl],
10
+ 18 => SWTProxy[:alt],
11
+ 37 => SWTProxy[:arrow_left],
12
+ 38 => SWTProxy[:arrow_up],
13
+ 39 => SWTProxy[:arrow_right],
14
+ 40 => SWTProxy[:arrow_down],
15
+ }
16
+
17
+ JS_LOCATION_TO_SWT_KEY_LOCATION_MAP = {
18
+ 1 => SWTProxy[:left],
19
+ 2 => SWTProxy[:right],
20
+ }
21
+
22
+
6
23
  class << self
7
24
  def instance
8
25
  @instance ||= new
@@ -95,7 +112,9 @@ module Glimmer
95
112
  event.singleton_class.define_method(:character) do
96
113
  which || key_code
97
114
  end
98
- event.define_singleton_method(:keyCode) {event.which}
115
+ event.define_singleton_method(:keyCode) {
116
+ JS_KEY_CODE_TO_SWT_KEY_CODE_MAP[event.which] || event.which
117
+ }
99
118
  event.define_singleton_method(:key_code, &event.method(:keyCode))
100
119
  event.define_singleton_method(:character) {event.which.chr}
101
120
  event.define_singleton_method(:stateMask) do
@@ -130,10 +149,19 @@ module Glimmer
130
149
  event: 'keydown',
131
150
  event_handler: -> (event_listener) {
132
151
  -> (event) {
133
- event.singleton_class.define_method(:character) do
152
+ original_event = event
153
+ event = ::Event.new(event)
154
+ event.define_singleton_method(:keyLocation) do
155
+ key_location = `#{original_event}.location`
156
+ JS_LOCATION_TO_SWT_KEY_LOCATION_MAP[key_location]
157
+ end
158
+ event.define_singleton_method(:key_location, &event.method(:keyLocation))
159
+ event.define_singleton_method(:character) do
134
160
  which || key_code
135
161
  end
136
- event.define_singleton_method(:keyCode) {event.which}
162
+ event.define_singleton_method(:keyCode) {
163
+ JS_KEY_CODE_TO_SWT_KEY_CODE_MAP[event.which] || event.which
164
+ }
137
165
  event.define_singleton_method(:key_code, &event.method(:keyCode))
138
166
  event.define_singleton_method(:character) {event.which.chr}
139
167
  event.define_singleton_method(:stateMask) do
@@ -150,7 +178,7 @@ module Glimmer
150
178
  doit = value
151
179
  end
152
180
  event.define_singleton_method(:doit) { doit }
153
- event_listener.call(event) if event.key_code != 13 && (event.key_code == 127 || event.key_code <= 31)
181
+ event_listener.call(event) if event.which != 13 && (event.which == 127 || event.which <= 40)
154
182
 
155
183
  # TODO Fix doit false, it's not stopping input
156
184
  unless doit
@@ -159,7 +187,6 @@ module Glimmer
159
187
  event.stop_propagation
160
188
  event.stop_immediate_propagation
161
189
  end
162
-
163
190
  doit
164
191
  }
165
192
  }
@@ -69,6 +69,7 @@ module Glimmer
69
69
  HEIGHT_MIN = 0
70
70
 
71
71
  def initialize(args)
72
+ # TODO set parent
72
73
  @args = args
73
74
  @children = []
74
75
  render # TODO attach to specific element
@@ -78,7 +79,7 @@ module Glimmer
78
79
  self.minimum_size = Point.new(WIDTH_MIN, HEIGHT_MIN)
79
80
  DisplayProxy.instance.shells << self
80
81
  end
81
-
82
+
82
83
  def post_add_content
83
84
  `$( document ).tooltip()`
84
85
  end
@@ -128,6 +129,16 @@ module Glimmer
128
129
  dom_element.css('min-height', "#{@minimum_size.y}px")
129
130
  end
130
131
 
132
+ def handle_observation_request(keyword, original_event_listener)
133
+ case keyword
134
+ when 'on_swt_show', 'on_swt_close', 'on_shell_closed'
135
+ keyword = 'on_swt_close' if keyword == 'on_shell_closed'
136
+ listeners_for(keyword.sub(/^on_/, '')) << original_event_listener.to_proc
137
+ else
138
+ super(keyword, original_event_listener)
139
+ end
140
+ end
141
+
131
142
  def style_dom_css
132
143
  <<~CSS
133
144
  .hide {
@@ -169,6 +180,7 @@ module Glimmer
169
180
  DisplayProxy.instance.shells.select(&:open?).reject {|s| s == self}.map(&:hide)
170
181
  dom_element.remove_class('hide')
171
182
  @open = true
183
+ listeners_for('swt_show').each {|listener| listener.call(Event.new(widget: self))}
172
184
  end
173
185
  end
174
186
  if async
@@ -177,6 +189,7 @@ module Glimmer
177
189
  work.call
178
190
  end
179
191
  end
192
+ alias show open
180
193
 
181
194
  def hide
182
195
  dom_element.add_class('hide')
@@ -187,11 +200,25 @@ module Glimmer
187
200
  DisplayProxy.instance.shells.delete(self)
188
201
  dom_element.remove
189
202
  @open = false
203
+ listeners_for('swt_close').each {|listener| listener.call(Event.new(widget: self))}
190
204
  end
191
205
 
192
206
  def open?
193
207
  @open
194
208
  end
209
+
210
+ def visible
211
+ @open
212
+ end
213
+ alias visible? visible
214
+
215
+ def visible=(value)
216
+ if value
217
+ show(async: false)
218
+ else
219
+ hide
220
+ end
221
+ end
195
222
  end
196
223
  end
197
224
  end
@@ -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!
@@ -31,6 +31,8 @@ module Glimmer
31
31
  include Glimmer
32
32
  include PropertyOwner
33
33
 
34
+ Event = Struct.new(:widget, keyword_init: true)
35
+
34
36
  SWT_CURSOR_TO_CSS_CURSOR_MAP = {
35
37
  wait: 'wait',
36
38
  sizenwse: 'nwse-resize',
@@ -140,7 +142,6 @@ module Glimmer
140
142
  # TODO consider changing children to an array (why is it a Set if order matters?)
141
143
  @children = Set.new # TODO consider moving to composite
142
144
  @enabled = true
143
- @data = {}
144
145
  DEFAULT_INITIALIZERS[self.class.underscored_widget_name(self).to_s.to_sym]&.call(self)
145
146
  @parent.post_initialize_child(self) # TODO rename to post_initialize_child to be closer to glimmer-dsl-swt terminology
146
147
  end
@@ -172,18 +173,30 @@ module Glimmer
172
173
  end
173
174
  end
174
175
 
175
- def set_data(key=nil, value)
176
- @data[key] = value
176
+ def set_data(key = nil, value)
177
+ if key.nil?
178
+ @data = value
179
+ else
180
+ swt_data[key] = value
181
+ end
177
182
  end
178
183
  alias setData set_data
179
184
  alias data= set_data
180
185
 
181
- def get_data(key=nil)
182
- @data[key]
186
+ def get_data(key = nil)
187
+ if key.nil?
188
+ @data
189
+ else
190
+ swt_data[key]
191
+ end
183
192
  end
184
193
  alias getData get_data
185
194
  alias data get_data
186
195
 
196
+ def swt_data
197
+ @swt_data ||= {}
198
+ end
199
+
187
200
  def css_classes
188
201
  dom_element.attr('class').to_s.split
189
202
  end
@@ -192,9 +205,9 @@ module Glimmer
192
205
  remove_all_listeners
193
206
  Document.find(path).remove
194
207
  parent&.post_dispose_child(self)
195
- # TODO fire on_widget_disposed listener
196
208
  # children.each(:dispose) # TODO enable this safely
197
209
  @disposed = true
210
+ listeners_for('widget_disposed').each {|listener| listener.call(Event.new(widget: self))}
198
211
  end
199
212
 
200
213
  def remove_all_listeners
@@ -733,6 +746,14 @@ module Glimmer
733
746
  @event_handling_suspended
734
747
  end
735
748
 
749
+ def listeners
750
+ @listeners ||= {}
751
+ end
752
+
753
+ def listeners_for(listener_event)
754
+ listeners[listener_event.to_s] ||= []
755
+ end
756
+
736
757
  def can_handle_observation_request?(observation_request)
737
758
  # TODO sort this out for Opal
738
759
  observation_request = observation_request.to_s
@@ -747,6 +768,15 @@ module Glimmer
747
768
  end
748
769
 
749
770
  def handle_observation_request(keyword, original_event_listener)
771
+ case keyword
772
+ when 'on_widget_disposed'
773
+ listeners_for(keyword.sub(/^on_/, '')) << original_event_listener.to_proc
774
+ else
775
+ handle_javascript_observation_request(keyword, original_event_listener)
776
+ end
777
+ end
778
+
779
+ def handle_javascript_observation_request(keyword, original_event_listener)
750
780
  return unless effective_observation_request_to_event_mapping.keys.include?(keyword)
751
781
  event = nil
752
782
  delegate = nil
@@ -770,7 +800,11 @@ module Glimmer
770
800
  end
771
801
  the_listener_dom_element = event_element_css_selector ? Element[event_element_css_selector] : listener_dom_element
772
802
  unless the_listener_dom_element.empty?
773
- the_listener_dom_element.on(event, &async_event_listener)
803
+ if is_a?(DisplayProxy) && event == 'keydown'
804
+ `document.addEventListener('keydown', #{async_event_listener})`
805
+ else
806
+ the_listener_dom_element.on(event, &async_event_listener)
807
+ end
774
808
  # TODO ensure uniqueness of insertion (perhaps adding equals/hash method to event listener proxy)
775
809
 
776
810
  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)
@@ -886,6 +920,18 @@ module Glimmer
886
920
  # }
887
921
  # end,
888
922
  # },
923
+ MenuItemProxy => {
924
+ :selection => lambda do |observer|
925
+ on_widget_selected { |selection_event|
926
+ # TODO look into validity of this and perhaps move toggle logic to MenuItemProxy
927
+ if check?
928
+ observer.call(!selection)
929
+ else
930
+ observer.call(selection)
931
+ end
932
+ }
933
+ end
934
+ },
889
935
  ScaleProxy => {
890
936
  :selection => lambda do |observer|
891
937
  on_widget_selected { |selection_event|
@@ -1021,7 +1067,6 @@ require 'glimmer/swt/combo_proxy'
1021
1067
  require 'glimmer/swt/c_combo_proxy'
1022
1068
  require 'glimmer/swt/checkbox_proxy'
1023
1069
  require 'glimmer/swt/composite_proxy'
1024
- require 'glimmer/swt/dialog_proxy'
1025
1070
  require 'glimmer/swt/date_time_proxy'
1026
1071
  require 'glimmer/swt/group_proxy'
1027
1072
  require 'glimmer/swt/label_proxy'