Class: YogaLayout::Node
Overview
YogaLayout::Node is the main object you will be interfacing with when using Yoga in Ruby. YogaLayout::Node is a thin FFI wrapper around the core Yoga library.
Use Nodes to build up a tree that describes your layout. Set layout and style properties to define your layout constraints.
Once you have set up a tree of nodes with styles you will want to get the result of a layout calculation. Call #calculate_layout to perform layout calculation. Once this function returns the results of the layout calculation is stored on each node. Traverse the tree and retrieve the values from each node.
Instance Attribute Summary
Attributes inherited from Wrapper
#pointer
Class Method Summary
collapse
Instance Method Summary
collapse
Methods inherited from Wrapper
#==, auto_ptr, #inspect, map_method
Constructor Details
#initialize(auto_ptr = nil, config = nil) ⇒ Node
Returns a new instance of Node.
53
54
55
56
57
58
59
60
61
62
|
# File 'lib/yoga_layout/node.rb', line 53
def initialize(auto_ptr = nil, config = nil)
super(auto_ptr)
@children = []
@parent = nil
@data = nil
@measure_func = nil
@baseline_func = nil
@config = config
end
|
Class Method Details
.[](opts = {}) ⇒ Node
Quickly create a bunch of nodes with this handy node literal syntax.
24
25
26
27
28
29
30
31
|
# File 'lib/yoga_layout/node.rb', line 24
def self.[](opts = {})
children = opts.delete(:children) || []
node = new.set_styles(opts)
children.each_with_index do |child, idx|
node.insert_child(child, idx)
end
node
end
|
.layout_props ⇒ Object
113
114
115
|
# File 'lib/yoga_layout/node.rb', line 113
def self.layout_props
@layout_props ||= {}
end
|
Create a new Node with a specific config.
37
38
39
|
# File 'lib/yoga_layout/node.rb', line 37
def self.new_with_config(config)
new(auto_ptr(YogaLayout::Bindings.YGNodeNewWithConfig(config.pointer)), config)
end
|
.style_props ⇒ Object
109
110
111
|
# File 'lib/yoga_layout/node.rb', line 109
def self.style_props
@style_props ||= {}
end
|
.unsafe_free_pointer(pointer) ⇒ Object
This method is part of a private API.
You should avoid using this method if possible, as it may be removed or be changed in the future.
49
50
51
|
# File 'lib/yoga_layout/node.rb', line 49
def self.unsafe_free_pointer(pointer)
YogaLayout::Bindings.YGNodeFree(pointer)
end
|
.unsafe_new_pointer ⇒ Object
This method is part of a private API.
You should avoid using this method if possible, as it may be removed or be changed in the future.
43
44
45
|
# File 'lib/yoga_layout/node.rb', line 43
def self.unsafe_new_pointer
YogaLayout::Bindings.YGNodeNew
end
|
Instance Method Details
#calculate_layout(par_width = nil, par_height = nil, par_dir = nil) ⇒ Object
288
289
290
291
292
293
294
295
296
297
|
# File 'lib/yoga_layout/node.rb', line 288
def calculate_layout(par_width = nil, par_height = nil, par_dir = nil)
undefined = ::Float::NAN
YogaLayout::Bindings.YGNodeCalculateLayout(
pointer,
par_width || undefined,
par_height || undefined,
par_dir || :inherit
)
self
end
|
#get_baseline_func ⇒ Object
262
263
264
|
# File 'lib/yoga_layout/node.rb', line 262
def get_baseline_func
@baseline_func
end
|
#get_child(idx) ⇒ Object
211
212
213
214
215
216
217
218
219
|
# File 'lib/yoga_layout/node.rb', line 211
def get_child(idx)
ruby_child = @children[idx]
child_pointer = YogaLayout::Bindings.YGNodeGetChild(pointer, idx)
return nil if ruby_child.nil? && child_pointer.nil?
unless ruby_child && ruby_child.pointer.address == child_pointer.address
raise Error, "Ruby child #{ruby_child.inspect} (index #{idx}) does not wrap native child #{child_pointer}"
end
ruby_child
end
|
#get_measure_func ⇒ Object
247
248
249
|
# File 'lib/yoga_layout/node.rb', line 247
def get_measure_func
@measure_func
end
|
#get_parent ⇒ Object
223
224
225
226
227
228
229
230
231
|
# File 'lib/yoga_layout/node.rb', line 223
def get_parent
ruby_parent = parent
parent_pointer = YogaLayout::Bindings.YGNodeGetParent(pointer)
return nil if ruby_parent.nil? && parent_pointer.nil?
unless ruby_parent && ruby_parent.pointer == parent_pointer
raise Error, "Ruby parent #{ruby_parent.inspect} does not wrap native parent #{parent_pointer}"
end
ruby_parent
end
|
#has_children? ⇒ Boolean
284
285
286
|
# File 'lib/yoga_layout/node.rb', line 284
def has_children?
get_child_count != 0
end
|
#has_measure_func? ⇒ Boolean
280
281
282
|
# File 'lib/yoga_layout/node.rb', line 280
def has_measure_func?
get_measure_func != nil
end
|
#insert_child(node, idx) ⇒ Object
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
|
# File 'lib/yoga_layout/node.rb', line 183
def insert_child(node, idx)
unless node.is_a?(self.class)
raise TypeError, "Child #{node.inspect} must be a YogaLayout::Node"
end
if node.parent
raise Error, "Child #{node.inspect} already has a parent, it must be removed first."
end
if has_measure_func?
raise Error, 'Cannot add child: Nodes with measure functions cannot have children.'
end
YogaLayout::Bindings.YGNodeInsertChild(pointer, node.pointer, idx)
@children.insert(idx, node)
node.parent = self
self
end
|
#layout ⇒ Hash
Retrieve all layout information as a hash
94
95
96
97
98
|
# File 'lib/yoga_layout/node.rb', line 94
def layout
Hash[
self.class.layout_props.map { |method, prop| [prop, public_send(method)] }
]
end
|
#mark_dirty ⇒ Object
266
267
268
269
270
271
272
273
274
|
# File 'lib/yoga_layout/node.rb', line 266
def mark_dirty
unless has_measure_func?
raise Error, 'Only leaf nodes with custom measure functions should manually mark themselves as diry'
end
YogaLayout::Bindings.YGNodeMarkDirty(pointer)
self
end
|
#remove_child(node) ⇒ Object
202
203
204
205
206
207
208
209
|
# File 'lib/yoga_layout/node.rb', line 202
def remove_child(node)
YogaLayout::Bindings.YGNodeRemoveChild(pointer, node.pointer)
if @children.delete(node)
node.parent = nil
end
self
end
|
#reset ⇒ Object
168
169
170
171
172
173
174
175
176
177
178
179
180
181
|
# File 'lib/yoga_layout/node.rb', line 168
def reset
if has_children?
raise Error, 'Cannot reset a node which still has children attached'
end
unless parent.nil?
raise Error, 'Cannot reset a node still attached to a parent'
end
YogaLayout::Bindings.YGNodeReset(pointer)
@measure_func = nil
@baseline_func = nil
@data = nil
end
|
#set_baseline_func(callable = nil, &block) ⇒ Object
251
252
253
254
255
256
257
258
259
260
|
# File 'lib/yoga_layout/node.rb', line 251
def set_baseline_func(callable = nil, &block)
@baseline_func = callable || block
if @baseline_func
YogaLayout::Bindings.YGNodeSetBaselineFunc(pointer, native_baseline_func)
else
YogaLayout::Bindings.YGNodeSetBaselineFunc(pointer, nil)
end
self
end
|
#set_measure_func(callable = nil, &block) ⇒ Object
233
234
235
236
237
238
239
240
241
242
243
244
245
|
# File 'lib/yoga_layout/node.rb', line 233
def set_measure_func(callable = nil, &block)
if has_children?
raise Error, 'Cannot set measure function: Nodes with measure functions cannot have children.'
end
@measure_func = callable || block
if @measure_func
YogaLayout::Bindings.YGNodeSetMeasureFunc(pointer, native_measure_func)
else
YogaLayout::Bindings.YGNodeSetMeasureFunc(pointer, nil)
end
self
end
|
#set_styles(styles) ⇒ Node
Set many styles at once.
Uses ruby magic to make it easier to set styles.
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
# File 'lib/yoga_layout/node.rb', line 70
def set_styles(styles)
styles.each do |prop, value|
method_name = "style_set_#{prop}"
if respond_to?(method_name)
if method(method_name).arity == 1
public_send(method_name, value)
else
public_send(method_name, :all, value)
end
else
method_name, _, edge = method_name.rpartition('_')
public_send(method_name, edge.to_sym, value)
end
end
self
end
|
#styles ⇒ Hash
Retrieve all style information as a hash
103
104
105
106
107
|
# File 'lib/yoga_layout/node.rb', line 103
def styles
Hash[
self.class.style_props.map { |method, prop| [prop, public_send(method)] }
]
end
|