ListBox

@Composable
fun <T> ListBox(items: List<T>, modifier: SwingModifier = SwingModifier, selectedIndices: Set<Int>? = null, onSelectionChange: (Set<Int>) -> Unit = {}, selectionMode: Int = ListSelectionModel.MULTIPLE_INTERVAL_SELECTION, visibleRowCount: Int = 8, layoutOrientation: Int = JList.VERTICAL, prototypeCellValue: T? = null, fixedCellWidth: Int = -1, fixedCellHeight: Int = -1, itemContent: @Composable ListItemScope.(item: T) -> Unit? = null)

A column of rows the user picks from: a JList showing one row per item, reporting what the user selects.

Items are declarative data. By default each row renders its item's toString; supply itemContent to render an arbitrary composable cell per row (a Row of an icon, labels, ...). Selection is declared with selectedIndices and reported through onSelectionChange, expressed as the general multi-select shape so one component covers all of SelectionMode's modes. Place it in a org.jetbrains.compose.swing.components.layout.ScrollPane to scroll:

ScrollPane {
content {
ListBox(items = rows, selectedIndices = sel, onSelectionChange = { sel = it }) { row ->
FlowPanel { Label(row.icon); Label(row.name) }
}
}
}

onSelectionChange reports the user's selection changes only, once per settled change - so dragging across rows produces one callback at the end rather than one per row crossed, and rendering new items produces none. A declared selection is the composition's state and is re-applied on every pass: it survives an items change (an index the current items no longer cover is dropped), and a user change the caller does not adopt does not stand. Undeclared, the selection is the user's alone - never imposed, and kept across an items change all the same; where the new items are too few to hold it, the rows that fall outside them leave the selection and onSelectionChange reports what is left of it.

layoutOrientation decides how the cells are laid out: a single column, or wrapped into as many columns or rows as the space the list is given allows. A wrapping list draws far more cells at once, and a list sizes itself by measuring them - one measurement per row through the renderer, and with a composable itemContent each of those is a cell stamped through a nested composition. Declaring a prototypeCellValue collapses that to a single measurement every cell is sized by; fixedCellWidth and fixedCellHeight state a size outright and spare it even that one.

Parameters

items

the items to display

modifier

the SwingModifier applied to the underlying component

selectedIndices

the selected row indices the caller declares; null - the default - leaves the selection to the user

onSelectionChange

callback invoked when the user settles on a new selection

selectionMode

how many rows/ranges may be selected; MULTIPLE_INTERVAL_SELECTION - the default - lets the user select any number of ranges

visibleRowCount

how many rows the list asks a viewport to make room for; 8 is the default. Under VERTICAL_WRAP it is the number of rows a column holds before the cells wrap into the next one. Under HORIZONTAL_WRAP the list takes its column count from it and then fits the items into as few rows as those columns need, which can come out below the count asked for

layoutOrientation

whether the cells form a single column or wrap into columns or rows; VERTICAL - the default - is the single column

prototypeCellValue

an item measured once, through the same renderer the rows use, to size every cell; null - the default - measures each row for itself

fixedCellWidth

the width in pixels of every cell; -1 - the default - takes the width from prototypeCellValue, or from each row's own measurement where no prototype is declared

fixedCellHeight

the height in pixels of every cell; -1 - the default - takes the height from prototypeCellValue, or from each row's own measurement where no prototype is declared

itemContent

optional composable cell rendered per row against a ListItemScope; null keeps the default toString rendering

See also


@Composable
fun <T> ListBox(items: List<T>, listSelectionListener: ListSelectionListener, modifier: SwingModifier = SwingModifier, selectedIndices: Set<Int>? = null, selectionMode: Int = ListSelectionModel.MULTIPLE_INTERVAL_SELECTION, visibleRowCount: Int = 8, layoutOrientation: Int = JList.VERTICAL, prototypeCellValue: T? = null, fixedCellWidth: Int = -1, fixedCellHeight: Int = -1, itemContent: @Composable ListItemScope.(item: T) -> Unit? = null)

A ListBox driven by a raw ListSelectionListener instead of an onSelectionChange lambda. The listener sees the adjusting events of a drag as well as the settled one, and is notified of the user's selection changes only; the latest declared instance is the one notified, so the listener may be declared inline.

Parameters

items

the items to display

listSelectionListener

the listener notified of the user's selection changes

modifier

the SwingModifier applied to the underlying component

selectedIndices

the selected row indices the caller declares; null - the default - leaves the selection to the user

selectionMode

how many rows/ranges may be selected; MULTIPLE_INTERVAL_SELECTION - the default - lets the user select any number of ranges

visibleRowCount

how many rows the list asks a viewport to make room for; 8 is the default. Under VERTICAL_WRAP it is the number of rows a column holds before the cells wrap into the next one. Under HORIZONTAL_WRAP the list takes its column count from it and then fits the items into as few rows as those columns need, which can come out below the count asked for

