glimmer-dsl-opal 0.25.4 → 0.26.0

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