Skip to content

UXTableView

UXTableView follows the AppKit split: the table does not hold your data, it asks for it. You implement two methods and the table does the rest:

protocol UXTableDataSource {
i32 numberOfRows(UXTableView* t);
u8* valueForCell(UXTableView* t, i32 row, i32 col);
}

The table also leaves several jobs to other parts of the toolkit:

  • Scrollbar. The scroll machinery owns it, fed by contentHeight.
  • Hit-testing. The ordinary tree hit test lands a click on a scrolled row, because scrolling moves the rows in the tree.
  • Text drawing. A cell is realized content that the platform draws.
  • Click routing. A cell does not override mouseDown, so the responder chain carries the click up to its row. That makes the row the selectable object even though the cell was hit.

On Win32 and AppKit a native table (UXList32, NSTableView) overlays the whole subtree. On GEM the rows are AES objects.

Lifetime rule: the string valueForCell returns goes straight into the realized cell and is read on every draw. Nothing is copied. Return a literal or a buffer the data source owns; it must outlive the table.

#use <UXKit>
class Contacts : Object <UXTableDataSource> {
i32 numberOfRows(UXTableView* t) { return (i32)people.count(); }
u8* valueForCell(UXTableView* t, i32 row, i32 col) {
return col == (i32)0 ? nameAt(row) : phoneAt(row);
}
}
UXTableView* table = new UXTableView();
table.addColumn((u8*)"Name", 140);
table.addColumn((u8*)"Phone", 100);
table.setDataSource(src); // GLOBAL or owned: the table holds it weakly
table.setDelegate(controller);
table.reloadData();

The data source is held weakly. Keep it alive yourself (a global, or a controller field). A temporary is released as soon as setDataSource returns.

Data · setDataSource · reloadData · rowCount Columns · addColumn · numberOfColumns Selection · selection · selectRow · deselectAllRows · isRowSelected · selectedCount · selectedRows · selectedRowList · setRowSelected · setAllowsMultipleSelection · allowsMultipleSelection Delegate · setDelegate Geometry · setRowHeight · contentHeight · countRows · columnTitle · columnWidth · rowHeightValue

void setDataSource(UXTableDataSource* d)

Attaches the source, weakly (see above).

void reloadData(void)

Asks the source for everything again and rebuilds the rows. Call it after your data changes.

i32 rowCount(void)

How many rows the last reload found.

void addColumn(u8* title, i16 width)

Appends a titled column of the given width. Call it before the first reload.

i32 numberOfColumns(void)

How many columns the table has.

i32 selection(void)

The anchor row: the last row clicked, or -1 for none. With multi-selection this is the shift-extend anchor; use isRowSelected for the full selection.

void selectRow(i32 r)

Selects a row from code and announces it through the delegate, on the same path a click takes.

void deselectAllRows(void)

Clears the selection and announces it.

bool isRowSelected(i32 r)

Whether the row is in the selection.

i32 selectedCount(void)

How many rows are selected.

i32 selectedRows(i32* out, i32 max) // returns the TOTAL selected
i32 selectedRowList(i32* out, i32 max) // returns how many it WROTE

Both fill out with selected row indices, up to max. They differ in what they return.

void setRowSelected(i32 r, bool on)

Sets one row’s selection without going through the click path. The anchor does not move and no delegate notification fires.

Out-of-range indices are ignored, so restoring a saved selection against a table that has since shrunk needs no bounds check.

setAllowsMultipleSelection / allowsMultipleSelection

Section titled “setAllowsMultipleSelection / allowsMultipleSelection”
void setAllowsMultipleSelection(bool on)
bool allowsMultipleSelection(void)

Off (default): one row at a time. On: ctrl toggles a row and shift extends a range from the anchor, following the platform conventions on every backend.

countRows / columnTitle / columnWidth / rowHeightValue

Section titled “countRows / columnTitle / columnWidth / rowHeightValue”
i32 countRows(void)
u8* columnTitle(i32 c)
i16 columnWidth(i32 c)
i16 rowHeightValue(void)

The readers behind the setters. A driver uses them to build a native table from the neutral model. An application uses them to lay something out beside the table (a header, a summary line, a print layout) without keeping a second copy of the geometry.

void setDelegate(UXTableDelegate* d)

Sets the object that receives announcements. The protocol has one optional method:

protocol UXTableDelegate {
optional void tableSelectionDidChange(UXTableView* t, i32 row);
}
void setRowHeight(i16 h)

The uniform row height. It is also the scroll view’s natural line step.

i16 contentHeight(void)

rows × rowHeight, the value passed to the scroll machinery.

UXTableColumn (title and width), UXTableHeader (the pinned title strip), UXTableRow (the selectable line), and UXTableCell (one realized string). For hierarchy, see UXOutlineView, a table whose row list is derived from a tree.

UXTableView on Web

The toolkit-drawn table: header strip, rows, and the selection band.