layoutOrientation

whether the cells form a single column or wrap into columns or rows; VERTICAL - the default - is the single column

prototypeCellValue

an item measured once, through the same renderer the rows use, to size every cell; null - the default - measures each row for itself

fixedCellWidth

the width in pixels of every cell; -1 - the default - takes the width from prototypeCellValue, or from each row's own measurement where no prototype is declared

fixedCellHeight

the height in pixels of every cell; -1 - the default - takes the height from prototypeCellValue, or from each row's own measurement where no prototype is declared

itemContent

optional composable cell rendered per row against a ListItemScope; null keeps the default toString rendering

See also


@Composable
fun <T> ListBox(model: ListModel<T>, modifier: SwingModifier = SwingModifier, selectedIndices: Set<Int>? = null, onSelectionChange: (Set<Int>) -> Unit = {}, selectionMode: Int = ListSelectionModel.MULTIPLE_INTERVAL_SELECTION, visibleRowCount: Int = 8, layoutOrientation: Int = JList.VERTICAL, prototypeCellValue: T? = null, fixedCellWidth: Int = -1, fixedCellHeight: Int = -1, itemContent: @Composable ListItemScope.(item: T) -> Unit? = null)

A ListBox driven by a caller-owned ListModel instead of a declarative items list. The model is installed as-is and observed only: the library never mutates it, so element changes are the caller's responsibility. Selection is declared with selectedIndices and reported through onSelectionChange, and survives a model swap whether declared or not.

ScrollPane {
content {
ListBox(model = myModel, selectedIndices = sel, onSelectionChange = { sel = it })
}
}

onSelectionChange reports the user's selection changes only, once per settled change - so dragging across rows produces one callback at the end rather than one per row crossed, and installing a new model produces none. A declared selection is the composition's state and is re-applied on every pass, so a user change the caller does not adopt does not stand; undeclared, the selection is the user's alone and is never imposed - where the new model is too short to hold it, the rows that fall outside it leave the selection and onSelectionChange reports what is left of it.

Parameters

model

the caller-owned list model to display; installed as-is and never mutated

modifier

the SwingModifier applied to the underlying component

selectedIndices

the selected row indices the caller declares; null - the default - leaves the selection to the user

onSelectionChange

callback invoked when the user settles on a new selection

selectionMode

how many rows/ranges may be selected; MULTIPLE_INTERVAL_SELECTION - the default - lets the user select any number of ranges

visibleRowCount

how many rows the list asks a viewport to make room for; 8 is the default. Under VERTICAL_WRAP it is the number of rows a column holds before the cells wrap into the next one. Under HORIZONTAL_WRAP the list takes its column count from it and then fits the items into as few rows as those columns need, which can come out below the count asked for

layoutOrientation

whether the cells form a single column or wrap into columns or rows; VERTICAL - the default - is the single column

prototypeCellValue

an item measured once, through the same renderer the rows use, to size every cell; null - the default - measures each row for itself

fixedCellWidth

the width in pixels of every cell; -1 - the default - takes the width from prototypeCellValue, or from each row's own measurement where no prototype is declared

fixedCellHeight

the height in pixels of every cell; -1 - the default - takes the height from prototypeCellValue, or from each row's own measurement where no prototype is declared

itemContent

optional composable cell rendered per row against a ListItemScope; null keeps the default toString rendering

See also


@Composable
fun <T> ListBox(model: ListModel<T>, listSelectionListener: ListSelectionListener, modifier: SwingModifier = SwingModifier, selectedIndices: Set<Int>? = null, selectionMode: Int = ListSelectionModel.MULTIPLE_INTERVAL_SELECTION, visibleRowCount: Int = 8, layoutOrientation: Int = JList.VERTICAL, prototypeCellValue: T? = null, fixedCellWidth: Int = -1, fixedCellHeight: Int = -1, itemContent: @Composable ListItemScope.(item: T) -> Unit? = null)

A model-driven ListBox driven by a raw ListSelectionListener instead of an onSelectionChange lambda. The listener sees the adjusting events of a drag as well as the settled one, and is notified of the user's selection changes only; the latest declared instance is the one notified, so the listener may be declared inline.

The model is installed as-is and observed only: the library never mutates it, and the selection survives a model swap whether declared or not.

Parameters

model

the caller-owned list model to display; installed as-is and never mutated

listSelectionListener

the listener notified of the user's selection changes

modifier

the SwingModifier applied to the underlying component

selectedIndices

the selected row indices the caller declares; null - the default - leaves the selection to the user

selectionMode

how many rows/ranges may be selected; MULTIPLE_INTERVAL_SELECTION - the default - lets the user select any number of ranges

visibleRowCount

how many rows the list asks a viewport to make room for; 8 is the default. Under VERTICAL_WRAP it is the number of rows a column holds before the cells wrap into the next one. Under HORIZONTAL_WRAP the list takes its column count from it and then fits the items into as few rows as those columns need, which can come out below the count asked for

