Class: Tuile::Component::Layout
- Inherits:
-
Component
- Object
- Component
- Tuile::Component::Layout
- Defined in:
- lib/tuile/component/layout.rb,
sig/tuile.rbs
Overview
A layout doesn't paint anything by itself: its job is to position child components.
Children that fully tile the layout's rect repaint themselves and cover everything; children that leave gaps (e.g. a form with widgets of varying widths) trigger #repaint's default behavior — the background is cleared and children are re-invalidated so they paint over a clean surface.
Defined Under Namespace
Classes: Absolute
Instance Method Summary collapse
-
#add(child) ⇒ void
Adds a child component to this layout.
- #children ⇒ Array<Component>
-
#focusable? ⇒ Boolean
Layouts are focusable containers — like Window and Popup, they don't accept input themselves but they need to participate in the HasContent focus cascade so a Popup wrapping a Layout wrapping a TextField ends up focusing the field rather than parking focus on the popup.
-
#handle_mouse(event) ⇒ void
Dispatches the event to the child under the mouse cursor.
-
#initialize ⇒ Layout
constructor
A new instance of Layout.
- #on_focus ⇒ void
-
#remove(child) ⇒ void
@param
child.
Constructor Details
#initialize ⇒ Layout
Returns a new instance of Layout.
14 15 16 17 |
# File 'lib/tuile/component/layout.rb', line 14 def initialize super @children = [] end |
Instance Method Details
#add(child) ⇒ void
This method returns an undefined value.
Adds a child component to this layout.
@param child
35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/tuile/component/layout.rb', line 35 def add(child) if child.is_a? Enumerable child.each { add(_1) } else raise TypeError, "expected Component, got #{child.inspect}" unless child.is_a? Component raise ArgumentError, "#{child} already has a parent #{child.parent}" unless child.parent.nil? @children << child child.parent = self end end |
#children ⇒ Array<Component>
20 |
# File 'lib/tuile/component/layout.rb', line 20 def children = @children.to_a |
#focusable? ⇒ Boolean
Layouts are focusable containers — like Window and Popup, they don't accept input themselves but they need to participate in the HasContent focus cascade so a Popup wrapping a Layout wrapping a TextField ends up focusing the field rather than parking focus on the popup. Layouts don't paint any visible chrome of their own (the auto-cleared background is just blank space), so this has no mouse-routing consequences — clicks on a gap area land back on the Layout itself and the on_focus cascade forwards to a tab stop.
30 |
# File 'lib/tuile/component/layout.rb', line 30 def focusable? = true |
#handle_mouse(event) ⇒ void
This method returns an undefined value.
Dispatches the event to the child under the mouse cursor.
@param event
62 63 64 65 66 67 |
# File 'lib/tuile/component/layout.rb', line 62 def handle_mouse(event) super @children.each do |child| child.handle_mouse(event) if child.rect.contains?(event.point) end end |
#on_focus ⇒ void
This method returns an undefined value.
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/tuile/component/layout.rb', line 70 def on_focus super # Forward focus to the first interactive widget in the subtree so the # user can start typing / cursoring immediately. Prefer a {#tab_stop?} # descendant (TextField, List, Button…) so we skip past intermediate # containers like a {Window} or another {Layout}. Fall back to the # first focusable direct child for the rare case where the layout has # focusable but non-tab-stop children (e.g. an empty {Window}). first_tab_stop = nil on_tree { |c| first_tab_stop ||= c if !c.equal?(self) && c.tab_stop? } if first_tab_stop screen.focused = first_tab_stop else first_focusable = @children.find(&:focusable?) screen.focused = first_focusable unless first_focusable.nil? end end |
#remove(child) ⇒ void
This method returns an undefined value.
@param child
49 50 51 52 53 54 55 56 57 |
# File 'lib/tuile/component/layout.rb', line 49 def remove(child) raise TypeError, "expected Component, got #{child.inspect}" unless child.is_a? Component raise ArgumentError, "#{child}'s parent is #{child.parent}, not this layout #{self}" if child.parent != self child.parent = nil @children.delete(child) invalidate if @children.empty? on_child_removed(child) end |