Skip to content

ListNode<T>

Namespace: Hex1b

Assembly: Hex1b.dll

Render node for . Supports two render modes:

  Default mode — no `ItemTemplate` set: each row is rendered
  as a single line of `item?.ToString()` with the themed selection
  indicator and selected/hover background, identical to the original
   visuals.

  Template mode — `ItemTemplate` set: each row is reconciled
  into a child widget tree the template returns. The template owns all
  visual chrome and styles itself from
  .
csharp
public class ListNode<T> : Hex1bNode, ILayoutProvider

Inheritance

ObjectHex1bNodeListNode<T>

Implements

Properties

ClipMode

The clip mode for this layout region.

Returns: ClipMode

csharp
public ClipMode ClipMode { get; }

ClipRect

The effective clipping rectangle for this layout region.

Returns: Rect

csharp
public Rect ClipRect { get; }

DataSource

Optional virtualized data source. When set, is ignored and the node materialises only a window of items around the visible viewport on each frame. Subscribes to if the source supports it.

Returns: IListDataSource<<T>>

csharp
public IListDataSource<T>? DataSource { get; set; }

EffectiveItemCount

The total number of items, either from the in-memory list or the cached count from . Returns 0 until the first async count completes.

Returns: Int32

csharp
public int EffectiveItemCount { get; }

FocusedIndex

The currently selected index. Preserved across reconciliation.

Returns: Int32

csharp
public int FocusedIndex { get; set; }

FocusedItem

The currently selected item, or default if the list is empty or the selected row hasn't been loaded yet (virtualized mode).

Returns: <T>

csharp
public T? FocusedItem { get; }

FocusedText

The text of the currently selected item (via ), or null if the list is empty / not yet loaded.

Returns: String

csharp
public string? FocusedText { get; }

HasLoadedCount

True once the item count is known (always true for in-memory lists; for virtualized sources, true after the first completes). Used to gate the empty-state widget so it doesn't flash while a data source is still resolving.

Returns: Boolean

csharp
public bool HasLoadedCount { get; }

HoveredItemIndex

The index of the row currently under the mouse cursor, or -1 if the list isn't hovered or the cursor sits past the last item. Updated by and reset to -1 when flips to false.

Returns: Int32

csharp
public int HoveredItemIndex { get; }

IsFocusable

Returns true if this node can receive focus.

Returns: Boolean

csharp
public override bool IsFocusable { get; }

IsFocused

Gets or sets whether this node is currently focused. Only meaningful for focusable nodes (where IsFocusable is true).

Returns: Boolean

csharp
public override bool IsFocused { get; set; }

IsHovered

Gets or sets whether the mouse is currently hovering over this node. Set by Hex1bApp based on mouse position during each frame. Only set on focusable nodes (tracked via FocusRing hit testing).

Returns: Boolean

csharp
public override bool IsHovered { get; set; }

IsMultiSelectEnabled

True when this list's multi-select feature is enabled. Reconciled from . Affects keybindings, the default row renderer, and .

Returns: Boolean

csharp
public bool IsMultiSelectEnabled { get; }

IsScrollable

Whether the list needs scrolling (more items than fit in the viewport).

Returns: Boolean

csharp
public bool IsScrollable { get; }

IsVirtualized

Whether the node is operating in virtualized mode.

Returns: Boolean

csharp
public bool IsVirtualized { get; }

ItemHeight

The fixed row height in terminal rows. Defaults to 1. Always at least 1.

Returns: Int32

csharp
public int ItemHeight { get; set; }

Items

The list items to display.

Returns: IReadOnlyList<<T>>

csharp
public IReadOnlyList<T> Items { get; set; }

MaxScrollOffset

The maximum scroll offset based on item count and visible item count.

Returns: Int32

csharp
public int MaxScrollOffset { get; }

ParentLayoutProvider

The parent layout provider, if any. Set when this provider becomes the current layout provider and there was already one active. Used to ensure nested clipping works correctly.

Returns: ILayoutProvider

csharp
public ILayoutProvider? ParentLayoutProvider { get; set; }

ScrollOffset

The scroll offset (index of the first visible item). Preserved across reconciliation.

Returns: Int32

csharp
public int ScrollOffset { get; set; }

SelectedIndices

The current checked-set indices (a read-only snapshot). Always empty when is false.

Returns: IReadOnlyCollection<Int32>

csharp
public IReadOnlyCollection<int> SelectedIndices { get; }

SourceWidget

The source widget that was reconciled into this node.

Returns: ListWidget<<T>>

csharp
public ListWidget<T>? SourceWidget { get; set; }

ViewportHeight

Returns: Int32

csharp
public int ViewportHeight { get; }

VisibleItemCount

