core

package
v1.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 16, 2026 License: BSD-3-Clause Imports: 4 Imported by: 0

Documentation

Overview

Package core defines the fundamental interfaces of the Bellui toolkit.

These interfaces form the backbone of every Bellui application: CanvasObject for anything that can be drawn, Widget for interactive components, Canvas for the rendering surface, Layout for arranging objects, and [Window] for the top-level UI container.

This package depends only on bellui/geo and bellui/event (both leaf packages), making it safe to import from anywhere in the framework.

import "github.com/belluikit/bellui/core"

Index

Constants

View Source
const (
	ActionPress     = "press"     // Button, link, menu item
	ActionToggle    = "toggle"    // Checkbox, switch
	ActionIncrement = "increment" // Slider, spinbox
	ActionDecrement = "decrement" // Slider, spinbox
	ActionExpand    = "expand"    // Accordion, tree node
	ActionCollapse  = "collapse"  // Accordion, tree node
	ActionSelect    = "select"    // List item, tab
	ActionDismiss   = "dismiss"   // Dialog, toast, snackbar
	ActionRename    = "rename"    // Tree/list rows with inline rename
	ActionDelete    = "delete"    // Tree/list rows, removable chips
	ActionUndo      = "undo"      // Text editors with undo history
	ActionRedo      = "redo"      // Text editors with redo history
)

Standard action names for use in AccessibleActioner implementations.

Variables

View Source
var (
	ShowToolTip func(obj CanvasObject, c Canvas)
	HideToolTip func()
)

ShowToolTip and HideToolTip are an optional hook installed by the widget package to render hover tooltips; both are nil until then, so a driver that runs without the widget package (or before it initializes) pays a single nil check per pointer move. The seam mirrors the OnActivation / SetFontFallbackRegister hook pattern, keeping core widget-free.

A driver calls NotifyToolTip when the tooltip target under the pointer changes: with the new ToolTipable target (which starts the show delay), or with nil (which hides any visible tooltip). Both run on the main goroutine from the driver's hover dispatch. The installed controller owns the delay timer, the bubble overlay and its lifecycle.

View Source
var OnActivation func(obj CanvasObject, viaKeyboard bool)

OnActivation is an optional hook invoked once each time an interactive object is activated: a pointer tap, or a screen-reader "press"/"toggle"/"select" action (screen-reader activations route through the same Tapped dispatch, so they are covered for free). It is nil unless a consumer installs it, so an app that never imports a consumer pays a single nil check per activation.

The seam mirrors the SetFontFallbackRegister/RegisterTextMeasure hook pattern: a package var wired by an optional peripheral package, keeping core dependency-free and widget-free. The analytics package's EnableAutoCapture is the reference consumer. viaKeyboard is true when the activation came from a keyboard Enter/Space on the focused object rather than a pointer tap.

It is always called on the main goroutine, from the driver's input dispatch, right where the object's Tapped is fired. Keep the callback cheap and non-blocking; hand heavy work to a queue (as the analytics tracker does).

Functions

func NotifyActivation

func NotifyActivation(obj CanvasObject, viaKeyboard bool)

NotifyActivation invokes OnActivation when a consumer is installed. Drivers call it at their tap/activate dispatch sites, once per activation, right where the object's Tapped is fired. It is a single nil check when no consumer is registered.

func NotifyToolTip

func NotifyToolTip(obj CanvasObject, c Canvas)

NotifyToolTip forwards a tooltip target change to the installed controller. A nil obj hides any visible tooltip; a non-empty ToolTipable obj starts the show delay. It is a single nil check when no controller is registered.

func WalkAccessibleTree

func WalkAccessibleTree(root CanvasObject, children ChildrenFunc, visit func(AccessibleNode, int) bool)

WalkAccessibleTree traverses the visible object tree starting at root, calling visit for each object that implements Accessible. The walk is depth-first, parent before children. The int parameter to visit is the current depth (root = 0). If visit returns true, the walk stops immediately.

The children function is used to obtain child objects; callers in the driver layer supply a function that reads the render cache, while test code can provide a simpler implementation.

Types

type Accessible