layoutOrientation

whether the cells form a single column or wrap into columns or rows; VERTICAL - the default - is the single column

prototypeCellValue

an item measured once, through the same renderer the rows use, to size every cell; null - the default - measures each row for itself

fixedCellWidth

the width in pixels of every cell; -1 - the default - takes the width from prototypeCellValue, or from each row's own measurement where no prototype is declared

fixedCellHeight

the height in pixels of every cell; -1 - the default - takes the height from prototypeCellValue, or from each row's own measurement where no prototype is declared

itemContent

optional composable cell rendered per row against a ListItemScope; null keeps the default toString rendering

See also


@Composable
fun <T> ListBox(items: List<T>, state: ListState, modifier: SwingModifier = SwingModifier, selectionMode: Int = ListSelectionModel.MULTIPLE_INTERVAL_SELECTION, visibleRowCount: Int = 8, layoutOrientation: Int = JList.VERTICAL, prototypeCellValue: T? = null, fixedCellWidth: Int = -1, fixedCellHeight: Int = -1, itemContent: @Composable ListItemScope.(item: T) -> Unit? = null)

A ListBox driven by a ListState instead of a declared selectedIndices and an onSelectionChange lambda. The state owns the selection: the rows it holds are what the list shows selected, the user's own selecting is written back into it, and it is where a row is revealed from.

val state = rememberListState()

ScrollPane {
ListBox(items = rows, state = state, modifier = SwingModifier.viewport())
}
Label("Selected: ${state.selectedIndices.size}")

Parameters

items

the items to display

state

the hoistable selection state the list applies and reports into; see ListState

modifier

the SwingModifier applied to the underlying component

selectionMode

how many rows/ranges may be selected; MULTIPLE_INTERVAL_SELECTION - the default - lets the user select any number of ranges

visibleRowCount

how many rows the list asks a viewport to make room for; 8 is the default. Under VERTICAL_WRAP it is the number of rows a column holds before the cells wrap into the next one. Under HORIZONTAL_WRAP the list takes its column count from it and then fits the items into as few rows as those columns need, which can come out below the count asked for

layoutOrientation

whether the cells form a single column or wrap into columns or rows; VERTICAL - the default - is the single column

prototypeCellValue

an item measured once, through the same renderer the rows use, to size every cell; null - the default - measures each row for itself

fixedCellWidth

the width in pixels of every cell; -1 - the default - takes the width from prototypeCellValue, or from each row's own measurement where no prototype is declared

fixedCellHeight

the height in pixels of every cell; -1 - the default - takes the height from prototypeCellValue, or from each row's own measurement where no prototype is declared

itemContent

optional composable cell rendered per row against a ListItemScope; null keeps the default toString rendering

See also


@Composable
fun <T> ListBox(model: ListModel<T>, state: ListState, modifier: SwingModifier = SwingModifier, selectionMode: Int = ListSelectionModel.MULTIPLE_INTERVAL_SELECTION, visibleRowCount: Int = 8, layoutOrientation: Int = JList.VERTICAL, prototypeCellValue: T? = null, fixedCellWidth: Int = -1, fixedCellHeight: Int = -1, itemContent: @Composable ListItemScope.(item: T) -> Unit? = null)

A model-driven ListBox driven by a ListState instead of a declared selectedIndices and an onSelectionChange lambda. The state owns the selection: the rows it holds are what the list shows selected, the user's own selecting is written back into it, and it is where a row is revealed from.

The model is installed as-is and observed only: the library never mutates it, so element changes are the caller's responsibility, and the selection survives a model swap.

Parameters

model

the caller-owned list model to display; installed as-is and never mutated

state

the hoistable selection state the list applies and reports into; see ListState

modifier

the SwingModifier applied to the underlying component

selectionMode

how many rows/ranges may be selected; MULTIPLE_INTERVAL_SELECTION - the default - lets the user select any number of ranges

visibleRowCount

how many rows the list asks a viewport to make room for; 8 is the default. Under VERTICAL_WRAP it is the number of rows a column holds before the cells wrap into the next one. Under HORIZONTAL_WRAP the list takes its column count from it and then fits the items into as few rows as those columns need, which can come out below the count asked for

layoutOrientation

whether the cells form a single column or wrap into columns or rows; VERTICAL - the default - is the single column

prototypeCellValue

an item measured once, through the same renderer the rows use, to size every cell; null - the default - measures each row for itself

fixedCellWidth

the width in pixels of every cell; -1 - the default - takes the width from prototypeCellValue, or from each row's own measurement where no prototype is declared

fixedCellHeight

the height in pixels of every cell; -1 - the default - takes the height from prototypeCellValue, or from each row's own measurement where no prototype is declared

itemContent

optional composable cell rendered per row against a ListItemScope; null keeps the default toString rendering

See also