Teek API Documentation

The build-phase tree: an unattached root Node plus a name index (Symbol -> Node). Plain Ruby, no Tk - building and traversing a Document never touches an interpreter, which is what makes the DSL headless-testable.

Document only constructs and indexes nodes; it has no opinion on tree shape (which node is whose parent) - the build surface decides that by calling Node#add_child itself, so Document stays reusable underneath whatever parent-tracking scheme the builder uses.

Inherits: Object

Instance Methods

claim_path_segment(parent_path, segment)

fresh instance for every separate realize pass (the initial realize, each Session#add, each lazily-Handle#realize!d screen) - tracking claims here instead keeps them honest across every one of those passes for this Document’s whole lifetime. Two mounts of the same component requesting the same key under the same real parent (e.g. a reusable row/screen, realized more than once - see WidgetDSL#component) get distinct, disambiguated segments; the common, non-colliding case keeps its plain segment unchanged.

Parameters
  • parent_path String
  • segment String — the requested (not yet disambiguated) segment

Returns Stringsegment, or segment suffixed to make it unique under parent_path if this is a repeat

@api private - called by Realizer#allocate_path, which gets a

create(type:, name: nil, opts: {}, scope: Scope::TOP_LEVEL)

Construct a node and register it under its name (if any), scoped to scope - the same name used in two different scopes indexes as two distinct entries, so a component’s local :save never collides with another component’s (or the top level’s) own :save. Does NOT attach it to any parent - the caller does that with Node#add_child, so Document never needs to know about a current-parent stack.

The node’s own name/key stay bare/unqualified - only this index is scope-aware. A node’s real Tk path is already distinct per scope with no help needed here, since it’s built from the parent chain (Realizer#allocate_path), and two components’ subtrees are never siblings of themselves.

Parameters

Returns Node

@raise ArgumentError if name is already registered within scope

each_named_node(&block)

Every named node, regardless of whether it’s actually attached anywhere in the tree - see Validator’s orphan check, which is exactly the reason this differs from #each_node.

Returns Enumerator — if no block given

@yieldparam name Symbol

@yieldparam node Node

each_node(&block)

Depth-first, pre-order traversal of the whole tree from #root.

Returns Enumerator — if no block given

@yieldparam node Node

find(name, scope: Scope::TOP_LEVEL)

Parameters
  • name Symbol
  • scope Scope — must be the same Scope instance the node was #created with - a name registered inside a scope is never found by a lookup in a different one, or vice versa

Returns Node, nil

find_by_path(path)

Reverse lookup: given a real Tk path (from an error message, a winfo query, or poking around in a REPL), find which node it belongs to - the counterpart to #find’s name-based lookup. Only ever matches a node’s own RealizedNode#path, never its arrange_path (the scrollbar-wrapper case - the wrapper frame itself has no owning node of its own to return) or a WidgetType#addressing strategy’s synthesized virtual path (a menu entry has no real Tk path at all - see MenuEntryAddressing#virtual_path’s own !-marked format, never something Tk itself would hand back from winfo or an error).

Parameters
  • path String — a real Tk widget path, e.g. ".toolbar.save"

Returns Node, nil

initialize

Returns Document — a new instance of Document

notify(event, *args)

Parameters
  • event Symbol
  • args Array — forwarded to every subscriber

Returns void

@api private - see #subscribe

subscribe(event, &block)

A minimal, always-on, generic build-event hook - Node#add_child notifies :append; the build stack’s own push/pop (WidgetDSL#push_stack/WidgetDSL#pop_stack) notify :push/ :pop. Document has no idea what (if anything) is listening, or why - it’s a plain EventBus, same mechanism Session’s own public ui.on/ui.emit already uses, just private and scoped to build-time instrumentation instead of app events. With nothing subscribed (the overwhelmingly common case), #notify costs one hash lookup into an empty list - not something a normal build needs to think about. See TreeInspector, the one built-in subscriber.

Parameters
  • event Symbol

Returns Proc — see EventBus#on

@api private

unregister(node)

Removes node from the name index, scoped exactly like #register does - a no-op if node was never named (nothing to remove) or already unregistered. Called by Handle#destroy! for a destroyed node and every named descendant of its own subtree (Tk destroys descendants recursively, so their names need to stop resolving too), so a later widget can reuse the same name in the same scope, and #find correctly reports the name as gone in the meantime.

Parameters
  • node Node

Returns void

Attributes

root [R]

Returns Node — the tree's root - starts with no children