Spinner

@Composable
fun Spinner(value: Number, onValueChange: (Number) -> Unit, modifier: SwingModifier = SwingModifier, min: Number? = null, max: Number? = null, step: Number = 1, format: String? = null, editor: @Composable () -> Unit? = null)

A JSpinner over numbers: it shows value in an editable field beside a pair of arrows that step it by step, through a SpinnerNumberModel built from min, max and step. A value the user leaves the spinner on and the caller does not answer with a matching value is settled back onto the declared one, so the spinner shows what the composition holds.

A null min or max leaves that side unbounded. Tightening either past the current value does not move the value, so the spinner can hold one outside its own range until the next value it takes. A bound is held in value's own class, so bounds and value may be declared in different classes.

The class of value is the class the field edits in: what it shows, what a commit is parsed back to, and what onValueChange is handed. A value declared in another class moves the field to that class, so a spinner declared an Int and later a Double edits decimals from then on.

Parameters

value

the current value.

onValueChange

callback invoked with the value the user changes the spinner to - a step, a scroll, or a committed edit - and with the value the spinner is left on where it cannot hold value; applying a value the spinner can hold is not itself reported.

modifier

the SwingModifier applied to the underlying component.

min

the smallest selectable value, held in value's class, or null for none.

max

the largest selectable value, held in value's class, or null for none.

step

the amount a step changes the value by; 1 by default. A step is taken in the class of the value it steps, so a whole-number step off a decimal value keeps the decimals.

format

the pattern the spinner formats and parses its value with - a DecimalFormat pattern; null formats it the way the locale does. A new pattern rebuilds the spinner's own editor around it.

editor

the editing surface the spinner shows in place of its own, composed into the spinner as a composition of its own joined to the caller's, so it reads the same state and locals the caller does; null leaves the editor the one the spinner builds for its own model. A fresh lambda each recomposition is fine - that composition recomposes rather than being rebuilt, so characters typed but not committed stand.

See also

Throws

if both a format and an editor are declared, if value falls outside min..max, if either bound is one value's class cannot hold exactly, or if a bound is declared over a BigInteger or BigDecimal value.


@Composable
fun Spinner(value: Date, onValueChange: (Date) -> Unit, modifier: SwingModifier = SwingModifier, start: Date? = null, end: Date? = null, calendarField: Int = Calendar.DAY_OF_MONTH, format: String? = null, editor: @Composable () -> Unit? = null)

A JSpinner over dates: it shows value in an editable field beside a pair of arrows that step it by one calendarField, through a SpinnerDateModel built from start and end.

A null start or end leaves that side unbounded. Tightening either past the current value does not move the value, so the spinner can hold one outside its own range until the next value it takes.

Parameters

value

the current value.

onValueChange

callback invoked with the value the user changes the spinner to - a step, a scroll, or a committed edit - and with the value the spinner is left on where it cannot hold value; applying a value the spinner can hold is not itself reported.

modifier

the SwingModifier applied to the underlying component.

start

the earliest selectable date, or null for none.

end

the latest selectable date, or null for none.

calendarField

the Calendar field a step moves the value by; DAY_OF_MONTH by default, so a step moves the date by one day.

format

the pattern the spinner formats and parses its value with - a SimpleDateFormat pattern; null formats it the way the locale does. A new pattern rebuilds the spinner's own editor around it.

editor

the editing surface the spinner shows in place of its own, composed into the spinner as a composition of its own joined to the caller's, so it reads the same state and locals the caller does; null leaves the editor the one the spinner builds for its own model. A fresh lambda each recomposition is fine - that composition recomposes rather than being rebuilt, so characters typed but not committed stand.

See also

Throws

if both a format and an editor are declared, or if value falls outside start..end.


@Composable
fun <T : Any> Spinner(items: List<T>, value: T?, onValueChange: (T) -> Unit, modifier: SwingModifier = SwingModifier, editor: @Composable () -> Unit? = null)

A JSpinner over items: it shows the one selected value in an editable field beside a pair of arrows that step from one item to the next, without wrapping at either end. Text typed at the end of the field is completed to the next item starting with it, so a distinguishing prefix is enough to commit one.

An empty items is allowed: the spinner then holds no value and steps neither forward nor back until items arrive. Assigning a new items moves the selection to its head.

Parameters

items

the values the spinner steps through, in order.

value

the current value, or null for no selection - the state an empty items leaves the spinner in, and the one to declare while a list is still loading. Declaring null against an items that does hold values settles the spinner on the head and reports it through onValueChange, since a spinner over items always shows one of them.

onValueChange

callback invoked with the value the user changes the spinner to - a step, or a committed edit landing on one of items, and with the value the spinner is left on where it cannot hold value; applying a value the spinner can hold is not itself reported.

modifier

the SwingModifier applied to the underlying component.

editor

the editing surface the spinner shows in place of its own, composed into the spinner as a composition of its own joined to the caller's, so it reads the same state and locals the caller does; null leaves the editor the one the spinner builds for its own model. A fresh lambda each recomposition is fine - that composition recomposes rather than being rebuilt, so characters typed but not committed stand.

See also


@Composable
fun Spinner(model: SpinnerModel, changeListener: ChangeListener, modifier: SwingModifier = SwingModifier, format: String? = null, editor: @Composable () -> Unit? = null)

A JSpinner over a caller-owned model, driven by a raw changeListener rather than by a value the spinner reports back. The changeListener is attached as-is and removed on the same instance; pass a stable instance (e.g. remember {}) to avoid churn. Swapping the model instance installs the new model verbatim.

Parameters

model

the model the spinner renders.

changeListener

the listener notified when the spinner's value changes.

modifier

the SwingModifier applied to the underlying component.

format

the pattern the spinner formats and parses its values with - a DecimalFormat pattern over a number model, a SimpleDateFormat pattern over a date model; null formats them the way the locale does. A new pattern rebuilds the spinner's own editor around it.

editor

the editing surface the spinner shows in place of its own, composed into the spinner as a composition of its own joined to the caller's, so it reads the same state and locals the caller does; null leaves the editor the one the spinner builds for its own model. A fresh lambda each recomposition is fine - that composition recomposes rather than being rebuilt, so characters typed but not committed stand.

See also

Throws

if both a format and an editor are declared, or if a format is declared over a model that is neither a number's nor a date's.