Class Column<T>
- Type Parameters:
T- the row type
Table: a title, how a row becomes a cell, how rows compare on it, and
how wide it is.
A column is built once by the application and handed to the table. Three factories cover
the everyday cases — text(limn.i18n.I18nString, java.util.function.Function<T, java.lang.String>), numeric(limn.i18n.I18nString, java.util.function.ToDoubleFunction<T>) and of(limn.i18n.I18nString, java.util.function.Function<T, V>, java.util.function.Function<? super V, java.lang.String>) with a formatter
— and widget is the seam for a cell that is a control rather than a value: a
switch, a button, an icon. Everything after the factory is a fluent setter.
The language a cell is written in is the table's own:
every formatter a column runs, a cell's, a footer's and the text a sort falls back to, runs with
the table's locale in scope, so NumberFormats,
DateFormats and anything else that reads I18n.locale() write a cell
in the table's language even when the table reads its rows again outside a pass.
The UI thread. Every setter runs on the UI thread, as every widget's does, and throws
IllegalStateException on any other thread and before a backend is running. The table
reads its columns on that thread while it lays out, sorts and paints, and a column changes under
a table that already holds it (a width, a visibility), so a column written from another thread
is a race with that reading, one nothing would report. Build the columns where the table is
built, on the UI thread.
Widths. A column has a preferred width, a minimum, and a weight. Layout gives every
column its preferred width and then shares what is left of the viewport among the weighted
ones, as Expanded shares a row's leftover; a table whose preferred widths exceed the
viewport scrolls sideways rather than crushing anything below its minimum. A width the user
dragged is held here, so it survives a Table.refresh(), and is held as dragged: the
column takes no share of the leftover until resetWidth(), so the divider stays where
the pointer left it and the other weighted columns take up the difference.
Sorting. A header click sorts through compare(T, T, java.text.Collator, java.util.Locale): a comparator the application
named, else the values themselves — numbers numerically, strings through the language's
collator, anything else comparable by itself — else the formatted text. Numbers compare
exactly, so a long id past 2^53 or a BigDecimal amount keeps its place, and a
column whose values differ in kind sorts its numbers first, then its text, then the rest, each
among its own kind. A widget column has no value and is not sortable unless given a comparator.
The footer. A column may put something in the table's summary row, which is pinned
under the rows the way the header is pinned over them and appears as soon as one column has
something for it: a fixed text (footer(I18nString)), a value computed from all the
rows and formatted as the cells are (footer(Function)), or one of the aggregates a
numeric column offers (footerSum(), footerAverage(), footerMin(),
footerMax()) and the count any column does (footerCount()). The table computes
it on Table.setRows(java.util.List<T>) and Table.refresh(), never per frame.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic enumWhere a cell's text sits across its column. -
Method Summary
Modifier and TypeMethodDescriptionalign(Column.Alignment alignment) Sets where a cell's text sits across the column (defaultColumn.Alignment.START, orColumn.Alignment.ENDfor anumeric(limn.i18n.I18nString, java.util.function.ToDoubleFunction<T>)column).Takes the footer cell away, asfooter(null)would: that call does not compile, becausenullfits more than one of the overloads.comparator(@Nullable Comparator<T> comparator) Names how rows compare on this column, replacing the comparison derived from the value.static <T> Column<T> currency(String title, ToDoubleFunction<T> value, Currency currency) currency(I18nString, ToDoubleFunction, Currency)with a literal title.static <T> Column<T> currency(I18nString title, ToDoubleFunction<T> value, Currency currency) A column of amounts in one currency, written as the language in effect writes money (NumberFormats.currency(Currency)): the symbol, its side, the decimals and the separators are the locale's, and a footer sum is money too.footer(I18nString)with a literal text.Computes this column's footer cell from all the rows, and formats the result as the column's cells are formatted: atext(limn.i18n.I18nString, java.util.function.Function<T, java.lang.String>)column expects a string back, anumeric(limn.i18n.I18nString, java.util.function.ToDoubleFunction<T>)one anyNumber, anof(limn.i18n.I18nString, java.util.function.Function<T, V>, java.util.function.Function<? super V, java.lang.String>)column a value of its own type.footer(@Nullable I18nString text) Puts a fixed text in this column's footer cell: "Total", say, beside the sums.Averages the column's numbers in the footer; empty when there are no rows.The row count in the footer, localized as a number; any column may carry it.The largest of the column's numbers in the footer; empty when there are no rows.The smallest of the column's numbers in the footer; empty when there are no rows.Sums the column's numbers in the footer.booleanbooleanbooleanbooleanfloatminWidth()minWidth(float points) Sets the width below which neither layout nor a drag takes this column (default 40).static <T> Column<T> numeric(String title, ToDoubleFunction<T> value) numeric(I18nString, ToDoubleFunction)with a literal title.static <T> Column<T> numeric(String title, ToDoubleFunction<T> value, DoubleFunction<String> format) numeric(I18nString, ToDoubleFunction, DoubleFunction)with a literal title.static <T> Column<T> numeric(I18nString title, ToDoubleFunction<T> value) A column of numbers: aligned to the reading end, formatted and localized as the charts format an axis, and sorted numerically.static <T> Column<T> numeric(I18nString title, ToDoubleFunction<T> value, DoubleFunction<String> format) A column of numbers written byformat, which is any ofNumberFormatsor the application's ownDoubleFunction<String>:NumberFormats.prefix("R$ ")for a fixed prefix,decimals(2),unit(" kg"),percent(1),compact().static <T,V> Column <T> of(I18nString, Function, BiFunction)with a literal title.static <T,V> Column <T> of(I18nString, Function, Function)with a literal title.static <T,V> Column <T> of(I18nString title, Function<T, @Nullable V> value, BiFunction<V, Locale, String> format) A column over any value, with a formatter that is handed the locale to write it in:I18n.numberLocale()under the table's language, the locale the toolkit writes numbers in.static <T,V> Column <T> of(I18nString title, Function<T, @Nullable V> value, Function<? super V, String> format) A column over any value, with a format that turns it into text and reads the language in effect as it does, asDateFormatsandNumberFormatsdo: a date throughDateFormats.date(FormatStyle.SHORT), an enum through its own words.voidForgets a width the user dragged, so layout starts from the preferred width again and the column's weight takes its share of the leftover again.sortable(boolean sortable) Sets whether a header click sorts on this column (default on).static <T> Column<T> text(I18nString, Function)with a literal title, for a header no translation covers.static <T> Column<T> text(I18nString title, Function<T, @Nullable String> value) A column of text.title()visible(boolean visible) Shows or hides the column.floatweight()weight(float weight) Sets this column's share of the viewport width left over once every column has its preferred width (default 0: keep the preferred width).static <T> Column<T> widget(String title, BiFunction<T, Supplier<T>, Widget<?>> factory) widget(I18nString, BiFunction)with a literal title.static <T> Column<T> widget(I18nString, Function)with a literal title.static <T> Column<T> widget(I18nString title, BiFunction<T, Supplier<T>, Widget<?>> factory) A column whose cells are widgets that act on their row's record as the table holds it when they act: the factory is handed the row it builds the cell for and a supplier of that row's record, which a control reads in its handler.static <T> Column<T> widget(I18nString title, Function<T, Widget<?>> factory) A column whose cells are widgets: one is built per realized row and released with it, so the factory is called again for a row that scrolled out and back.floatwidth()width(float points) Sets the width layout starts from, in points (default 120).
-
Method Details
-
text
A column of text.- Type Parameters:
T- the row type- Parameters:
title- what the header saysvalue- the text of a row's cell;nulldraws an empty cell- Returns:
- the column
-
text
text(I18nString, Function)with a literal title, for a header no translation covers.- Type Parameters:
T- the row type- Parameters:
title- what the header saysvalue- the text of a row's cell- Returns:
- the column
-
numeric
A column of numbers: aligned to the reading end, formatted and localized as the charts format an axis, and sorted numerically.- Type Parameters:
T- the row type- Parameters:
title- what the header saysvalue- a row's number- Returns:
- the column
-
numeric
public static <T> Column<T> numeric(I18nString title, ToDoubleFunction<T> value, DoubleFunction<String> format) A column of numbers written byformat, which is any ofNumberFormatsor the application's ownDoubleFunction<String>:NumberFormats.prefix("R$ ")for a fixed prefix,decimals(2),unit(" kg"),percent(1),compact(). The footer's aggregates are written by the same format, so a sum of prices is a price.- Type Parameters:
T- the row type- Parameters:
title- what the header saysvalue- a row's numberformat- the number as text, reading the locale in effect when it formats- Returns:
- the column
-
numeric
public static <T> Column<T> numeric(String title, ToDoubleFunction<T> value, DoubleFunction<String> format) numeric(I18nString, ToDoubleFunction, DoubleFunction)with a literal title.- Type Parameters:
T- the row type- Parameters:
title- what the header saysvalue- a row's numberformat- the number as text- Returns:
- the column
-
currency
public static <T> Column<T> currency(I18nString title, ToDoubleFunction<T> value, Currency currency) A column of amounts in one currency, written as the language in effect writes money (NumberFormats.currency(Currency)): the symbol, its side, the decimals and the separators are the locale's, and a footer sum is money too.- Type Parameters:
T- the row type- Parameters:
title- what the header saysvalue- a row's amount, incurrencycurrency- the currency the amounts are in- Returns:
- the column
-
currency
currency(I18nString, ToDoubleFunction, Currency)with a literal title.- Type Parameters:
T- the row type- Parameters:
title- what the header saysvalue- a row's amountcurrency- the currency the amounts are in- Returns:
- the column
-
numeric
numeric(I18nString, ToDoubleFunction)with a literal title.- Type Parameters:
T- the row type- Parameters:
title- what the header saysvalue- a row's number- Returns:
- the column
-
of
public static <T,V> Column<T> of(I18nString title, Function<T, @Nullable V> value, Function<? super V, String> format) A column over any value, with a format that turns it into text and reads the language in effect as it does, asDateFormatsandNumberFormatsdo: a date throughDateFormats.date(FormatStyle.SHORT), an enum through its own words. The table's locale is in scope while it formats.- Type Parameters:
T- the row typeV- the value type- Parameters:
title- what the header saysvalue- a row's value;nulldraws an empty cell and sorts firstformat- the value as text; never asked fornull- Returns:
- the column
-
of
public static <T,V> Column<T> of(String title, Function<T, @Nullable V> value, Function<? super V, String> format) of(I18nString, Function, Function)with a literal title.- Type Parameters:
T- the row typeV- the value type- Parameters:
title- what the header saysvalue- a row's valueformat- the value as text- Returns:
- the column
-
of
public static <T,V> Column<T> of(I18nString title, Function<T, @Nullable V> value, BiFunction<V, Locale, String> format) A column over any value, with a formatter that is handed the locale to write it in:I18n.numberLocale()under the table's language, the locale the toolkit writes numbers in. It names the numbering system the toolkit writes (-u-nu-) wherever the platform would otherwise write other digits, soString.format(locale, "%.1f MB", mb)writes1234.5as1234.5 MBunder a barearand١٢٣٤٫٥ MBunderar-EG, in the digits of the numeric columns beside it; the bare locale wrote Arabic-Indic digits underar, where the toolkit writes Latin ones. The language is the table's: a month's name or a word looked up under this locale is in that language. A date wantsof(I18nString, Function, Function)withDateFormatsinstead, because the platform writes a date in ASCII digits under any locale.- Type Parameters:
T- the row typeV- the value type- Parameters:
title- what the header saysvalue- a row's value;nulldraws an empty cell and sorts firstformat- the value as text under the locale handed to it; never asked fornull- Returns:
- the column
-
of
public static <T,V> Column<T> of(String title, Function<T, @Nullable V> value, BiFunction<V, Locale, String> format) of(I18nString, Function, BiFunction)with a literal title.- Type Parameters:
T- the row typeV- the value type- Parameters:
title- what the header saysvalue- a row's valueformat- the value as text under the locale handed to it- Returns:
- the column
-
widget
A column whose cells are widgets: one is built per realized row and released with it, so the factory is called again for a row that scrolled out and back. Not sortable unlesscomparatornames how.The factory is handed the record the table holds for the row as the cell is built, and a control made here acts on that object. A row that
Table.setRows(java.util.List<T>)orTable.refresh()keeps, because a popup hangs from one of its widget cells or the keyboard is in one, keeps the widgets built then; where the list now holds a new object equal to the old, as after a server's push, they go on acting on the old one until the row is built again. A control that writes to its record, a combo box or a check box that sets a field, takeswidget(I18nString, BiFunction), whose writes land in the record the table holds.- Type Parameters:
T- the row type- Parameters:
title- what the header saysfactory- the widget for a row's cell- Returns:
- the column
-
widget
widget(I18nString, Function)with a literal title.- Type Parameters:
T- the row type- Parameters:
title- what the header saysfactory- the widget for a row's cell- Returns:
- the column
-
widget
A column whose cells are widgets that act on their row's record as the table holds it when they act: the factory is handed the row it builds the cell for and a supplier of that row's record, which a control reads in its handler. The supplier answers the object the factory was handed until aTable.setRows(java.util.List<T>)or aTable.refresh()keeps the cell's row (because a popup hangs from one of its widget cells, such as a combo box's open list, or the keyboard is in one) while the list now holds another object for that record, as a server's push of new objects equal to the old does; from then on it answers that object. So a choice made in a list that stayed open through the push lands in the record the table holds, and the row shows it when it is built again, where a control holding on to the object it was built with would have written to one the table no longer holds.Column.<Order>widget("Status", (order, current) -> { ComboBox<Status> box = new ComboBox<>(List.of(Status.values())); box.setSelectedItem(order.status()); box.onSelect(() -> current.get().setStatus(box.selectedItem())); return box; });Ask it on the UI thread, where a control's handlers run. Once the row has left the table it answers the last record it was bound to. In every other respect this is
widget(I18nString, Function).- Type Parameters:
T- the row type- Parameters:
title- what the header saysfactory- the widget for a row's cell, from the row and the supplier of its record now- Returns:
- the column
-
widget
widget(I18nString, BiFunction)with a literal title.- Type Parameters:
T- the row type- Parameters:
title- what the header saysfactory- the widget for a row's cell, from the row and the supplier of its record now- Returns:
- the column
-
title
- Returns:
- what the header says
-
isWidgetColumn
public boolean isWidgetColumn()- Returns:
- whether this column's cells are widgets rather than values
-
comparator
Names how rows compare on this column, replacing the comparison derived from the value. A table sorted on this column sorts again at once, asTable.setSort(limn.components.table.Column<T>, limn.components.table.SortOrder)would: the focus cell, the range anchor and a widget cell holding the keyboard go with their records, and the selection stays with its own. A table whoseTable.onSortRequestorders the rows itself keeps them as they are. A comparator that leaves the column unable to compare (nullon a widget column) takes the table's sort on it away. UI thread only.- Parameters:
comparator- the order;nullrestores the derived one- Returns:
- this column
-
sortable
Sets whether a header click sorts on this column (default on). A column that cannot compare — a widget column with no comparator — is not sortable whatever this says. A table sorted on this column when it stops being sortable goes back to the model's order at once, asTable.setSort(limn.components.table.Column<T>, limn.components.table.SortOrder)withSortOrder.NONEwould, the focus cell and the range anchor going with their records. UI thread only.- Parameters:
sortable- whether a click sorts- Returns:
- this column
-
isSortable
public boolean isSortable()- Returns:
- whether a header click sorts on this column
-
align
Sets where a cell's text sits across the column (defaultColumn.Alignment.START, orColumn.Alignment.ENDfor anumeric(limn.i18n.I18nString, java.util.function.ToDoubleFunction<T>)column). UI thread only.- Parameters:
alignment- where the text sits- Returns:
- this column
-
alignment
- Returns:
- where a cell's text sits across the column
-
width
Sets the width layout starts from, in points (default 120). A width the user dragged replaces it untilresetWidth(). UI thread only.- Parameters:
points- the preferred width; at least the minimum- Returns:
- this column
-
minWidth
Sets the width below which neither layout nor a drag takes this column (default 40). UI thread only.- Parameters:
points- the floor- Returns:
- this column
-
weight
Sets this column's share of the viewport width left over once every column has its preferred width (default 0: keep the preferred width). A weight of 1 on one column makes it take all of the leftover; equal weights on two share it equally. A column whose width the user dragged takes no share untilresetWidth(). UI thread only.- Parameters:
weight- the share; zero or more- Returns:
- this column
-
visible
Shows or hides the column. A hidden column takes no space, is not published to a screen reader, builds no widget for its cells when it is a widget column, and keeps its widths for when it returns. The change is picked up by the table's next layout, which releases a hidden widget column's widgets and builds a newly shown one's and leaves every other cell's widget alone, a focused one included; the table asks for that layout itself.Table.refresh()asks for one too, and as every refresh does rebuilds the realized rows except the one whose widget cell holds the keyboard, which stays with its record while the list still holds it (and hands the keyboard to the table when its own column is the one hidden, or its record is gone). A focus cell, or the header's cursor, on the hidden column moves to the nearest shown column. UI thread only.- Parameters:
visible- whether the column is shown- Returns:
- this column
-
isVisible
public boolean isVisible()- Returns:
- whether the column is shown
-
resetWidth
public void resetWidth()Forgets a width the user dragged, so layout starts from the preferred width again and the column's weight takes its share of the leftover again. UI thread only. -
width
public float width()- Returns:
- the width layout starts from: the one the user dragged, else the preferred one
-
minWidth
public float minWidth()- Returns:
- the floor under this column's width
-
weight
public float weight()- Returns:
- this column's share of the leftover width
-