LavaUI docs GitHub

class LayoutHost

Swift

final class LayoutHost

Owns the retained root and runs Yoga layout.

Sources/LavaUI/LayoutNode.swift:2023

Constructors

init()

Creates a host with no tree.

Sources/LavaUI/LayoutNode.swift:2039

Properties

var lastFrames: [LayoutFrame] { get }

Committed layout from the last calculateLayout (hit-test / queries read this).

Sources/LavaUI/LayoutNode.swift:2031

var lastLayoutFrames: [LayoutFrame] { get }

Frames from the most recent layout, for frames that only redraw.

Sources/LavaUI/LayoutNode.swift:2213

var lastLayoutHeight: Float { get }

The height passed to the last calculateLayout(width:height:).

Sources/LavaUI/LayoutNode.swift:2035

var lastLayoutWidth: Float { get }

The width passed to the last calculateLayout(width:height:).

Sources/LavaUI/LayoutNode.swift:2033

var mountCount: Int { get }

How many times setRoot mounted a fresh tree rather than reconciling.

Sources/LavaUI/LayoutNode.swift:2028

var reconcileCount: Int { get }

Generations of setRoot — for tests / dumps.

Sources/LavaUI/LayoutNode.swift:2026

var rootID: NodeID? { get }

The root node's id, or nil before the first setRoot.

Sources/LavaUI/LayoutNode.swift:2042

var rootNode: (any AnyViewNode)? { get }

The root of the retained tree, or nil before the first setRoot.

Sources/LavaUI/LayoutNode.swift:2210

Methods

func agentFind(query: String, originY: Float = 0, limit: Int = 32) -> [[String : Any]]

Find nodes by substring match on sid/label/text. Returns flat list of {sid,id,label,type,text?,x,y,w,h,interactive} (max limit).

Sources/LavaUI/AgentLayout.swift:93

func agentFrame(label: String, originY: Float = 0) -> LayoutFrame?

Frame of the first node whose label equals label (committed layout).

Sources/LavaUI/AgentLayout.swift:68

func agentFrame(id: UInt64, originY: Float = 0) -> LayoutFrame?

Frame by process-local NodeID (not stable across launches).

Sources/LavaUI/AgentLayout.swift:76

func agentFrame(sid: String, originY: Float = 0) -> LayoutFrame?

Frame by stable agent id or structural path (sid from layout_tree).

Sources/LavaUI/AgentLayout.swift:84

func agentHitLabel(x: Float, y: Float, originY: Float = 0) -> String?

Topmost layout label under a point (debug helper for agents).

Sources/LavaUI/AgentLayout.swift:53

func agentLayoutTree(originY: Float = 0, maxDepth: Int = 16) -> [String : Any]

Nested layout tree suitable for JSONSerialization.

Sources/LavaUI/AgentLayout.swift:16

func agentLayoutTreeJSON(originY: Float = 0, maxDepth: Int = 16) -> String

JSON string of agentLayoutTree.

Sources/LavaUI/AgentLayout.swift:41

@discardableResult func calculateLayout(width: Float, height: Float) -> [LayoutFrame]

Layout into a definite viewport size (window / body pixels).

The root Yoga node is given an exact width/height matching the viewport. With width: auto alone, Yoga sizes the root to its content and flexGrow children never receive free space — so after a window resize the UI stayed content-sized (black empty region). Setting definite root dimensions is the standard full-window Yoga pattern.

Sources/LavaUI/LayoutNode.swift:2067

func diagramHostFrame() -> LayoutFrame?

Diagram host from committed layout — does not re-run Yoga.

Sources/LavaUI/LayoutNode.swift:2216

@discardableResult func dismissOverlays() -> Bool

Dismisses everything presented. Returns true if anything was showing, so a key handler can tell whether it consumed the event.

Sources/LavaUI/LayoutNode.swift:2447

func dragGestureSource(x: Float, y: Float, originX: Float = 0, originY: Float = 0) -> NodeID?

The nearest .onDragGesture at this point, walking outwards.