The number of items that fit in the viewport at the current .

Returns: Int32

csharp
public int VisibleItemCount { get; }

Methods

ArrangeCore(Rect)

Override this method to implement arranging logic for this node. The base implementation saves previous bounds, marks dirty on change, and sets bounds.

Parameters:

csharp
protected override void ArrangeCore(Rect bounds)

ClipString(int, int, string)

Clips a string that starts at the given position, returning only the visible portion. Implementations should also consult the ParentLayoutProvider if present.

Parameters:

  • x (Int32): Starting absolute X position.
  • y (Int32): Absolute Y position.
  • text (String): The text to potentially clip.

Returns: ValueTuple<Int32, String>

A tuple containing:

  • adjustedX: The X position to start rendering (may be > x if left-clipped)
  • clippedText: The portion of text that should be rendered (may be empty)
csharp
public (int adjustedX, string clippedText) ClipString(int x, int y, string text)

ConfigureDefaultBindings(InputBindingsBuilder)

Default binding configuration uses 's rebindable actions. The override redirects to the legacy action ids so existing rebind code keeps working.

Parameters:

csharp
public override void ConfigureDefaultBindings(InputBindingsBuilder bindings)

GetChildren()

Gets the direct children of this node for structural tree traversal. Container nodes should override this to return their children.

Returns: IEnumerable<Hex1bNode>

csharp
public override IEnumerable<Hex1bNode> GetChildren()

GetFocusableNodes()

Item child nodes are render-only in v1 — the list itself is the only focusable surface. Interactive widgets inside an item template will not receive focus.

Returns: IEnumerable<Hex1bNode>

csharp
public override IEnumerable<Hex1bNode> GetFocusableNodes()

GetVisibleWindow(int)

Computes the absolute range of rows to materialize for the current scroll position: visible window plus rows above and below. Used by both data-source pre-fetch and templated child reconciliation.

Parameters:

Returns: ValueTuple<Int32, Int32>

csharp
public (int Start, int End) GetVisibleWindow(int totalCount)

HandleMouseClick(int, int, Hex1bMouseEvent)

Handles a mouse click event (after mouse bindings have been checked). Override this in nodes to handle clicks that weren't matched by any mouse binding. The coordinates in the event are local to this node's bounds (0,0 is top-left of node).

Parameters:

  • localX (Int32): The X coordinate relative to this node's bounds.
  • localY (Int32): The Y coordinate relative to this node's bounds.
  • mouseEvent (Hex1bMouseEvent): The original mouse event (with absolute coordinates).

Returns: InputResult

Handled if the click was consumed, NotHandled otherwise.

csharp
public override InputResult HandleMouseClick(int localX, int localY, Hex1bMouseEvent mouseEvent)

LoadDataAsync(int, int, CancellationToken)

Loads count items starting at startIndex from the data source, cancelling any in-flight load. No-op when no is set.

Parameters:

Returns: ValueTask

csharp
public ValueTask LoadDataAsync(int startIndex, int count, CancellationToken cancellationToken = default)

MeasureCore(Constraints)

Override this method to implement measuring logic for this node.

Parameters:

Returns: Size

csharp
protected override Size MeasureCore(Constraints constraints)

OnHoverMove(int, int)

Called whenever the mouse moves while this node is the hovered (hit-tested) node, even if doesn't change. Nodes that style themselves based on the mouse's position within their bounds (e.g. a list highlighting the row under the cursor) override this and mark themselves dirty when the derived state changes. Coordinates are absolute (screen-space), not local.

Parameters:

  • mouseX (Int32): Absolute X coordinate of the cursor.
  • mouseY (Int32): Absolute Y coordinate of the cursor.
csharp
public override void OnHoverMove(int mouseX, int mouseY)

Render(Hex1bRenderContext)

Renders the node to the given context.

Parameters:

csharp
public override void Render(Hex1bRenderContext context)

ShouldRenderAt(int, int)

Determines if a character at the given absolute position should be rendered. Implementations should also check the ParentLayoutProvider if present.

Parameters:

  • x (Int32): Absolute X position in terminal coordinates.
  • y (Int32): Absolute Y position in terminal coordinates.

Returns: Boolean

True if the character should be rendered, false if it should be clipped.

csharp
public bool ShouldRenderAt(int x, int y)

TryGetEffectiveItem(int, out T)

Attempts to resolve an item by absolute index. Returns false for indices not currently cached (virtualized mode only). In non-virtualized mode this always succeeds when absoluteIndex is in range.

Parameters:

  • absoluteIndex (Int32):
  • item (<T>):

Returns: Boolean

csharp
public bool TryGetEffectiveItem(int absoluteIndex, out T item)

Released under the MIT License.