Class: Hokusai::Block
- Inherits:
-
Object
show all
- Defined in:
- ui/src/hokusai/block.rb
Overview
A UI Component
Blocks are reusable and can be mounted in other blocks via templates
Blocks have ‘props“ and emit `events`
Direct Known Subclasses
Demos::Buddy::App, Demos::Clock, Demos::Counter, Demos::Demo::App, Demos::Demo::Post, Demos::Dynamic::App, Demos::Dynamic::Block, Demos::Forum::App, Demos::Forum::FileBlock, Demos::Forum::MusicBlock, Demos::Forum::PostBlock, Demos::Spreadsheet::App, Demos::Spreadsheet::CSV, Demos::Spreadsheet::Cell, Demos::Spreadsheet::Row, Demos::StockDecider::App, Demos::StockDecider::StackedBar, Demos::Test::App, Demos::TicTacToe::App, Demos::TicTacToe::Row, Demos::TicTacToe::Square, Hokusai::Blocks::Button, Hokusai::Blocks::Checkbox, Hokusai::Blocks::Circle, Hokusai::Blocks::Clipped, Hokusai::Blocks::Cursor, Hokusai::Blocks::Dynamic, Hokusai::Blocks::Empty, Hokusai::Blocks::Hblock, Hokusai::Blocks::Image, Hokusai::Blocks::Input, Hokusai::Blocks::Label, Hokusai::Blocks::Panel, Hokusai::Blocks::Rect, Hokusai::Blocks::SVG, Hokusai::Blocks::ScissorBegin, Hokusai::Blocks::ScissorEnd, Hokusai::Blocks::Scrollbar, Hokusai::Blocks::Selectable, Hokusai::Blocks::Text, Hokusai::Blocks::Titlebar::OSX, Hokusai::Blocks::Toggle, Hokusai::Blocks::Variable, Hokusai::Blocks::Vblock
Instance Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
Constructor Details
#initialize(**args) ⇒ Block
Returns a new instance of Block.
146
147
148
149
150
|
# File 'ui/src/hokusai/block.rb', line 146
def initialize(**args)
raise Hokusai::Error.new("Must supply node argument to #{self.class}.new") unless args[:node]
@node = args[:node]
end
|
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(name, *args, **kwargs, &block) ⇒ Object
186
187
188
189
190
191
192
|
# File 'ui/src/hokusai/block.rb', line 186
def method_missing(name, *args,**kwargs, &block)
if Hokusai::Meta.commands.respond_to?(name)
return Hokusai::Meta.commands.send(name, *args, **kwargs, &block)
end
super
end
|
Instance Attribute Details
#node ⇒ Object
Returns the value of attribute node.
13
14
15
|
# File 'ui/src/hokusai/block.rb', line 13
def node
@node
end
|
#provides ⇒ Object
Returns the value of attribute provides.
15
16
17
|
# File 'ui/src/hokusai/block.rb', line 15
def provides
@provides
end
|
#publisher ⇒ Object
Returns the value of attribute publisher.
14
15
16
|
# File 'ui/src/hokusai/block.rb', line 14
def publisher
@publisher
end
|
Class Method Details
.compile(name = "root", parent_node = nil) ⇒ Object
138
139
140
|
# File 'ui/src/hokusai/block.rb', line 138
def self.compile(name = "root", parent_node = nil)
Node.parse(template_get, name, parent_node)
end
|
.computed(name, **args) ⇒ Object
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
# File 'ui/src/hokusai/block.rb', line 87
def self.computed(name, **args)
define_method(name) do
prop = node.meta.get_prop(name.to_sym)
if prop.nil?
prop = args[:default]
end
if prop.nil?
return
end
case args[:convert]
when Proc
args[:convert].call(prop)
when NilClass
prop
else
if args[:convert].respond_to?(:convert)
args[:convert].convert(prop)
else
raise Hokusai::Error.new("Prop converter #{args[:convert]} requires a convert method `.convert(value) => #{args[:convert]}`")
end
end
end
end
|
.computed!(name) ⇒ Object
114
115
116
117
118
|
# File 'ui/src/hokusai/block.rb', line 114
def self.computed!(name)
define_method(name.to_sym) do
return node.meta.get_prop(name.to_sym) || (raise Hokusai::Error.new("Missing prop: #{name} on #{self.class}"))
end
end
|
.inject(name, aliased = name) ⇒ Object
120
121
122
123
124
125
126
|
# File 'ui/src/hokusai/block.rb', line 120
def self.inject(name, aliased = name)
define_method(aliased) do
if provider = Node.provides[node.uuid]&.[](name)
provider.call
end
end
end
|
.inject!(name, aliased) ⇒ Object
128
129
130
131
132
133
134
135
136
|
# File 'ui/src/hokusai/block.rb', line 128
def self.inject!(name, aliased)
define_method(aliased) do
if provider = Node.provides[node.uuid]&.[](name)
return provider.call
end
raise Hokusai::Error.new("No provision for #{name}")
end
end
|
.mount(name = "root", parent_node = nil) ⇒ Object
142
143
144
|
# File 'ui/src/hokusai/block.rb', line 142
def self.mount(name = "root", parent_node = nil)
compile(name, parent_node).mount(self)
end
|
.provide(name, value = nil, &block) ⇒ Object
17
18
19
20
21
22
23
24
25
26
27
|
# File 'ui/src/hokusai/block.rb', line 17
def self.provide(name, value = nil, &block)
if block_given?
provides[name] = block
else
if value.is_a?(Symbol)
provides[name] = value
else
provides[name] = ->{value}
end
end
end
|
.provides ⇒ Object
29
30
31
|
# File 'ui/src/hokusai/block.rb', line 29
def self.provides
@provides ||= {}
end
|
.style(template) ⇒ Object
41
42
43
44
45
46
47
48
|
# File 'ui/src/hokusai/block.rb', line 41
def self.style(template)
case template
when String
@styles = Hokusai::Style.parse(template)
when Hokusai::Style
@styles = template
end
end
|
.styles_get ⇒ Object
65
66
67
|
# File 'ui/src/hokusai/block.rb', line 65
def self.styles_get
@styles || {}
end
|
.template(template) ⇒ Object
Sets the template for this block
36
37
38
39
|
# File 'ui/src/hokusai/block.rb', line 36
def self.template(template)
@template = template
@uses ||= {}
end
|
.template_from_file(path) ⇒ Object
Sets the template for this block Uses a file
54
55
56
|
# File 'ui/src/hokusai/block.rb', line 54
def self.template_from_file(path)
@template = File.read(path)
end
|
.template_get ⇒ String
Fetches the template for this block
61
62
63
|
# File 'ui/src/hokusai/block.rb', line 61
def self.template_get
@template || (raise Hokusai::Error.new("Must define template for #{self}"))
end
|
.use(type) ⇒ Object
79
80
81
82
83
84
85
|
# File 'ui/src/hokusai/block.rb', line 79
def self.use(type)
if block_klass = @uses[type]
block_klass
else
raise Hokusai::Error.new("Type #{type} is not used on #{self}")
end
end
|
.uses(**args) ⇒ Object
Defines blocks that this block uses in it’s template Keys map to template node names, values map to a ‘Hokusai::Block`
71
72
73
74
75
76
77
|
# File 'ui/src/hokusai/block.rb', line 71
def self.uses(**args)
args.each do |key, value|
raise Hokusai::Error.new("#{key} value must be a Block, got #{value}") unless value.is_a?(Block.class)
@uses[key.to_s.downcase] = value
end
end
|
Instance Method Details
#children ⇒ Object
156
157
158
|
# File 'ui/src/hokusai/block.rb', line 156
def children
node.meta.children!
end
|
#children? ⇒ Boolean
152
153
154
|
# File 'ui/src/hokusai/block.rb', line 152
def children?
node.meta.children?
end
|
#draw(&block) ⇒ Object
180
181
182
183
184
|
# File 'ui/src/hokusai/block.rb', line 180
def draw(&block)
instance_eval(&block)
end
|
#draw_with {|Hokusai::Meta.commands| ... } ⇒ Object
194
195
196
197
198
199
|
# File 'ui/src/hokusai/block.rb', line 194
def draw_with
yield Hokusai::Meta.commands
end
|
#dump(level = 1, show_props: false) ⇒ Object
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
|
# File 'ui/src/hokusai/block.rb', line 207
def dump(level = 1, show_props: false)
io = ""
io << "#{self.class}"
io << " if " if node.ast.has_if_condition?
io << "(#{node.type})"
if portal = node.portal
io << ".#{portal.ast.classes.join(".")}"
end
io << "\n"
if node.meta.props!.values.size > 0 && show_props
io << "#{" " * level * 2}{\n"
node.meta.props!.each do |key, value|
io << "#{" " * level * 3}#{key} = #{value}\n"
end
unless node.portal.nil?
node.portal.ast.events.each do |_, event|
io << "#{" " * level * 3}@#{event.name} = #{event.value.method} #{!!node.portal.ast.event(event.name)}\n"
end
end
io << "#{" " * level * 2}}\n"
end
if children.nil?
io << "#{" " * level * 2}(no children)\n"
else
child_dump = children?&.map {|child| child.dump(level + 1, show_props: show_props) }
io << "#{" " * level * 2}#{child_dump.join("#{" " * level * 2}") }\n"
end
io
end
|
#emit(name, *args, **kwargs) ⇒ Object
172
173
174
175
176
177
178
|
# File 'ui/src/hokusai/block.rb', line 172
def emit(name, *args, **kwargs)
if portal = node.portal
if event = portal.event(name)
node.meta.publisher.notify(event.value.method, *args, **kwargs)
end
end
end
|
#on_resize(canvas) ⇒ Object
205
|
# File 'ui/src/hokusai/block.rb', line 205
def on_resize(canvas); end
|
#render(canvas) {|canvas| ... } ⇒ Object
201
202
203
|
# File 'ui/src/hokusai/block.rb', line 201
def render(canvas)
yield(canvas)
end
|
#update ⇒ Object
160
161
162
163
164
165
166
167
168
169
170
|
# File 'ui/src/hokusai/block.rb', line 160
def update
node.meta.children?&.each do |child|
child.before_updated if child.respond_to?(:before_updated)
end
node.meta.update(self)
node.meta.children?&.each do |child|
child.after_updated if child.respond_to?(:after_updated)
end
end
|