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 +4 -4
- data/CHANGELOG.md +9 -1
- data/README.md +38 -3
- data/VERSION +1 -1
- data/lib/glimmer/dsl/opal/menu_expression.rb +0 -3
- data/lib/glimmer/swt/control_editor.rb +2 -2
- data/lib/glimmer/swt/dialog_proxy.rb +11 -4
- data/lib/glimmer/swt/display_proxy.rb +2 -0
- data/lib/glimmer/swt/shell_proxy.rb +28 -1
- data/lib/glimmer/swt/table_item_proxy.rb +0 -20
- data/lib/glimmer/swt/table_proxy.rb +4 -0
- data/lib/glimmer/swt/widget_proxy.rb +48 -7
- data/lib/glimmer/ui/custom_shell.rb +2 -0
- data/lib/glimmer/ui/custom_widget.rb +2 -0
- data/lib/glimmer-dsl-opal/samples/elaborate/tetris/model/block.rb +48 -0
- data/lib/glimmer-dsl-opal/samples/elaborate/tetris/model/game.rb +275 -0
- data/lib/glimmer-dsl-opal/samples/elaborate/tetris/model/past_game.rb +39 -0
- data/lib/glimmer-dsl-opal/samples/elaborate/tetris/model/tetromino.rb +329 -0
- data/lib/glimmer-dsl-opal/samples/elaborate/tetris/view/block.rb +41 -0
- data/lib/glimmer-dsl-opal/samples/elaborate/tetris/view/high_score_dialog.rb +122 -0
- data/lib/glimmer-dsl-opal/samples/elaborate/tetris/view/playfield.rb +56 -0
- data/lib/glimmer-dsl-opal/samples/elaborate/tetris/view/score_lane.rb +87 -0
- data/lib/glimmer-dsl-opal/samples/elaborate/tetris/view/tetris_menu_bar.rb +136 -0
- data/lib/glimmer-dsl-opal/samples/elaborate/tetris.rb +166 -0
- data/lib/glimmer-dsl-opal.rb +1 -0
- metadata +12 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0deb6c6d04586f92d01c22a4228072fcfa145359121f33d92265c580fc1abd91
|
4
|
+
data.tar.gz: fc11c74ce51115dc92548debd2bf3a1d590ba638915de71f33455ee62a82c5fb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
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.
|
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.
|
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.
|
1
|
+
0.26.0
|
@@ -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 <
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|