type Accessible interface {
	// AccessibleRole returns the semantic role of this widget.
	AccessibleRole() AccessibleRole

	// AccessibleLabel returns the human-readable name of this widget.
	// For a button this is the button text; for an entry, the placeholder.
	AccessibleLabel() string
}

Accessible is implemented by widgets that provide semantic information for assistive technologies such as screen readers.

Widgets opt in by implementing this interface, following the same composition pattern as Disableable or event.Tappable.

type AccessibleAction

type AccessibleAction struct {
	Name        string // Machine-readable name (e.g. "press", "toggle")
	Description string // Human-readable description
}

AccessibleAction represents a named action that a widget supports.

type AccessibleActioner

type AccessibleActioner interface {
	// AccessibleActions returns the list of actions this widget supports.
	AccessibleActions() []AccessibleAction

	// PerformAccessibleAction invokes the named action.
	// Unknown or unsupported names are silently ignored.
	PerformAccessibleAction(name string)
}

AccessibleActioner reports supported actions and allows invoking them by name. Platform bridges translate these to platform-specific action protocols (NSAccessibilityAction, ATK_ACTION, UIA Invoke).

type AccessibleActiveDescendant

type AccessibleActiveDescendant interface {
	// AccessibleActiveDescendant returns the stable identity of the currently
	// focused descendant, or nil when the container itself holds AT focus (no
	// internal cursor, or the cursor is on the container as a whole).
	AccessibleActiveDescendant() any
}

AccessibleActiveDescendant is implemented by a focusable container that manages an internal keyboard cursor over descendant items — a data grid moving a cell cursor with the arrow keys, a tree or virtualized list moving a row cursor. The container is the single event.Focusable that receives the key events, but assistive technology should follow and announce the item the cursor is on, not the container as a whole. This is the ARIA aria-activedescendant analog.

It designates the AT-focused descendant by stable identity — the [AccessibleIdentity] key of a realized descendant, or the AccessibleVirtualNode.ID of a virtual one (both ride the shared AccessibleNode.NodeID channel). Platform bridges resolve AT focus to the descendant whose NodeID matches this key and raise a platform focus-change event when the cursor moves to a different descendant, so a screen reader speaks each item during arrow-key navigation.

This is an AT-only focus designation: it must not change which object Canvas.Focused reports, since that would reroute real keyboard event delivery. The designated descendant must already be a node in the reconciled tree — realized, or within a provider's virtual window (AccessibleVirtualNodeProvider); the container is responsible for scrolling its cursor into that window. A descendant that also marks itself StateFocused reports keyboard focus to the platform even without matching by identity.

type AccessibleConcealed

type AccessibleConcealed interface {
	// AccessibleConcealed reports whether the widget currently conceals its
	// content (e.g. a password field). When true, semantic auto-capture omits
	// the widget.
	AccessibleConcealed() bool
}

AccessibleConcealed is implemented by widgets whose content is sensitive and must be excluded wholesale from semantic auto-capture (and similar introspection) — a password Entry, or any field showing concealed text. Auto-capture (analytics.EnableAutoCapture) skips a target that reports true, belt-and-suspenders on top of never capturing values in the first place.

It is distinct from RolePasswordField: a masked-role widget still exposes a role and label, whereas a concealed one opts out of capture entirely.

type AccessibleDescriber

type AccessibleDescriber interface {
	// AccessibleDescription returns help text describing the widget's purpose.
	AccessibleDescription() string
}

AccessibleDescriber optionally provides a longer description beyond the label. Useful for icon-only buttons or complex widgets where the label alone is insufficient.

type AccessibleGridDimensioner

type AccessibleGridDimensioner interface {
	// AccessibleGridDimensions returns the row and column count of the grid
	// as currently presented — including rows that are scrolled off-screen or
	// otherwise not realized, but reflecting the current sort and filter. A
	// filtered grid reports the filtered length, not the unfiltered source
	// total, so it matches the "row R of N" a screen reader announces against
	// the AccessibleCellPosition display coordinates.
	AccessibleGridDimensions() (rows, cols int)
}