Sources/LavaUI/DragGesture.swift:191

func dropTarget(x: Float, y: Float, originX: Float = 0, originY: Float = 0) -> NodeID?

The nearest .onDrop handler at this point, innermost first.

Not hitTestHover, which resolves exactly one node and is right for a highlight and wrong for a drop: the topmost thing under the pointer is almost never the view that registered the handler. In LavaView it is the picture, in an editor the text — and a child with no interest in drops must not swallow the one its parent is waiting for. So the chain is walked outwards and the first handler along it wins, which is what every other drag-and-drop implementation means by "the drop target".

Sources/LavaUI/LayoutNode.swift:2404

func dumpFrames(width: Float, height: Float)

Lays out at width × height and prints every frame to standard error.

Sources/LavaUI/LayoutNode.swift:2192

func fileDragSource(x: Float, y: Float, originX: Float = 0, originY: Float = 0) -> NodeID?

The nearest .onFileDrag source at this point, found the way dropTarget finds a drop target and for the same reason: the press lands on a row's label, and it is the row that registered.

Sources/LavaUI/LayoutNode.swift:2418

func focusTarget(x: Float, y: Float, originX: Float = 0, originY: Float = 0) -> NodeID?

The nearest .focusable view at this point, walking outwards.

Sources/LavaUI/Focusable.swift:55

func hitTestClick(x: Float, y: Float, originX: Float = 0, originY: Float = 0, mods: Int32 = 0, button: Int32 = 0) -> (() -> Void)?

Reverse-z hit test against committed Yoga geometry (no re-layout). originY matches emit offset (menu bar). Window-pixel coordinates.

Sources/LavaUI/LayoutNode.swift:2223

func hitTestHover(x: Float, y: Float, originX: Float = 0, originY: Float = 0) -> NodeID?

Topmost interactive node under the pointer, for hover highlighting.

Sources/LavaUI/LayoutNode.swift:2270

func hitTestSceneHover(x: Float, y: Float, originX: Float = 0, originY: Float = 0) -> NodeID?

What the renderer would call hovered at this point.

Deliberately not hitTestHover. That one answers a local question — which node should highlight, which container a wheel notch belongs to, what a file was dropped on — and it counts scrollables and drop targets as hover targets because those are the things it exists to find. The renderer counts something narrower: the nodes it was handed a hit-test flag for, which is isRendererInteractive and nothing else.

The distinction matters exactly once, and it is enough: an injected pointer in a client has no renderer to answer .nodeHover, so this is what stands in for it, and it has to give the same answer the renderer would or a Button will not believe the pointer is on it.

Deepest wins, matching RenderWindow::updateSceneHover, which walks a pre-order list and keeps the last node containing the point.

Sources/LavaUI/LayoutNode.swift:2306

func hitTestScrollChain(x: Float, y: Float, originX: Float = 0, originY: Float = 0) -> [NodeID]

Every node under the pointer that a wheel event may be offered to, innermost first.

Hover resolves exactly one node, which is right for highlighting and wrong for the wheel: a button, text field, or canvas sitting inside a ScrollView is the topmost hit, so routing by hover alone let it mask the container and a notch over it scrolled nothing. This keeps the whole ancestor path instead so ScrollRouter can bubble. Deliberately a separate walk — hover and click targeting stay exactly as they were.

Sources/LavaUI/LayoutNode.swift:2371

func invalidateTextMetrics()

After FontStore content-scale change: force every text leaf to re-measure on the next calculateLayout (library helper).

Sources/LavaUI/LayoutNode.swift:2184

func pressObservers(x: Float, y: Float, originX: Float = 0, originY: Float = 0) -> [NodeID]

Every .onAnyPress containing this point, innermost first.

Sources/LavaUI/DragGesture.swift:199

func setRoot<V>(_ view: V) where V : View

Makes view the root: reconciled against the current tree when there is one, mounted fresh otherwise. The next layout pass lays it out.

Sources/LavaUI/LayoutNode.swift:2046