glimmer-dsl-opal 0.25.4 → 0.26.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d82f0649f5baefa289ee1facb6102608e4d84e5a98e84a775ab1112f1698cc3d
4
- data.tar.gz: da29c7ccd153e217867d2dd47afc7611311d79511461bb9395529a6561551cca
3
+ metadata.gz: 0deb6c6d04586f92d01c22a4228072fcfa145359121f33d92265c580fc1abd91
4
+ data.tar.gz: fc11c74ce51115dc92548debd2bf3a1d590ba638915de71f33455ee62a82c5fb
5
5
  SHA512:
6
- metadata.gz: 427deabace568823bb59fc9e09dbbbdc7c37c22c25dd131daa41fa61a88cc61a7cc746480d733b2862055fe798a05728ca1a809bacba839068ae346f9ce005da
7
- data.tar.gz: bf34f31729b7c49c25442f12292042c92faf9eeb97e02582d87ad25f548a201ba574af4d00d5280166235c157509b95c2e5412a9e06f3f3924ea2738c6a3555a
6
+ metadata.gz: e7849b84f8ee8c749c69636abbe7490a3ac2585957fa7c526b1a2a322eb40d7d1bfdba66e344c8f1f3b76095fb1a2ed5210ae62c08db093828be823f10fd9e33
7
+ data.tar.gz: 12125b86cdd30f321311e3909b8f50e4383eb2fea2938b4983d02a5860f0d3a056d50dce9d94abe7a68f557d1c374d998e3fcfb25de90edc1d3b936cc033f1b6
data/CHANGELOG.md CHANGED
@@ -1,8 +1,16 @@
1
1
  # Change Log
2
2
 
3
+ ## 0.26.0
4
+
5
+ - Tetris elaborate sample (minimal initial version of the one in Glimmer DSL for SWT)
6
+ - Support `menu_item` `selection` attribute data-binding for `:check` and `:radio` SWT styles
7
+ - Set 'custom_shell' data for custom shell on its body_root
8
+ - Provide parent_proxy on custom widgets as an alternative to parent for compatibility with Glimmer DSL for SWT
9
+ - Have custom widgets derive their parent from body root if not passed in explicitly
10
+
3
11
  ## 0.25.4
4
12
 
5
- - Upgrade to opal-async 1.4.0
13
+ - Upgrade to opal-async 1.4.0
6
14
  - Update Hello, Custom Widget! to utilize `Array#async_cycle` instead of `Array#cycle`
7
15
 
8
16
  ## 0.25.3
