Skip to main content

ListBox

private readonly ListBox<string> _authors;
private readonly string _mine = "fEst";

_authors = new ListBox<string>(options.Keymap)
{
Render = author => $" {author}",
ItemStyle = author => author == _mine ? Theme.Active : Theme.Default,
OnActivate = author => ViewKind.Author,
Items = authors,
};

_authors.Draw(region);

Widgets are built in the view's constructor, so options is the ArlecchinoOptions the container hands it, and region is the region the view draws the widget into.

MemberMeaning
ItemsThe rows, read fresh every frame
RenderTurns an item into the line that is drawn
ItemStyleOptional per-row style
PaintRowOptional: draws the row itself, for rows that are not one color
OnActivateRuns on Confirm or a second click; returns a route
SelectedIndexWhere the cursor is
IsFocusedSet by the focus ring

Keys and clicks

InputDoes
/ Move one row
PgUp / PgDnJump ten rows
Home / EndGo to the ends
ConfirmActivates the selected row
WheelScrolls
ClickSelects the row
Second click on the selected rowActivates it

All of them come from the keymap.

Focused and unfocused

The selected row is drawn ActiveSelection while the list has the focus and Selection while it does not, so a list beside another pane still shows where its cursor is. Those two roles are chosen so that neither reads as an error.

Scrolling

Only the visible slice is rendered — ScrollWindow.Around is the same helper the widget uses, available for lists you draw yourself.

A list with more items than rows grows a scroll bar down its last column, and the rows are truncated one cell earlier to make room rather than being covered by it. A list that fits keeps its full width and shows nothing.

Choice and multi-choice modals get the same treatment: a bar beside the options and a 3/40 readout on the filter line, worded by Strings.ListPosition.

Where the rows come from

Items is read while the frame is drawn, so the collection behind it belongs to the drawing thread. Change it from a view, a command or a callback, and hand changes that arrive from anywhere else to FrameThread.Post.

What is built on it

Table<T> and Tree<T> both hold a ListBox and hand it the rows they computed, so movement, clicks, activation and the scroll bar are the same in all three.