hokusai-zero 0.1.4 → 0.1.6
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 +4 -4
- data/README.md +31 -83
- data/ast/src/core/text.c +20 -0
- data/ext/extconf.rb +32 -10
- data/hokusai.gemspec +2 -1
- data/ui/examples/counter.rb +36 -28
- data/ui/examples/forum.rb +25 -24
- data/ui/examples/spreadsheet/csv.rb +3 -1
- data/ui/examples/spreadsheet.rb +4 -2
- data/ui/lib/lib_hokusai.rb +2 -0
- data/ui/src/hokusai/assets/arrow-drop-down-line.png +0 -0
- data/ui/src/hokusai/assets/chevron-down.svg +1 -0
- data/ui/src/hokusai/assets/close-large-line.png +0 -0
- data/ui/src/hokusai/backends/raylib.rb +17 -10
- data/ui/src/hokusai/backends/sdl2.rb +27 -0
- data/ui/src/hokusai/block.rb +36 -11
- data/ui/src/hokusai/blocks/cursor.rb +1 -1
- data/ui/src/hokusai/blocks/dropdown.rb +205 -0
- data/ui/src/hokusai/blocks/image.rb +2 -1
- data/ui/src/hokusai/blocks/input.rb +1 -1
- data/ui/src/hokusai/blocks/modal.rb +62 -0
- data/ui/src/hokusai/blocks/panel.rb +2 -2
- data/ui/src/hokusai/blocks/scrollbar.rb +0 -2
- data/ui/src/hokusai/blocks/text.rb +8 -5
- data/ui/src/hokusai/commands.rb +22 -7
- data/ui/src/hokusai/font.rb +1 -1
- data/ui/src/hokusai/meta.rb +1 -8
- data/ui/src/hokusai/mounting/loop_entry.rb +3 -3
- data/ui/src/hokusai/mounting/mount_entry.rb +7 -17
- data/ui/src/hokusai/node.rb +0 -9
- data/ui/src/hokusai/node_mounter.rb +3 -3
- data/ui/src/hokusai/painter.rb +65 -6
- data/ui/src/hokusai/util/clamping_iterator.rb +6 -4
- data/ui/src/hokusai.rb +17 -0
- metadata +21 -2
data/ui/src/hokusai/block.rb
CHANGED
@@ -30,6 +30,10 @@ module Hokusai
|
|
30
30
|
@provides ||= {}
|
31
31
|
end
|
32
32
|
|
33
|
+
def self.injectables
|
34
|
+
@injectables ||= []
|
35
|
+
end
|
36
|
+
|
33
37
|
# Sets the template for this block
|
34
38
|
#
|
35
39
|
# @param [String] template to set
|
@@ -118,16 +122,18 @@ module Hokusai
|
|
118
122
|
end
|
119
123
|
|
120
124
|
def self.inject(name, aliased = name)
|
125
|
+
injectables << name
|
126
|
+
|
121
127
|
define_method(aliased) do
|
122
|
-
|
123
|
-
provider.call
|
124
|
-
end
|
128
|
+
@injections[name]&.call
|
125
129
|
end
|
126
130
|
end
|
127
131
|
|
128
132
|
def self.inject!(name, aliased)
|
133
|
+
injectables << name
|
134
|
+
|
129
135
|
define_method(aliased) do
|
130
|
-
if provider =
|
136
|
+
if provider = @injections[name]
|
131
137
|
return provider.call
|
132
138
|
end
|
133
139
|
|
@@ -147,6 +153,25 @@ module Hokusai
|
|
147
153
|
raise Hokusai::Error.new("Must supply node argument to #{self.class}.new") unless args[:node]
|
148
154
|
|
149
155
|
@node = args[:node]
|
156
|
+
@injections = {}
|
157
|
+
|
158
|
+
self.class.injectables.each do |name|
|
159
|
+
if value = args[:providers][name]
|
160
|
+
@injections[name] = value
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def providers
|
166
|
+
self.class.provides.map do |k, v|
|
167
|
+
if v.is_a?(Symbol)
|
168
|
+
[k, -> { public_send(v) }]
|
169
|
+
elsif v.is_a?(Proc)
|
170
|
+
[k, v]
|
171
|
+
else
|
172
|
+
[k, -> { v }]
|
173
|
+
end
|
174
|
+
end.to_h
|
150
175
|
end
|
151
176
|
|
152
177
|
def children?
|
@@ -179,23 +204,23 @@ module Hokusai
|
|
179
204
|
|
180
205
|
def draw(&block)
|
181
206
|
instance_eval(&block)
|
182
|
-
# node.meta.commands.each(&:draw)
|
183
|
-
# node.meta.commands.clear!
|
184
207
|
end
|
185
208
|
|
186
209
|
def method_missing(name, *args,**kwargs, &block)
|
187
|
-
if
|
188
|
-
return
|
210
|
+
if node.meta.commands.respond_to?(name)
|
211
|
+
return node.meta.commands.send(name, *args, **kwargs, &block)
|
189
212
|
end
|
190
213
|
|
191
214
|
super
|
192
215
|
end
|
193
216
|
|
194
217
|
def draw_with
|
195
|
-
yield
|
218
|
+
yield node.meta.commands
|
219
|
+
end
|
196
220
|
|
197
|
-
|
198
|
-
|
221
|
+
def execute_draw
|
222
|
+
node.meta.commands.execute
|
223
|
+
node.meta.commands.clear!
|
199
224
|
end
|
200
225
|
|
201
226
|
def render(canvas)
|
@@ -9,7 +9,7 @@ class Hokusai::Blocks::Cursor < Hokusai::Block
|
|
9
9
|
computed :x, default: 0.0
|
10
10
|
computed :y, default: 0.0
|
11
11
|
computed :show, default: false
|
12
|
-
computed :speed, default: 0.
|
12
|
+
computed :speed, default: 0.5
|
13
13
|
computed :cursor_width, default: 2.0
|
14
14
|
computed :cursor_height, default: 0.0
|
15
15
|
computed :color, default: DEFAULT_COLOR, convert: Hokusai::Color
|
@@ -0,0 +1,205 @@
|
|
1
|
+
class Hokusai::Blocks::DropDownItem < Hokusai::Block
|
2
|
+
style <<~EOF
|
3
|
+
[style]
|
4
|
+
cursorStyle {
|
5
|
+
cursor: "pointer";
|
6
|
+
}
|
7
|
+
EOF
|
8
|
+
|
9
|
+
template <<~EOF
|
10
|
+
[template]
|
11
|
+
text {
|
12
|
+
@hover="hover_handler"
|
13
|
+
@mouseout="mouseout_handler"
|
14
|
+
...cursorStyle
|
15
|
+
:content="option"
|
16
|
+
:color="color"
|
17
|
+
:size="size"
|
18
|
+
@click="emit_option"
|
19
|
+
@height_updated="update_height"
|
20
|
+
}
|
21
|
+
EOF
|
22
|
+
|
23
|
+
uses(text: Hokusai::Blocks::Text)
|
24
|
+
|
25
|
+
computed! :index
|
26
|
+
computed! :option
|
27
|
+
computed! :size
|
28
|
+
computed! :color
|
29
|
+
|
30
|
+
attr_accessor :hovered
|
31
|
+
|
32
|
+
def hover_handler(event)
|
33
|
+
self.hovered = true
|
34
|
+
end
|
35
|
+
|
36
|
+
def mouseout_handler(event)
|
37
|
+
self.hovered = false
|
38
|
+
end
|
39
|
+
|
40
|
+
def update_height(height)
|
41
|
+
node.meta.set_prop(:height, height)
|
42
|
+
|
43
|
+
emit("height", index, height)
|
44
|
+
end
|
45
|
+
|
46
|
+
def emit_option(event)
|
47
|
+
emit("option", index)
|
48
|
+
end
|
49
|
+
|
50
|
+
def render(canvas)
|
51
|
+
if hovered
|
52
|
+
draw do
|
53
|
+
rect(canvas.x, canvas.y, canvas.width, canvas.height) do |command|
|
54
|
+
command.color = Hokusai::Color.new(255, 255, 255, 20)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
yield canvas
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class Hokusai::Blocks::Dropdown < Hokusai::Block
|
64
|
+
style <<~EOF
|
65
|
+
[style]
|
66
|
+
panelStyle {
|
67
|
+
z: 1;
|
68
|
+
}
|
69
|
+
rootStyle {
|
70
|
+
height: 70.0;
|
71
|
+
color: rgb(122, 118, 135);
|
72
|
+
}
|
73
|
+
|
74
|
+
cursorStyle {
|
75
|
+
cursor: "pointer";
|
76
|
+
}
|
77
|
+
EOF
|
78
|
+
|
79
|
+
template <<~EOF
|
80
|
+
[template]
|
81
|
+
vblock {
|
82
|
+
@hover="dropdown_hover"
|
83
|
+
@mouseout="dropdown_mouseout"
|
84
|
+
@click="dropdown_toggle"
|
85
|
+
:background="background"
|
86
|
+
:height="size_with_padding"
|
87
|
+
:outline="outline"
|
88
|
+
:outline_color="outline_color"
|
89
|
+
}
|
90
|
+
hblock
|
91
|
+
label {
|
92
|
+
...cursorStyle
|
93
|
+
:content="dropdown_option_selected"
|
94
|
+
:size="size"
|
95
|
+
:color="text_color"
|
96
|
+
}
|
97
|
+
image {
|
98
|
+
padding="5.0,10.0,5.0,5.0"
|
99
|
+
:source="dropdown_icon"
|
100
|
+
:height="size"
|
101
|
+
:width="size"
|
102
|
+
}
|
103
|
+
[if="dropdown_is_toggled"]
|
104
|
+
panel#first {
|
105
|
+
...panelStyle
|
106
|
+
:height="panel_height"
|
107
|
+
:background="background"
|
108
|
+
}
|
109
|
+
[for="option in options"]
|
110
|
+
dropdown_item {
|
111
|
+
:color="text_color"
|
112
|
+
:size="size"
|
113
|
+
:height="option_height(index)"
|
114
|
+
:option="option_content(option)"
|
115
|
+
:key="dropdown_key(option, index)"
|
116
|
+
:index="index"
|
117
|
+
@option="option_emit_selected"
|
118
|
+
@height="option_update_height"
|
119
|
+
}
|
120
|
+
EOF
|
121
|
+
|
122
|
+
uses(
|
123
|
+
vblock: Hokusai::Blocks::Vblock,
|
124
|
+
hblock: Hokusai::Blocks::Hblock,
|
125
|
+
label: Hokusai::Blocks::Text,
|
126
|
+
panel: Hokusai::Blocks::Panel,
|
127
|
+
image: Hokusai::Blocks::Image,
|
128
|
+
dropdown_item: Hokusai::Blocks::DropDownItem
|
129
|
+
)
|
130
|
+
|
131
|
+
computed! :options
|
132
|
+
computed :option_callback, default: ->(option) { option }
|
133
|
+
computed :size, default: 25, convert: proc(&:to_i)
|
134
|
+
computed :padding, default: Hokusai::Padding.new(5.0, 5.0, 5.0, 5.0), convert: Hokusai::Padding
|
135
|
+
computed :background, default: Hokusai::Color.new(67, 64, 92), convert: Hokusai::Color
|
136
|
+
computed :outline, default: Hokusai::Outline.new(0.0, 0.0, 1.0, 0.0), convert: Hokusai::Outline
|
137
|
+
computed :outline_color, default: Hokusai::Color.new(122, 118, 135), convert: Hokusai::Color
|
138
|
+
computed :text_color, default: Hokusai::Color.new(255, 255, 255), convert: Hokusai::Color
|
139
|
+
computed :panel_width, default: 200.0, convert: proc(&:to_f)
|
140
|
+
computed :panel_height, default: 300.0, convert: proc(&:to_f)
|
141
|
+
computed :icon, default: "#{ASSETS_FOLDER}/arrow-drop-down-line.png"
|
142
|
+
|
143
|
+
attr_accessor :selected, :dropdown_is_toggled, :hovered
|
144
|
+
attr_reader :heights
|
145
|
+
|
146
|
+
def dropdown_icon
|
147
|
+
icon
|
148
|
+
end
|
149
|
+
|
150
|
+
def dropdown_hover(event)
|
151
|
+
self.hovered = true
|
152
|
+
end
|
153
|
+
|
154
|
+
def dropdown_mouseout(event)
|
155
|
+
self.hovered = false
|
156
|
+
end
|
157
|
+
|
158
|
+
def size_with_padding
|
159
|
+
size + padding.top + padding.bottom
|
160
|
+
end
|
161
|
+
|
162
|
+
def dropdown_key(option, index)
|
163
|
+
"option-#{option_callback.call(option)}-#{index}"
|
164
|
+
end
|
165
|
+
|
166
|
+
def dropdown_toggle(event)
|
167
|
+
self.dropdown_is_toggled = !dropdown_is_toggled
|
168
|
+
end
|
169
|
+
|
170
|
+
def dropdown_option_selected
|
171
|
+
option_callback.call(selected)
|
172
|
+
end
|
173
|
+
|
174
|
+
def option_height(index)
|
175
|
+
heights[index]
|
176
|
+
end
|
177
|
+
|
178
|
+
def option_update_height(index, height)
|
179
|
+
heights[index] = height
|
180
|
+
end
|
181
|
+
|
182
|
+
def option_content(option)
|
183
|
+
option_callback.call(option)
|
184
|
+
end
|
185
|
+
|
186
|
+
def after_updated
|
187
|
+
node.meta.set_prop(:height, size * 2)
|
188
|
+
end
|
189
|
+
|
190
|
+
def option_emit_selected(index)
|
191
|
+
emit("selected", options[index])
|
192
|
+
|
193
|
+
self.selected = options[index]
|
194
|
+
self.dropdown_is_toggled = false
|
195
|
+
end
|
196
|
+
|
197
|
+
def initialize(**args)
|
198
|
+
super
|
199
|
+
|
200
|
+
@hovered = false
|
201
|
+
@heights = {}
|
202
|
+
@dropdown_is_toggled = false
|
203
|
+
@selected = options.first
|
204
|
+
end
|
205
|
+
end
|
@@ -9,12 +9,13 @@ class Hokusai::Blocks::Image < Hokusai::Block
|
|
9
9
|
computed! :source
|
10
10
|
computed :width, default: nil
|
11
11
|
computed :height, default: nil
|
12
|
+
computed :padding, default: Hokusai::Padding.new(0.0, 0.0, 0.0, 0.0), convert: Hokusai::Padding
|
12
13
|
|
13
14
|
def render(canvas)
|
14
15
|
src = Pathname.new(source).absolute? ? source : "#{File.dirname(caller[-1].split(":")[0])}/#{source}"
|
15
16
|
|
16
17
|
draw do
|
17
|
-
image(src, canvas.x, canvas.y, width&.to_f || canvas.width, height&.to_f || canvas.height)
|
18
|
+
image(src, canvas.x + padding.left, canvas.y + padding.top, (width&.to_f || canvas.width) - padding.right, (height&.to_f || canvas.height) - padding.bottom)
|
18
19
|
end
|
19
20
|
|
20
21
|
yield canvas
|
@@ -195,7 +195,7 @@ class Hokusai::Blocks::Input < Hokusai::Block
|
|
195
195
|
flush
|
196
196
|
|
197
197
|
if table.pieces.size > 10
|
198
|
-
self.table = Util::PieceTable.new(table.to_s)
|
198
|
+
self.table = ::Hokusai::Util::PieceTable.new(table.to_s)
|
199
199
|
end
|
200
200
|
|
201
201
|
self.start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
@@ -0,0 +1,62 @@
|
|
1
|
+
class Hokusai::Blocks::Modal < Hokusai::Block
|
2
|
+
style <<~EOF
|
3
|
+
[style]
|
4
|
+
closeButtonStyle {
|
5
|
+
width: 40;
|
6
|
+
height: 40;
|
7
|
+
cursor: "pointer";
|
8
|
+
padding: padding(10.0, 10.0, 10.0, 0.0)
|
9
|
+
}
|
10
|
+
EOF
|
11
|
+
|
12
|
+
template <<~EOF
|
13
|
+
[template]
|
14
|
+
hblock
|
15
|
+
empty
|
16
|
+
empty
|
17
|
+
image {
|
18
|
+
:source="close_icon"
|
19
|
+
...closeButtonStyle
|
20
|
+
@click="emit_close"
|
21
|
+
|
22
|
+
}
|
23
|
+
hblock
|
24
|
+
empty
|
25
|
+
slot
|
26
|
+
empty
|
27
|
+
hblock
|
28
|
+
empty
|
29
|
+
EOF
|
30
|
+
|
31
|
+
uses(
|
32
|
+
vblock: Hokusai::Blocks::Vblock,
|
33
|
+
hblock: Hokusai::Blocks::Hblock,
|
34
|
+
empty: Hokusai::Blocks::Empty,
|
35
|
+
image: Hokusai::Blocks::Image
|
36
|
+
)
|
37
|
+
|
38
|
+
computed :active, default: false
|
39
|
+
computed :background, default: [0, 0, 0, 200], convert: Hokusai::Color
|
40
|
+
computed :close_icon, default: "#{ASSETS_FOLDER}/close-large-line.png"
|
41
|
+
|
42
|
+
def emit_close(event)
|
43
|
+
emit("close")
|
44
|
+
end
|
45
|
+
|
46
|
+
def on_mounted
|
47
|
+
node.meta.set_prop(:z, 1)
|
48
|
+
node.meta.set_prop(:ztarget, "root")
|
49
|
+
end
|
50
|
+
|
51
|
+
def render(canvas)
|
52
|
+
return unless active
|
53
|
+
|
54
|
+
draw do
|
55
|
+
rect(canvas.x, canvas.y, canvas.width, canvas.height) do |command|
|
56
|
+
command.color = background
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
yield canvas
|
61
|
+
end
|
62
|
+
end
|
@@ -62,8 +62,8 @@ class Hokusai::Blocks::Panel < Hokusai::Block
|
|
62
62
|
if y = top
|
63
63
|
if new_scroll_y < y
|
64
64
|
self.scroll_goto_y = y
|
65
|
-
elsif new_scroll_y
|
66
|
-
self.scroll_goto_y = panel_height
|
65
|
+
elsif new_scroll_y - top >= panel_height
|
66
|
+
self.scroll_goto_y = panel_height if scroll_percent != 1.0
|
67
67
|
else
|
68
68
|
self.scroll_goto_y = new_scroll_y
|
69
69
|
end
|
@@ -15,6 +15,7 @@ class Hokusai::Blocks::Text < Hokusai::Block
|
|
15
15
|
uses(empty: Hokusai::Blocks::Empty)
|
16
16
|
|
17
17
|
computed! :content
|
18
|
+
computed :cursor, default: nil
|
18
19
|
computed :font, default: nil
|
19
20
|
computed :size, default: 16, convert: proc(&:to_i)
|
20
21
|
computed :line_height, default: 5, convert: proc(&:to_f)
|
@@ -68,7 +69,7 @@ class Hokusai::Blocks::Text < Hokusai::Block
|
|
68
69
|
iterator.on_draw do |text, x, y, group|
|
69
70
|
if selector = selection
|
70
71
|
if cursor_offset&.zero? && !selector.started
|
71
|
-
selector.cursor = [x, y + offset_y, 0.0, size.to_f]
|
72
|
+
# selector.cursor = [x, y + offset_y, 0.0, size.to_f]
|
72
73
|
|
73
74
|
self.last_cursor_offset = cursor_offset
|
74
75
|
end
|
@@ -112,6 +113,8 @@ class Hokusai::Blocks::Text < Hokusai::Block
|
|
112
113
|
system("open #{group.link}")
|
113
114
|
when /linux/
|
114
115
|
system("xdg-open #{group.link}")
|
116
|
+
when /msys|mingw/
|
117
|
+
system("Start-Process \"#{group.link}\"")
|
115
118
|
end
|
116
119
|
|
117
120
|
self.click_position = nil
|
@@ -125,9 +128,9 @@ class Hokusai::Blocks::Text < Hokusai::Block
|
|
125
128
|
end
|
126
129
|
|
127
130
|
iterator.on_draw_selection do |x, y, width, height|
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
+
commands.rect(x, y, width, height) do |command|
|
132
|
+
command.color = selection_color
|
133
|
+
end
|
131
134
|
end
|
132
135
|
|
133
136
|
iterator.on_selection_change do |start, stop|
|
@@ -170,7 +173,7 @@ class Hokusai::Blocks::Text < Hokusai::Block
|
|
170
173
|
end
|
171
174
|
end
|
172
175
|
|
173
|
-
if link_hovered
|
176
|
+
if link_hovered || cursor == "pointer"
|
174
177
|
Hokusai.set_mouse_cursor(:pointer)
|
175
178
|
elsif hovered
|
176
179
|
Hokusai.set_mouse_cursor(:ibeam)
|
data/ui/src/hokusai/commands.rb
CHANGED
@@ -15,7 +15,9 @@ module Hokusai
|
|
15
15
|
class Commands
|
16
16
|
attr_reader :queue
|
17
17
|
|
18
|
-
def initialize
|
18
|
+
def initialize
|
19
|
+
@queue = []
|
20
|
+
end
|
19
21
|
|
20
22
|
# Draw a rectangle
|
21
23
|
#
|
@@ -28,7 +30,8 @@ module Hokusai
|
|
28
30
|
|
29
31
|
yield(command)
|
30
32
|
|
31
|
-
command
|
33
|
+
queue << command
|
34
|
+
# command.draw
|
32
35
|
end
|
33
36
|
|
34
37
|
# Draw a circle
|
@@ -41,7 +44,9 @@ module Hokusai
|
|
41
44
|
|
42
45
|
yield(command)
|
43
46
|
|
44
|
-
|
47
|
+
|
48
|
+
queue << command
|
49
|
+
# command.draw
|
45
50
|
end
|
46
51
|
|
47
52
|
# Draws an SVG
|
@@ -55,23 +60,25 @@ module Hokusai
|
|
55
60
|
command = Commands::SVG.new(source, x, y, w, h)
|
56
61
|
|
57
62
|
yield(command)
|
63
|
+
|
64
|
+
queue << command
|
58
65
|
end
|
59
66
|
|
60
67
|
# Invokes an image command
|
61
68
|
# from a filename, at position {x,y} with `w`x`h` dimensions
|
62
69
|
def image(source, x, y, w, h)
|
63
|
-
Commands::Image.new(source, x, y, w, h)
|
70
|
+
queue << Commands::Image.new(source, x, y, w, h)
|
64
71
|
end
|
65
72
|
|
66
73
|
# Invokes a scissor begin command
|
67
74
|
# at position {x,y} with `w`x`h` dimensions
|
68
75
|
def scissor_begin(x, y, w, h)
|
69
|
-
Commands::ScissorBegin.new(x, y, w, h)
|
76
|
+
queue << Commands::ScissorBegin.new(x, y, w, h)
|
70
77
|
end
|
71
78
|
|
72
79
|
# Invokes a scissor stop command
|
73
80
|
def scissor_end
|
74
|
-
Commands::ScissorEnd.new
|
81
|
+
queue << Commands::ScissorEnd.new
|
75
82
|
end
|
76
83
|
|
77
84
|
# Draws text
|
@@ -83,7 +90,15 @@ module Hokusai
|
|
83
90
|
command = Commands::Text.new(content, x, y)
|
84
91
|
yield command
|
85
92
|
|
86
|
-
command
|
93
|
+
queue << command
|
94
|
+
end
|
95
|
+
|
96
|
+
def execute
|
97
|
+
queue.each(&:draw)
|
98
|
+
end
|
99
|
+
|
100
|
+
def clear!
|
101
|
+
queue.clear
|
87
102
|
end
|
88
103
|
end
|
89
104
|
end
|
data/ui/src/hokusai/font.rb
CHANGED
@@ -224,7 +224,7 @@ module Hokusai
|
|
224
224
|
end
|
225
225
|
|
226
226
|
def char_is_selected(char)
|
227
|
-
return false if select_begin.nil? || select_end.nil?
|
227
|
+
return false if select_begin.nil? || select_end.nil? || (select_end - select_begin).zero?
|
228
228
|
|
229
229
|
(select_begin..select_end).include?(char.offset)
|
230
230
|
end
|
data/ui/src/hokusai/meta.rb
CHANGED
@@ -5,7 +5,7 @@ module Hokusai
|
|
5
5
|
attr_reader :focused, :parent, :target, :updater,
|
6
6
|
:props, :publisher
|
7
7
|
|
8
|
-
def
|
8
|
+
def commands
|
9
9
|
@commands ||= Commands.new
|
10
10
|
end
|
11
11
|
|
@@ -126,13 +126,6 @@ module Hokusai
|
|
126
126
|
|
127
127
|
false
|
128
128
|
end
|
129
|
-
#
|
130
|
-
# def destroy
|
131
|
-
# children.each do |child|
|
132
|
-
# child.before_destroy if child.respond_to?(:before_destroy)
|
133
|
-
# child.node.destroy
|
134
|
-
# end
|
135
|
-
# end
|
136
129
|
|
137
130
|
def child_delete(index)
|
138
131
|
if child = children![index]
|
@@ -27,7 +27,7 @@ module Hokusai
|
|
27
27
|
|
28
28
|
INDEX_KEY = "index".freeze
|
29
29
|
|
30
|
-
def_delegators :@entry, :ast, :block, :target, :parent
|
30
|
+
def_delegators :@entry, :ast, :block, :target, :parent, :providers
|
31
31
|
|
32
32
|
def initialize(mount_entry)
|
33
33
|
@entry = mount_entry
|
@@ -78,12 +78,12 @@ module Hokusai
|
|
78
78
|
block.node.meta << child_block
|
79
79
|
|
80
80
|
node.ast.children.each_with_index do |child, idx|
|
81
|
-
entries_to_return << MountEntry.new(index, child, child_block, child_block, child_block, context: nil)
|
81
|
+
entries_to_return << MountEntry.new(index, child, child_block, child_block, child_block, context: nil, providers: providers.merge(child_block.providers))
|
82
82
|
end
|
83
83
|
|
84
84
|
siblings = []
|
85
85
|
portal.ast.children.each_with_index do |child, idx|
|
86
|
-
siblings << MountEntry.new(idx, child, child_block, child_block, target, context: ctx)
|
86
|
+
siblings << MountEntry.new(idx, child, child_block, child_block, target, context: ctx, providers: providers.merge(child_block.providers))
|
87
87
|
end
|
88
88
|
|
89
89
|
secondary_entries << siblings
|
@@ -1,14 +1,15 @@
|
|
1
1
|
module Hokusai
|
2
2
|
module Mounting
|
3
3
|
class MountEntry
|
4
|
-
attr_reader :block, :parent, :ast, :target, :index, :ctx
|
4
|
+
attr_reader :block, :parent, :ast, :target, :index, :ctx, :providers
|
5
5
|
|
6
|
-
def initialize(index, ast, block, parent, target = parent, context: nil)
|
6
|
+
def initialize(index, ast, block, parent, target = parent, context: nil, providers: {})
|
7
7
|
@index = index
|
8
8
|
@ast = ast
|
9
9
|
@block = block
|
10
10
|
@parent = parent
|
11
11
|
@target = target
|
12
|
+
@providers = providers
|
12
13
|
@ctx = context
|
13
14
|
end
|
14
15
|
|
@@ -28,6 +29,7 @@ module Hokusai
|
|
28
29
|
StringIO.open do |io|
|
29
30
|
io << "#{block.class} | #{ast.type} (#{index})\n"
|
30
31
|
io << "#{block.node.ast.children.map(&:type)}"
|
32
|
+
io << "providers: #{providers.map {|k,v| k }.join(", ")}\n"
|
31
33
|
io << "parent: #{parent.class}\n"
|
32
34
|
io << "target: #{target.class}\n\n"
|
33
35
|
end.string
|
@@ -35,7 +37,7 @@ module Hokusai
|
|
35
37
|
|
36
38
|
def with_block(new_block, supercede_parent: false)
|
37
39
|
parent_block = supercede_parent ? block : parent
|
38
|
-
MountEntry.new(index, ast, new_block, parent_block, target, context: ctx)
|
40
|
+
MountEntry.new(index, ast, new_block, parent_block, target, context: ctx, providers: providers)
|
39
41
|
end
|
40
42
|
|
41
43
|
def mount(context: nil)
|
@@ -46,23 +48,11 @@ module Hokusai
|
|
46
48
|
node.add_styles(target.class)
|
47
49
|
node.add_props_from_block(target, context: context || ctx)
|
48
50
|
|
49
|
-
|
51
|
+
# handle provides / dependency injection
|
52
|
+
child_block = klass.new(node: node, providers: providers)
|
50
53
|
child_block.node.meta.publisher.add(target) # todo
|
51
54
|
UpdateEntry.new(child_block, block, target).register(context: context || ctx)
|
52
55
|
|
53
|
-
block.class.provides.each do |k, v|
|
54
|
-
if v.is_a?(Symbol)
|
55
|
-
Node.provide(child_block.node, k, ->{ block.public_send(v) })
|
56
|
-
|
57
|
-
# child_block.node.meta.provides[k] = -> { block.public_send(v) }
|
58
|
-
# child_block.class.provides[k] = -> { block.public_send(v) }
|
59
|
-
else
|
60
|
-
Node.provide(child_block.node, k, v)
|
61
|
-
# child_block.node.meta.provides[k] = v
|
62
|
-
# child_block.class.provides[k] = v
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
56
|
block.node.meta << child_block
|
67
57
|
|
68
58
|
yield child_block
|
data/ui/src/hokusai/node.rb
CHANGED
@@ -12,15 +12,6 @@ module Hokusai
|
|
12
12
|
|
13
13
|
def_delegators :@ast, :slot?, :type, :event
|
14
14
|
|
15
|
-
def self.provides
|
16
|
-
@provides ||= {}
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.provide(node, key, value)
|
20
|
-
provides[node.uuid] ||= {}
|
21
|
-
provides[node.uuid][key] = value
|
22
|
-
end
|
23
|
-
|
24
15
|
def self.parse(template, name = "root", parent = nil)
|
25
16
|
ast = Ast.parse(template, name)
|
26
17
|
|