AccessibleGridDimensioner reports the dimensions of a table or grid container. Virtualized tables realize only the visible cells, so without this the full extent is invisible to assistive technologies — platform bridges map it to dimension-aware patterns (the UIA Grid pattern's RowCount/ColumnCount).

type AccessibleGridItem

type AccessibleGridItem interface {
	// AccessibleCellPosition returns the cell's zero-based row and column in
	// the grid's current presentation order — the position as the user
	// perceives it, after any sort, filter or scroll. It is a display
	// coordinate, not a stable source/model index: a re-sort or re-filter
	// changes it, mirroring the on-screen layout that platform grid patterns
	// (UIA GridItem Row/Column, NSAccessibility AXRow order) expect. Stable
	// data identity — for letting assistive-tech focus follow a record across
	// reindexing — travels on a separate channel ([AccessibleVirtualNode.ID]
	// for virtualized rows, [AccessibleIdentified] for realized cells), never
	// on this coordinate.
	AccessibleCellPosition() (row, col int)
}

AccessibleGridItem reports the coordinates of a cell within its table or grid. Platform bridges map this to coordinate-aware patterns (NSAccessibility row/column indexes, UIA GridItem).

type AccessibleIdentified

type AccessibleIdentified interface {
	// AccessibleIdentity returns a stable, COMPARABLE key for the logical item
	// this node represents (it is used as a map key; a non-comparable value
	// panics). It must be unique within the window: incorporate an owner
	// reference (e.g. the owning widget) if a bare index could collide with
	// another widget's. Return nil to fall back to CanvasObject identity.
	AccessibleIdentity() any
}

AccessibleIdentified gives a node a stable data identity independent of its CanvasObject. Platform bridges normally reconcile a realized node by its object pointer, but a virtualized collection (a table/list with a million logical rows) recycles a small pool of cell objects across the data, so the same object represents a different record after a sort, scroll or filter. A node that reports an identity is reconciled by that key instead, so its platform element — and the assistive-tech cursor on it — follows the record rather than the recycled screen slot.

This is the realized-node counterpart of AccessibleVirtualNode.ID (which carries the identity of a node that has no CanvasObject at all); both feed the same AccessibleNode.NodeID identity channel.

type AccessibleLabelOverrider

type AccessibleLabelOverrider interface {
	// AccessibilityLabel returns the application-supplied label, or an
	// empty string when no override is set.
	AccessibilityLabel() string
}

AccessibleLabelOverrider optionally provides an application-supplied accessible label that takes precedence over Accessible.AccessibleLabel. It is the plumbing behind widget.BaseWidget.SetAccessibilityLabel: widgets without intrinsic text (icon-only buttons, images) return an empty label from AccessibleLabel, and the application names them explicitly.

type AccessibleLeveler

type AccessibleLeveler interface {
	// AccessibleLevel returns the 1-based nesting level (a root item is 1).
	AccessibleLevel() int
}

AccessibleLeveler reports the nesting depth of an item in a hierarchy, such as a tree node. Rendered trees lay rows out flat, so without this the outline structure is invisible to assistive technologies.

type AccessibleNode

type AccessibleNode struct {
	Object       CanvasObject
	Role         AccessibleRole
	Label        string
	Description  string // Empty if Object does not implement AccessibleDescriber
	Value        string // Empty if Object does not implement AccessibleValuer
	State        AccessibleState
	Actions      []AccessibleAction
	HasRange     bool // False when AccessibleRange returned the (0, 0, 0) "not applicable" sentinel
	RangeMin     float64
	RangeMax     float64
	RangeCurrent float64

	HasCellPosition  bool // True when Object implements AccessibleGridItem
	CellRow, CellCol int  // Display coordinates in current presentation order (see AccessibleGridItem)
	Level            int  // 1-based hierarchy level; 0 when Object does not implement AccessibleLeveler

	HasGridDims        bool // True when Object implements AccessibleGridDimensioner
	GridRows, GridCols int  // Current presented extent, filter-aware (see AccessibleGridDimensioner)

	// NodeID is a stable identity used by platform bridges to reconcile this
	// node's element across walks instead of keying by CanvasObject: from
	// AccessibleIdentified for a realized node, or AccessibleVirtualNode.ID for
	// a virtual one. Nil ⇒ key by Object (the default for most widgets).
	NodeID any
}

AccessibleNode provides a snapshot of accessibility properties for a node discovered during a tree walk. Fields are populated via type assertions on the underlying CanvasObject.

func SnapshotAccessible

func SnapshotAccessible(obj CanvasObject) (node AccessibleNode, ok bool)

SnapshotAccessible captures the accessibility properties of obj into an AccessibleNode. ok is false when obj does not implement Accessible. The optional interfaces (AccessibleDescriber, AccessibleValuer, AccessibleStateful, AccessibleActioner) are queried the same way WalkAccessibleTree does for each visited node.

StateDisabled is additionally derived from Disableable: an object reporting Disabled() gets the bit whether or not it implements AccessibleStateful, so a disabled widget is never announced as actionable.

type AccessibleRole

type AccessibleRole int

AccessibleRole identifies the semantic purpose of a widget for assistive technologies. Values are inspired by WAI-ARIA roles.

const (
	RoleNone             AccessibleRole = iota // Not semantically meaningful
	RoleButton                                 // Clickable action trigger
	RoleCheckbox                               // Toggleable boolean
	RoleRadioButton                            // One-of-N selection
	RoleRadioGroup                             // Container for radio buttons
	RoleSwitch                                 // On/off toggle
	RoleTextBox                                // Single-line text input
	RoleMultiLineTextBox                       // Multi-line text input
	RolePasswordField                          // Masked text input
	RoleComboBox                               // Dropdown selector
	RoleSearchField                            // Search input
	RoleSlider                                 // Range selection
	RoleSpinButton                             // Numeric stepper
	RoleProgressBar                            // Determinate/indeterminate progress
	RoleLabel                                  // Static text
	RoleLink                                   // Hyperlink
	RoleImage                                  // Image content
	RoleList                                   // Scrollable list container
	RoleListItem                               // Item within a list
	RoleTree                                   // Hierarchical tree
	RoleTreeItem                               // Item within a tree
	RoleTable                                  // Data table
	RoleTableRow                               // Row in a table
	RoleTableCell                              // Cell in a table
	RoleGrid                                   // Grid layout
	RoleTab                                    // Tab button
	RoleTabList                                // Container of tabs
	RoleTabPanel                               // Content panel for a tab
	RoleMenu                                   // Menu container
	RoleMenuItem                               // Item in a menu
	RoleMenuBar                                // Top-level menu bar
	RoleToolbar                                // Toolbar container
	RoleNavigation                             // Navigation container
	RoleDialog                                 // Modal dialog
	RoleAlertDialog                            // Confirmation/alert dialog
	RoleForm                                   // Form container
	RoleGroup                                  // Generic grouping
	RoleAccordion                              // Expandable section container
	RoleCard                                   // Card container
	RoleBadge                                  // Notification indicator
	RoleStatus                                 // Status message (toast/snackbar)
	RoleTooltip                                // Tooltip popup
	RoleSeparator                              // Visual separator
	RoleScrollBar                              // Scroll indicator
	RoleRegion                                 // Generic landmark region
	RoleHeading                                // Section heading text
)

func (AccessibleRole) ChildrenPresentational

func (r AccessibleRole) ChildrenPresentational() bool

ChildrenPresentational reports whether the descendants of a widget with this role are presentation details that must not appear in the semantic tree. It mirrors WAI-ARIA's "children presentational" characteristic: a button is announced as one control, so the internal text widget that paints its label carries no semantics of its own. Tree walkers drop the accessible descendants of such a node.

Text-bearing roles that can host embedded interactive controls (text inputs with an action button, rich text with hyperlinks) are not in this set — see AccessibleRole.NonInteractiveChildrenPresentational.

func (AccessibleRole) NonInteractiveChildrenPresentational

func (r AccessibleRole) NonInteractiveChildrenPresentational() bool

NonInteractiveChildrenPresentational reports whether the widget's non-interactive accessible descendants are presentation details while its interactive descendants remain part of the semantic tree. This covers bellui's text-bearing controls: their renderers are built from internal accessible text widgets that would duplicate the control's own label or value (and are dropped), but they can also host real embedded controls that must stay reachable — an Entry's ActionItem button (a DateEntry's calendar, a SearchField's clear button) or hyperlinks inside rich text.

Tree walkers keep the descendants that expose actions or respond to taps and drop the rest. WAI-ARIA does not mark textbox as children presentational; this is the analogous, selective treatment.

func (AccessibleRole) String

func (r AccessibleRole) String() string

String returns a human-readable name for the role, or "AccessibleRole(n)" for an unrecognized value. It is intended for debugging and developer tooling (logs, the widget inspector); assistive-technology backends map roles to their own platform constants rather than using this text.

type AccessibleScrollIntoView

type AccessibleScrollIntoView interface {
	// AccessibleScrollCellIntoView scrolls the container so the cell at the
	// zero-based display (row, col) — the same coordinate space as
	// [AccessibleGridDimensioner] — becomes visible and realized. Out-of-range
	// coordinates are ignored. Called on the main goroutine, like other
	// accessible actions.
	AccessibleScrollCellIntoView(row, col int)
}

AccessibleScrollIntoView is implemented by a virtualized grid or list to bring a not-currently-realized cell into the visible viewport when assistive technology explicitly realizes it — the UIA VirtualizedItem pattern's Realize, or a VoiceOver activate on an off-screen cell. It is deliberately separate from the read path (AccessibleVirtualCellRealizer.AccessibleRealizeCell) so that merely announcing an off-screen row as the AT cursor passes over it does not move the viewport; only an explicit realize/activate scrolls.

type AccessibleState

type AccessibleState uint32

AccessibleState is a bitmask of boolean states for assistive technologies.

const (
	StateChecked  AccessibleState = 1 << iota // Checkbox/switch is on
	StateExpanded                             // Accordion/tree node is open
	StateSelected                             // List/tab item is selected
	StateDisabled                             // Widget is disabled
	StateFocused                              // Widget has keyboard focus
	StateRequired                             // Form field is required
	StateReadOnly                             // Text field is read-only
	StatePartial                              // Indeterminate check state
	StateModal                                // Dialog is modal
)

func (AccessibleState) Has

func (s AccessibleState) Has(flag AccessibleState) bool

Has reports whether s contains the given state flag.

type AccessibleStateful

type AccessibleStateful interface {
	// AccessibleState returns the current state flags.
	// Only flags relevant to the widget's role are meaningful.
	AccessibleState() AccessibleState
}

AccessibleStateful reports dynamic boolean states such as "checked", "expanded", or "selected". Platform bridges use this to communicate widget state to assistive technologies.

type AccessibleTextLayouter

type AccessibleTextLayouter interface {
	AccessibleTexter

	// AccessibleLineCount returns the number of visual (soft-wrapped) lines.
	AccessibleLineCount() int

	// AccessibleLineForOffset returns the zero-based visual line containing
	// the rune offset, clamped to the content.
	AccessibleLineForOffset(off int) int

	// AccessibleLineRange returns the half-open rune range [start, end) of
	// the zero-based visual line: end is the start of the following line —
	// covering a terminating newline or the soft-wrap boundary — or the
	// content length on the last line. ok is false for a line out of range.
	AccessibleLineRange(line int) (start, end int, ok bool)

	// AccessibleRangeBounds returns one rectangle per visual line touched by
	// the half-open rune range [start, end), clipped to the widget's visible
	// viewport: lines scrolled out of view are omitted, so the result stays
	// bounded by the viewport no matter how large the range. A degenerate
	// range (start == end) yields the caret rectangle at that offset. An
	// empty slice means no part of the range is currently visible, or
	// geometry is unavailable. On bidirectional rows the per-line rectangle
	// spans the range's endpoints and may over- or under-cover reordered runs.
	AccessibleRangeBounds(start, end int) []geo.Rectangle
}

AccessibleTextLayouter is an optional extension of AccessibleTexter for text widgets that can expose their visual layout: soft-wrapped (visual) line boundaries and the on-screen geometry of text ranges (pre-rebrand tracker #990). Platform bridges use it for line-granularity navigation that matches what the user sees (an AccessibleTexter alone yields logical, newline-delimited lines) and for the range-geometry queries behind screen-reader magnifiers and cursor tracking (AXBoundsForRange, the UIA GetBoundingRectangles, Android's character-location extra). Widgets without it degrade to logical lines and element-level geometry.

All offsets are rune indices into AccessibleTexter.AccessibleText, and all geometry is in the widget's own coordinate space adjusted for its current scroll offset — the same space as event.PreeditPositioner's caret rectangle — so bridges translate with the widget's absolute canvas position exactly as they do for the IME caret.

type AccessibleTexter

type AccessibleTexter interface {
	// AccessibleText returns the text assistive technology reads and
	// navigates. Password fields return a masked representation of the
	// same rune length, never the secret.
	AccessibleText() string

	// AccessibleSelection returns the selection as a half-open rune range
	// with start <= end; when nothing is selected both are the caret offset.
	AccessibleSelection() (start, end int)

	// AccessibleCaret returns the rune offset of the insertion point.
	AccessibleCaret() int

	// SetAccessibleSelection selects [start, end), clamped to the content;
	// equal offsets place the caret there with no selection.
	SetAccessibleSelection(start, end int)

	// ReplaceAccessibleSelection replaces the current selection with text —
	// or inserts it at the caret when nothing is selected — as one
	// undo-recorded edit.
	ReplaceAccessibleSelection(text string)
}

AccessibleTexter exposes the text content, caret and selection of a text widget to assistive technologies, and lets them edit it. Platform bridges map this to their text protocols (the NSAccessibility text attributes, the UIA Text pattern); without it a screen reader can read a text field's value but cannot track the caret, read the selection or edit by voice.

All offsets are rune indices into AccessibleTexter.AccessibleText; bridges convert to their platform's code-unit space. Mutating calls go through the widget's normal gated, undo-recorded edit paths and are no-ops on read-only or disabled widgets.

type AccessibleValuer

type AccessibleValuer interface {
	// AccessibleValue returns a human-readable representation of the
	// current value (e.g. "42", "50%").
	AccessibleValue() string

	// AccessibleRange returns the minimum, maximum, and current numeric
	// values. Returns (0, 0, 0) if a numeric range is not applicable.
	//
	// The sentinel means a widget whose range is genuinely 0..0 with a
	// current value of 0 (e.g. a slider constructed with min == max == 0)
	// is reported as having no range; such a range is degenerate — there
	// is nothing for assistive technology to adjust — so this is the
	// intended behavior.
	AccessibleRange() (min, max, current float64)
}

AccessibleValuer reports the current value and valid range of a widget. Implemented by sliders, spin boxes, progress bars, and similar range-based widgets.

type AccessibleVirtualCellRealizer

type AccessibleVirtualCellRealizer interface {
	// AccessibleRealizeCell returns the semantic node for the cell at the given
	// zero-based (row, col) in the grid's current presentation order — the same
	// display coordinate space as [AccessibleGridItem.AccessibleCellPosition] and
	// [AccessibleGridDimensioner.AccessibleGridDimensions], filter- and
	// sort-aware. ok is false when the coordinates are out of range.
	//
	// The returned node may have off-screen bounds; the bridge positions the AT
	// cursor on it without requiring visibility. Set [AccessibleVirtualNode.ID] to
	// the cell's stable data identity so the element tracks the record across
	// reindexing, and the embedded [AccessibleNode]'s HasCellPosition / CellRow /
	// CellCol so the bridge places it in the grid. A read must have no visible
	// side effect — in particular it must not scroll; the explicit bring-into-view
	// path is [AccessibleScrollIntoView].
	AccessibleRealizeCell(row, col int) (AccessibleVirtualNode, bool)
}

AccessibleVirtualCellRealizer lets assistive technology reach a grid or list cell that is NOT in the current viewport window. A virtualized container realizes only the visible cells and reports the full extent via AccessibleGridDimensioner; AccessibleVirtualNodeProvider surfaces only the near-viewport window so the tree walk stays O(viewport). This interface answers a targeted request for one off-window cell the screen reader navigated to — its table navigation reads a cell the user has not scrolled to — without the container materializing every logical row.

The cell is delivered to the platform bridge on demand and becomes a transient element there; it never flows through the bounds-aware tree walk, so an off-screen realized cell is not culled the way an off-screen node emitted by AccessibleVirtualNodeProvider would be. Platform bridges map this to the lazy item patterns: the UIA ItemContainer pattern (FindItemByProperty) and NSAccessibility's accessibilityCell(forColumn:row:).

type AccessibleVirtualNode

type AccessibleVirtualNode struct {
	AccessibleNode // Object is nil for virtual nodes

	Pos  geo.Position // top-left relative to the providing widget
	Size geo.Size

	// ID is a stable identity for the region (e.g. the segment that
	// produced it), letting platform backends reconcile elements across
	// updates the way they key real nodes by CanvasObject.
	ID any
}

AccessibleVirtualNode is a semantic node that is not backed by its own CanvasObject: a region inside a widget that renders several logical elements itself, such as a heading inside a RichText document. Bounds are relative to the providing widget; tree walkers convert them to absolute coordinates and attach the node as a child of the provider's node.

type AccessibleVirtualNodeProvider

type AccessibleVirtualNodeProvider interface {
	// AccessibleVirtualNodes returns the current virtual nodes in reading
	// order — a bounded window for virtualized collections (see the type
	// doc). Implementations return nil when nothing is rendered yet.
	AccessibleVirtualNodes() []AccessibleVirtualNode
}

AccessibleVirtualNodeProvider is implemented by widgets that expose semantic regions without dedicated CanvasObjects. The provider is consulted by bounds-aware tree walkers after the widget's real accessible descendants are collected.

Windowing (virtualized grids/lists). A provider backing a large virtualized collection — a table with a million logical rows that realizes only the visible cells — must NOT return a node per logical item: the walk allocates and sorts every returned node each pass. Instead return a bounded window (typically the rows near the viewport) and report the full extent through AccessibleGridDimensioner on the container, so assistive tech hears "row R of N" without the walk touching all N. Each windowed node still carries its own coordinates: for a grid, emit flat RoleTableCell nodes with HasCellPosition/CellRow/CellCol set on the embedded AccessibleNode (platform bridges group them into rows by CellRow — no nested row nodes are needed), and set AccessibleVirtualNode.ID to a stable per-item key so the backend can track a node across walks. Nodes whose bounds fall entirely outside the container's clip are culled by the backends; surfacing rows beyond the viewport for assistive-tech to navigate into (lazy realization) is a platform-virtualization concern tracked separately, not something a provider achieves by returning off-screen nodes here.

type Canvas

type Canvas interface {
	Content() CanvasObject
	SetContent(CanvasObject)
	Refresh(CanvasObject)

	Focus(event.Focusable)
	FocusNext()
	FocusPrevious()
	Unfocus()
	Focused() event.Focusable

	Size() geo.Size
	Scale() float32

	Overlays() OverlayStack

	OnTypedRune() func(rune)
	SetOnTypedRune(func(rune))
	OnTypedKey() func(*event.KeyEvent)
	SetOnTypedKey(func(*event.KeyEvent))
	AddShortcut(shortcut Shortcut, handler func(shortcut Shortcut))
	RemoveShortcut(shortcut Shortcut)

	Capture() image.Image

	PixelCoordinateForPosition(geo.Position) (int, int)
	InteractiveArea() (geo.Position, geo.Size)
}

Canvas defines a graphical canvas to which a CanvasObject can be added. Each canvas has a scale which is automatically applied during the render process.

type CanvasObject

type CanvasObject interface {
	MinSize() geo.Size
	Move(geo.Position)
	Position() geo.Position
	Resize(geo.Size)
	Size() geo.Size

	Hide()
	Visible() bool
	Show()

	Refresh()
}

CanvasObject describes any graphical object that can be added to a canvas. Objects have a size and position that can be controlled through this API.

type ChildrenFunc

type ChildrenFunc func(CanvasObject) []CanvasObject

ChildrenFunc returns the child objects of a given CanvasObject. Callers provide this to abstract away the difference between containers (direct children) and widgets (renderer children). Implementations typically use the internal render cache.

type Disableable

type Disableable interface {
	Enable()
	Disable()
	Disabled() bool
}

Disableable describes any CanvasObject that can be disabled.

type DragImageProvider

type DragImageProvider interface {
	// DragImage returns the object to paint under the pointer during a drag, or
	// nil for no ghost. It is read once when the drag starts.
	DragImage() CanvasObject
}

DragImageProvider is an optional extension of a drag source (event.Draggable): when a drag begins the driver paints the returned object as a "ghost" that follows the pointer, and removes it when the drag ends. Return nil for no ghost. It gives in-canvas drag-and-drop a visual affordance without every app hand-rolling a following overlay (pre-rebrand tracker #819).

Since: 1.0

type DragPayloadProvider

type DragPayloadProvider interface {
	// DragPayload returns the value delivered to drop targets, or nil.
	DragPayload() any
}

DragPayloadProvider is an optional extension of a drag source (event.Draggable): the returned value is carried to a DragTarget as the in-app drag payload (e.g. the palette entry being inserted, the card being moved). It is read once when the drag starts. Implementing it (or DragImageProvider) also marks the drag as an in-canvas DnD drag, which is what enables DragTarget routing — so a plain draggable (slider, scrollbar) never triggers drop-target callbacks.

Since: 1.0

type DragTarget

type DragTarget interface {
	// DragEnter fires when the pointer enters the target during a drag.
	DragEnter(*DragTargetEvent)
	// DragOver fires on every move while the pointer stays over the target.
	DragOver(*DragTargetEvent)
	// DragLeave fires when the pointer leaves the target (or the drag ends
	// elsewhere) without dropping on it.
	DragLeave()
	// Drop fires when the drag is released over the target.
	Drop(*DragTargetEvent)
}

DragTarget is the in-canvas counterpart of bellui.Droppable (which accepts OS file drops): a CanvasObject that accepts an in-app widget drag. The driver routes enter/over/leave/drop to the deepest DragTarget under the pointer, carrying the source-declared payload (DragPayloadProvider) — so targets get live hover callbacks (to highlight themselves) instead of every app re-implementing pointer hit-testing during a drag.

Routing happens only for in-canvas DnD drags — those whose source implements DragPayloadProvider or DragImageProvider — so ordinary draggables never reach a DragTarget.

Since: 1.0

type DragTargetEvent

type DragTargetEvent struct {
	AbsolutePosition geo.Position
	Position         geo.Position
	Payload          any
}

DragTargetEvent carries the in-app drag payload and the pointer position to a DragTarget during an in-canvas drag (pre-rebrand tracker #819). Position is relative to the target's top-left; AbsolutePosition is in canvas coordinates.

Since: 1.0

type Layout

type Layout interface {
	Layout([]CanvasObject, geo.Size)
	MinSize(objects []CanvasObject) geo.Size
}

Layout defines how CanvasObjects may be laid out in a specified Size.

type OverlayStack

type OverlayStack interface {
	Add(overlay CanvasObject)
	List() []CanvasObject
	Remove(overlay CanvasObject)
	Top() CanvasObject
}

OverlayStack is a stack of CanvasObjects used as overlays of a Canvas.

type Shortcut

type Shortcut interface {
	ShortcutName() string
}

Shortcut describes a keyboard shortcut (e.g. Ctrl+C).

type ToolTipable

type ToolTipable interface {
	ToolTip() string
}

ToolTipable is implemented by a CanvasObject that offers hover tooltip text. widget.BaseWidget satisfies it through SetToolTipText, so any widget can carry a tooltip with widget.Button{...}.SetToolTipText("New file"). A non-empty ToolTip() tells the driver to show a hover bubble after a short delay; an empty string means the object has no tooltip.

This is the driver-level replacement for the overlay-based widget.Tooltip, which never fired on the glfw desktop driver: the driver delivers hover to the widget itself reliably, so tooltips ride that instead of an invisible hit-test overlay (pre-rebrand tracker #800).

type Transformable

type Transformable interface {
	Transform() geo.Matrix
	SetTransform(geo.Matrix)
}

Transformable describes a CanvasObject that supports a 2D affine transform. The transform is applied in addition to the object's position and size. When objects in a tree implement Transformable, their transforms compose: a child's world transform is parent.worldTransform * Translate(child.Position()) * child.Transform().

type Widget

type Widget interface {
	CanvasObject

	// CreateRenderer returns a new WidgetRenderer for this widget.
	CreateRenderer() WidgetRenderer
}

Widget defines the standard behaviours of any widget. This extends CanvasObject. A widget behaves in the same basic way but will encapsulate many child objects to create the rendered widget.

type WidgetRenderer

type WidgetRenderer interface {
	Destroy()
	Layout(geo.Size)
	MinSize() geo.Size
	Objects() []CanvasObject
	Refresh()
}

WidgetRenderer defines the behaviour of a widget's implementation.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL