Skip to content

Commit

Permalink
LazyTree - contiguous selection appearance (#251)
Browse files Browse the repository at this point in the history
contiguous selection appearance fixed
  • Loading branch information
fscarponi authored Nov 27, 2023
1 parent 4cf1eeb commit a789ab1
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 32 deletions.
12 changes: 6 additions & 6 deletions foundation/api/foundation.api
Original file line number Diff line number Diff line change
Expand Up @@ -306,13 +306,13 @@ public final class org/jetbrains/jewel/foundation/lazy/SelectableLazyListState :
public final fun getLastActiveItemIndex ()Ljava/lang/Integer;
public final fun getLayoutInfo ()Landroidx/compose/foundation/lazy/LazyListLayoutInfo;
public final fun getLazyListState ()Landroidx/compose/foundation/lazy/LazyListState;
public fun getSelectedKeys ()Ljava/util/List;
public fun getSelectedKeys ()Ljava/util/Set;
public fun isScrollInProgress ()Z
public fun scroll (Landroidx/compose/foundation/MutatePriority;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun scrollToItem (IZILkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static synthetic fun scrollToItem$default (Lorg/jetbrains/jewel/foundation/lazy/SelectableLazyListState;IZILkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object;
public final fun setLastActiveItemIndex (Ljava/lang/Integer;)V
public fun setSelectedKeys (Ljava/util/List;)V
public fun setSelectedKeys (Ljava/util/Set;)V
}

public final class org/jetbrains/jewel/foundation/lazy/SelectableLazyListStateKt {
Expand All @@ -322,8 +322,8 @@ public final class org/jetbrains/jewel/foundation/lazy/SelectableLazyListStateKt
}

public abstract interface class org/jetbrains/jewel/foundation/lazy/SelectableScope {
public abstract fun getSelectedKeys ()Ljava/util/List;
public abstract fun setSelectedKeys (Ljava/util/List;)V
public abstract fun getSelectedKeys ()Ljava/util/Set;
public abstract fun setSelectedKeys (Ljava/util/Set;)V
}

public final class org/jetbrains/jewel/foundation/lazy/SelectionMode : java/lang/Enum {
Expand Down Expand Up @@ -638,12 +638,12 @@ public final class org/jetbrains/jewel/foundation/lazy/tree/TreeState : androidx
public fun getCanScrollBackward ()Z
public fun getCanScrollForward ()Z
public final fun getOpenNodes ()Ljava/util/Set;
public fun getSelectedKeys ()Ljava/util/List;
public fun getSelectedKeys ()Ljava/util/Set;
public fun isScrollInProgress ()Z
public final fun openNodes (Ljava/util/List;)V
public fun scroll (Landroidx/compose/foundation/MutatePriority;Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun setOpenNodes (Ljava/util/Set;)V
public fun setSelectedKeys (Ljava/util/List;)V
public fun setSelectedKeys (Ljava/util/Set;)V
public final fun toggleNode (Ljava/lang/Object;)V
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public interface SelectableColumnOnKeyEvent {
for (index in allKeys.indices) {
val key = allKeys[index]
if (key is Selectable) {
state.selectedKeys = listOf(key.key)
state.selectedKeys = setOf(key.key)
state.lastActiveItemIndex = index
return
}
Expand All @@ -34,7 +34,7 @@ public interface SelectableColumnOnKeyEvent {
state: SelectableLazyListState,
) {
val initialIndex = state.lastActiveItemIndex ?: return
val newSelection = ArrayList<Any>(max(initialIndex, state.selectedKeys.size)).apply {
val newSelection = HashSet<Any>(max(initialIndex, state.selectedKeys.size)).apply {
addAll(state.selectedKeys)
}
var lastActiveItemIndex = initialIndex
Expand All @@ -59,7 +59,7 @@ public interface SelectableColumnOnKeyEvent {
for (index in keys.lastIndex downTo 0) {
val key = keys[index]
if (key is Selectable) {
state.selectedKeys = listOf(key.key)
state.selectedKeys = setOf(key.key)
state.lastActiveItemIndex = index
return
}
Expand All @@ -75,7 +75,7 @@ public interface SelectableColumnOnKeyEvent {
state: SelectableLazyListState,
) {
val initialIndex = state.lastActiveItemIndex ?: return
val newSelection = ArrayList<Any>(max(keys.size - initialIndex, state.selectedKeys.size)).apply {
val newSelection = HashSet<Any>(max(keys.size - initialIndex, state.selectedKeys.size)).apply {
addAll(state.selectedKeys)
}
var lastActiveItemIndex = initialIndex
Expand All @@ -101,7 +101,7 @@ public interface SelectableColumnOnKeyEvent {
for (index in initialIndex - 1 downTo 0) {
val key = keys[index]
if (key is Selectable) {
state.selectedKeys = listOf(key.key)
state.selectedKeys = setOf(key.key)
state.lastActiveItemIndex = index
return
}
Expand Down Expand Up @@ -138,7 +138,7 @@ public interface SelectableColumnOnKeyEvent {
for (index in initialIndex + 1..keys.lastIndex) {
val key = keys[index]
if (key is Selectable) {
state.selectedKeys = listOf(key.key)
state.selectedKeys = setOf(key.key)
state.lastActiveItemIndex = index
return
}
Expand Down Expand Up @@ -173,7 +173,7 @@ public interface SelectableColumnOnKeyEvent {
) {
val visibleSize = state.layoutInfo.visibleItemsInfo.size
val targetIndex = max((state.lastActiveItemIndex ?: 0) - visibleSize, 0)
state.selectedKeys = listOf(keys[targetIndex].key)
state.selectedKeys = setOf(keys[targetIndex].key)
state.lastActiveItemIndex = targetIndex
}

Expand Down Expand Up @@ -206,7 +206,7 @@ public interface SelectableColumnOnKeyEvent {
) {
val visibleSize = state.layoutInfo.visibleItemsInfo.size
val targetIndex = min((state.lastActiveItemIndex ?: 0) + visibleSize, keys.lastIndex)
state.selectedKeys = listOf(keys[targetIndex].key)
state.selectedKeys = setOf(keys[targetIndex].key)
state.lastActiveItemIndex = targetIndex
}

Expand Down Expand Up @@ -240,7 +240,7 @@ public interface SelectableColumnOnKeyEvent {
* Select All.
*/
public fun onSelectAll(keys: List<SelectableLazyListKey>, state: SelectableLazyListState) {
state.selectedKeys = keys.filterIsInstance<Selectable>().map { it.key }
state.selectedKeys = keys.filterIsInstance<Selectable>().map { it.key }.toSet()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public val SelectableLazyListState.visibleItemsRange: IntRange

public interface SelectableScope {

public var selectedKeys: List<Any>
public var selectedKeys: Set<Any>
}

/**
Expand All @@ -36,7 +36,7 @@ public class SelectableLazyListState(

internal var lastKeyEventUsedMouse: Boolean = false

override var selectedKeys: List<Any> by mutableStateOf(emptyList<Any>())
override var selectedKeys: Set<Any> by mutableStateOf(emptySet())

public var lastActiveItemIndex: Int? = null

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
Expand Down Expand Up @@ -149,8 +149,21 @@ public fun <T> BasicLazyTree(
?: false,
)

val backgroundShape by remember {
mutableStateOf(RoundedCornerShape(elementBackgroundCornerSize))
val backgroundShape by derivedStateOf {
val hasRoundedTopCorners = flattenedTree.getOrNull(index - 1)?.id?.let {
it !in treeState.delegate.selectedKeys
} ?: false
val hasRoundedBottomCorners = flattenedTree.getOrNull(index + 1)?.id?.let {
it !in treeState.delegate.selectedKeys
} ?: false
val topCornerSize = computerCornerSize(hasRoundedTopCorners, elementBackgroundCornerSize)
val bottomCornerSize = computerCornerSize(hasRoundedBottomCorners, elementBackgroundCornerSize)
RoundedCornerShape(
topStart = topCornerSize,
topEnd = topCornerSize,
bottomEnd = bottomCornerSize,
bottomStart = bottomCornerSize,
)
}
Row(
verticalAlignment = Alignment.CenterVertically,
Expand Down Expand Up @@ -201,6 +214,11 @@ public fun <T> BasicLazyTree(
}
}

private fun computerCornerSize(
isRounded: Boolean,
cornerSize: CornerSize,
) = if (isRounded) cornerSize else CornerSize(0.dp)

private fun Modifier.elementBackground(
state: TreeElementState,
selectedFocused: Color,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public open class DefaultTreeViewOnKeyEvent(
?.let {
state.lastActiveItemIndex =
keys.indexOfFirst { selectableKey -> selectableKey.key == parentNodeKey }
state.selectedKeys = listOf(parentNodeKey)
state.selectedKeys = setOf(parentNodeKey)
}
}
}
Expand All @@ -59,7 +59,7 @@ public open class DefaultTreeViewOnKeyEvent(
if (keys[i].key in keyNodeList) {
if (keys[i] is SelectableLazyListKey.Selectable) {
state.lastActiveItemIndex = i
state.selectedKeys = listOf(keys[i].key)
state.selectedKeys = setOf(keys[i].key)
}
break
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public open class DefaultSelectableLazyColumnEventAction : PointerEventActions {
}

else -> {
selectableLazyListState.selectedKeys = listOf(key)
selectableLazyListState.selectedKeys = setOf(key)
selectableLazyListState.lastActiveItemIndex = allKeys.indexOfFirst { it.key == key }
}
}
Expand All @@ -94,12 +94,10 @@ public open class DefaultSelectableLazyColumnEventAction : PointerEventActions {
allKeys: List<SelectableLazyListKey>,
selectableLazyListState: SelectableLazyListState,
) {
if (selectableLazyListState.selectedKeys.contains(key)) {
selectableLazyListState.selectedKeys =
selectableLazyListState.selectedKeys.toMutableList().also { it.remove(key) }
selectableLazyListState.selectedKeys = if (selectableLazyListState.selectedKeys.contains(key)) {
selectableLazyListState.selectedKeys - key
} else {
selectableLazyListState.selectedKeys =
selectableLazyListState.selectedKeys.toMutableList().also { it.add(key) }
selectableLazyListState.selectedKeys + key
}
selectableLazyListState.lastActiveItemIndex = allKeys.indexOfFirst { it == key }
}
Expand All @@ -112,7 +110,7 @@ public open class DefaultSelectableLazyColumnEventAction : PointerEventActions {
) {
if (selectionMode == SelectionMode.None) return
if (selectionMode == SelectionMode.Single) {
state.selectedKeys = listOf(key)
state.selectedKeys = setOf(key)
} else {
val currentIndex = allKeys.indexOfFirst { it.key == key }.coerceAtLeast(0)
val lastFocussed = state.lastActiveItemIndex ?: currentIndex
Expand All @@ -133,7 +131,7 @@ public open class DefaultSelectableLazyColumnEventAction : PointerEventActions {
}
}
}
state.selectedKeys = state.selectedKeys.toMutableList().also { it.addAll(keys) }
state.selectedKeys += keys
state.lastActiveItemIndex = allKeys.indexOfFirst { it.key == key }
}
}
Expand Down Expand Up @@ -165,9 +163,8 @@ public class DefaultTreeViewPointerEventAction(
selectableLazyListState.lastKeyEventUsedMouse = false
super.toggleKeySelection(key, allKeys, selectableLazyListState)
}

else -> {
selectableLazyListState.selectedKeys = listOf(key)
selectableLazyListState.selectedKeys = setOf(key)
}
}
}
Expand Down

0 comments on commit a789ab1

Please sign in to comment.