Collections
Table
Rows in columns that the user sorts, resizes and moves.
ui.Table puts a list's rows in columns, under a header of
ui.TableColumns, each with a title, a width (or 0 to share the room the
others leave) and an alignment; cell builds the content of a row's
column, usually a Text. It builds only the rows in view, as a list does,
and rows are as high as their tallest cell, so text that wraps makes its
row taller.
cols := []ui.TableColumn{{Title: "Name"}, {Title: "Size", Width: 90, Align: ui.End}}
app.files.Selected = &app.file
if ui.Table(c, &app.files, cols, len(files), func(row, col int) {
switch col {
case 0:
ui.Text(c, files[row].Name).SingleLine()
case 1:
ui.Text(c, files[row].Size())
}
}).Grow(1).Submitted() {
app.open(files[app.file])
}Choosing rows
The table takes the same ListState as a list, or nil, and takes the
keyboard focus for it: with Selected, a click or the keys choose a row,
with Selection several, and Submitted reports a double click or Enter;
Key, Label, Reorder and the rest work as for a list. A row Header
names spans every column, which cell builds as column 0, and stays at the
top while its section's rows scroll under it.
Arranging columns
The user arranges the columns, as in Finder:
- Resizing. Dragging the right edge of a column's header resizes the
column, between its
MinWidthandMaxWidth, and a double click there fits it to its cells. The columns before it that share the room left keep their widths, for the edge to follow the pointer. - Moving. Dragging a header moves its column among the others.
- Scrolling sideways. Columns wider than the table scroll sideways, the header with them.
- Fixed columns. A
Fixedcolumn stays where it is, as wide as it is.
ListState.Columns keeps the order and the widths, by the columns' IDs
(their titles by default): set it from saved settings to restore them, and
save it as it changes.
Sorting
With ListState.Sort, a click on the header of a Sortable column sorts
the rows by it, ascending, and a second click reverses the order: the header
shows an arrow, assistive technology reads the order, and the table's
Changed reports it. The table shows the rows in the order cell gets
them, so sort them as it says, keyed by Key for the choice to follow its
rows:
cols := []ui.TableColumn{{Title: "Name", Sortable: true}, {Title: "Size", Width: 90, Align: ui.End, Sortable: true}}
app.files.Sort = &app.sort
sorted := sortFiles(app.files, app.sort) // by app.sort.Column, Descending or not
app.files.Key = func(i int) any { return sorted[i].ID }Renaming in place
An editable text in a cell is renamed in place, as Finder's file names: Return on macOS and F2 elsewhere edit the chosen row's text, as does a click on it once the row is chosen.
ui.Table(c, &app.files, cols, len(files), func(row, col int) {
if col == 0 && ui.EditableText(c, &files[row].Name).Changed() {
app.rename(files[row])
}
})Accessibility
Assistive technology sees a table, named by its Label, of rows named by
the text inside them, each saying which of all the rows it is, with column
headers that say the order the rows are sorted in.
For a tree of rows in columns, see Outline.