From Swing to Compose Desktop #4
Tags: java, kotlin, ux
Published: 2020-12-02 09:15:27

Welcome to the 4. post about my journey of transforming a Java Swing app to Compose for Desktop. Today I will focus on multiple selections in a list. When TKDupeFinder detects, say 10, files with the same MD5 hash their content is very likely the same. Consequently 9 of them are candidates for deletion. The app will provide two buttons, **Show** and **Delete** which will, well, show or delete files that have been selected in a list. Let's see how we can

- create a scrollable list
- and allow multiple selections

To wet your appetite, here is how things will look:

{% youtube fkm_I167q10 %}

And here comes the code that does the magic.

```kotlin
@Composable
fun ThirdRow(currentPos: Int, checksums: List<String>,
             selected: SnapshotStateMap<Int, Boolean>) {
    val items = if (checksums.isNotEmpty())
        df.getFiles(checksums[currentPos]) else emptyList()
    LazyColumnForIndexed(items,
            modifier = Modifier.fillMaxSize().padding(8.dp),
            itemContent = { index, item ->
                val current = selected[index] ?: false
                ListItem(secondaryText = { Text(item.parent) },
                        modifier = Modifier.toggleable(onValueChange = {
                            selected[index] = !current
                        },
                                value = current)
                                .background(if (current)
                                    Color.LightGray else Color.Transparent),
                        text = { Text(item.name) })
            })
}
```

`LazyColumnForIndexed()` provides the list. The contents to be displayed are already there. `currentPos` identifies the checksum whose files should be presented. So, with `df.getFiles(checksums[currentPos])` I get a list of files, which are passed to `LazyColumnForIndexed()`.

When a new list element needs to be created, `itemContent` is invoked. It gets an index and the item. I use the index to track if an element is currently selected. This map is passed to my composable (`SnapshotStateMap<Int, Boolean>`) because it needs to be altered somewhere else, too. Such changes must trigger recompositions, that is why I use a state.

`ListItem`s can be configured to have several lines of text and an icon. Most importantly, you can use its `modifier` to make it `toggleable`. If that happens, `onValueChange` is invoked. As you can see, I just need to flip a `Boolean`. Depending on the current value, my item has either a transparent or light gray background.

As you can see, with just a handful lines of code you get a nice looking scrollable list with multiple selection. Did you need to implement multiple selection lists in Compose? How did you implement that? Please share your solution in the comments, I would love to hear them.

---
[From Swing to Jetpack Compose Desktop #1](https://dev.to/tkuenneth/from-swing-to-jetpack-compose-desktop-1-12kf)
[From Swing to Jetpack Compose Desktop #2](https://dev.to/tkuenneth/from-swing-to-jetpack-compose-desktop-2-4a4h)
[From Swing to Compose Desktop #3](https://dev.to/tkuenneth/from-swing-to-compose-desktop-3-23ck)