data/README.md CHANGED
@@ -196,6 +196,7 @@ Other [Glimmer](https://github.com/AndyObtiva/glimmer) DSL gems:
196
196
  - [Elaborate Samples](#elaborate-samples)
197
197
  - [Login](#login)
198
198
  - [Contact Manager](#contact-manager)
199
+ - [Tetris](#tetris)
199
200
  - [Tic Tac Toe](#tic-tac-toe)
200
201
  - [User Profile](#user-profile)
201
202
  - [Weather](#weather)
@@ -235,7 +236,7 @@ Alternatively, web developers may directly use [Glimmer DSL for Opal](https://ru
235
236
  ## Pre-requisites
236
237
 
237
238
  - Rails 5.2: [https://github.com/rails/rails/tree/5-2-stable](https://github.com/rails/rails/tree/5-2-stable)
238
- - Opal 1.0.4: [https://github.com/opal/opal](https://github.com/opal/opal)
239
+ - Opal 1.0.5: [https://github.com/opal/opal](https://github.com/opal/opal)
239
240
  - Opal-Rails 1.1.2: [https://github.com/opal/opal-rails](https://github.com/opal/opal-rails)
240
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)
241
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)
@@ -252,7 +253,7 @@ Please follow the following steps to setup.
252
253
  Install a Rails 5 gem:
253
254
 
254
255
  ```
255
- gem install rails -v5.2.4.4
256
+ gem install rails -v5.2.6
256
257
  ```
257
258
 
258
259
  Start a new Rails 5 app:
@@ -264,7 +265,7 @@ rails new glimmer_app_server
264
265
  Add the following to `Gemfile`:
265
266
 
266
267
  ```
267
- gem 'opal', '1.0.4'
268
+ gem 'opal', '1.0.5'
268
269
  gem 'opal-rails', '1.1.2'
269
270
  gem 'opal-async', '~> 1.4.0'
270
271
  gem 'opal-jquery', '~> 0.4.4'
@@ -2584,6 +2585,40 @@ Glimmer DSL for Opal Contact Manager Edit Done
2584
2585
 
2585
2586
  ![Glimmer DSL for Opal Contact Manager Edit Done](images/glimmer-dsl-opal-contact-manager-edit-done.png)
2586
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
+
2587
2622
  #### Tic Tac Toe
2588
2623
 
2589
2624
  Add the following require statement to `app/assets/javascripts/application.rb`
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.25.4
1
+ 0.26.0
@@ -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?
@@ -97,6 +97,7 @@ module Glimmer
97
97
  end
98
98
  event.define_singleton_method(:keyCode) {event.which}
99
99
  event.define_singleton_method(:key_code, &event.method(:keyCode))
100
+ # TODO support alt/ctrl/shift/command & arrow keys in keyCode
100
101
  event.define_singleton_method(:character) {event.which.chr}
101
102
  event.define_singleton_method(:stateMask) do
102
103
  state_mask = 0
@@ -135,6 +136,7 @@ module Glimmer
135
136
  end
136
137
  event.define_singleton_method(:keyCode) {event.which}
137
138
  event.define_singleton_method(:key_code, &event.method(:keyCode))
139
+ # TODO support alt/ctrl/shift/command & arrow keys in keyCode
138
140
  event.define_singleton_method(:character) {event.which.chr}
139
141
  event.define_singleton_method(:stateMask) do
140
142
  state_mask = 0
@@ -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
@@ -886,6 +916,18 @@ module Glimmer
886
916
  # }
887
917
  # end,
888
918
  # },
919
+ MenuItemProxy => {
920
+ :selection => lambda do |observer|
921
+ on_widget_selected { |selection_event|
922
+ # TODO look into validity of this and perhaps move toggle logic to MenuItemProxy
923
+ if check?
924
+ observer.call(!selection)
925
+ else
926
+ observer.call(selection)
927
+ end
928
+ }
929
+ end
930
+ },
889
931
  ScaleProxy => {
890
932
  :selection => lambda do |observer|
891
933
  on_widget_selected { |selection_event|
@@ -1021,7 +1063,6 @@ require 'glimmer/swt/combo_proxy'
1021
1063
  require 'glimmer/swt/c_combo_proxy'
1022
1064
  require 'glimmer/swt/checkbox_proxy'
1023
1065
  require 'glimmer/swt/composite_proxy'
1024
- require 'glimmer/swt/dialog_proxy'
1025
1066
  require 'glimmer/swt/date_time_proxy'
1026
1067
  require 'glimmer/swt/group_proxy'
1027
1068
  require 'glimmer/swt/label_proxy'
@@ -67,6 +67,8 @@ module Glimmer
67
67
 
68
68
  def initialize(parent, args, options, &content)
69
69
  super(parent, args, options, &content)
70
+ body_root.set_data('custom_shell', self)
71
+ body_root.set_data('custom_window', self)
70
72
  raise Error, 'Invalid custom shell body root! Must be a shell or another custom shell.' unless body_root.is_a?(Glimmer::SWT::ShellProxy) || body_root.is_a?(Glimmer::UI::CustomShell)
71
73
  end
72
74
 
@@ -158,6 +158,7 @@ module Glimmer
158
158
 
159
159
 
160
160
  attr_reader :body_root, :parent, :options, :swt_style
161
+ alias parent_proxy parent
161
162
 
162
163
  def initialize(parent, args, options, &content)
163
164
  @parent = parent
@@ -177,6 +178,7 @@ module Glimmer
177
178
  body_block = self.class.instance_variable_get("@body_block")
178
179
  raise Glimmer::Error, 'Invalid custom widget for having no body! Please define body block!' if body_block.nil?
179
180
  @body_root = instance_exec(&body_block)
181
+ @parent ||= @body_root.parent
180
182
  raise Glimmer::Error, 'Invalid custom widget for having an empty body! Please fill body block!' if @body_root.nil?
181
183
  execute_hooks('after_body')
182
184
  end