diff --git a/components/SplitPane/demo/src/jvmMain/kotlin/org/jetbrains/compose/splitpane/demo/Main.kt b/components/SplitPane/demo/src/jvmMain/kotlin/org/jetbrains/compose/splitpane/demo/Main.kt index dd140484345..d1ab5d29216 100644 --- a/components/SplitPane/demo/src/jvmMain/kotlin/org/jetbrains/compose/splitpane/demo/Main.kt +++ b/components/SplitPane/demo/src/jvmMain/kotlin/org/jetbrains/compose/splitpane/demo/Main.kt @@ -23,7 +23,9 @@ import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.input.pointer.PointerIcon import androidx.compose.ui.input.pointer.pointerHoverIcon import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.WindowState import androidx.compose.ui.window.singleWindowApplication import org.jetbrains.compose.splitpane.ExperimentalSplitPaneApi import org.jetbrains.compose.splitpane.HorizontalSplitPane @@ -36,8 +38,12 @@ private fun Modifier.cursorForHorizontalResize(): Modifier = @OptIn(ExperimentalSplitPaneApi::class) fun main() = singleWindowApplication( + state = WindowState( + size = DpSize(800.dp, 700.dp) + ), title = "SplitPane demo" ) { + MaterialTheme { val splitterState = rememberSplitPaneState() val hSplitterState = rememberSplitPaneState() @@ -53,6 +59,13 @@ fun main() = singleWindowApplication( Text(if (hSplitterState.moveEnabled) "Freeze H" else "Unfreeze H") } + Button(onClick = { splitterState.firstVisible = !splitterState.firstVisible }) { + Text(if (splitterState.firstVisible) "Hide Left Pane" else "Show Left Pane") + } + Button(onClick = { hSplitterState.firstVisible = !hSplitterState.firstVisible }) { + Text(if (hSplitterState.firstVisible) "Hide Top Pane" else "Show Top Pane") + } + OutlinedTextField(value = delta, onValueChange = { delta = it }, label = { Text("Delta") }) Button(onClick = { delta.toFloatOrNull()?.let { splitterState.dispatchRawMovement(it) } }) { Text("Add delta V") diff --git a/components/SplitPane/library/src/commonMain/kotlin/org/jetbrains/compose/splitpane/SplitPaneDSL.kt b/components/SplitPane/library/src/commonMain/kotlin/org/jetbrains/compose/splitpane/SplitPaneDSL.kt index 4c533431524..57b68216957 100644 --- a/components/SplitPane/library/src/commonMain/kotlin/org/jetbrains/compose/splitpane/SplitPaneDSL.kt +++ b/components/SplitPane/library/src/commonMain/kotlin/org/jetbrains/compose/splitpane/SplitPaneDSL.kt @@ -20,7 +20,7 @@ interface SplitPaneScope { * Left part, for [VerticalSplitPane] it will be Top part * @param minSize a minimal size of composable item. * For [HorizontalSplitPane] it will be minimal width, for [VerticalSplitPane] it wil be minimal Heights. - * In this context minimal mean that this composable item could not be smaller than specified value. + * In this context, minimal means that this composable item could not be smaller than the specified value. * @param content composable item content. * */ fun first( @@ -33,7 +33,7 @@ interface SplitPaneScope { * For [HorizontalSplitPane] it will be Right part, for [VerticalSplitPane] it will be Bottom part * @param minSize a minimal size of composable item. * For [HorizontalSplitPane] it will be minimal width, for [VerticalSplitPane] it wil be minimal Heights. - * In this context minimal mean that this composable item could not be smaller than specified value. + * In this context, minimal means that this composable item could not be smaller than the specified value. * @param content composable item content. * */ fun second( @@ -48,7 +48,7 @@ interface SplitPaneScope { /** Receiver scope which is used by [SplitterScope] */ @ExperimentalSplitPaneApi interface HandleScope { - /** allow mark composable as movable handle */ + /** allow mark composable as a movable handle */ fun Modifier.markAsHandle(): Modifier } @@ -65,15 +65,15 @@ interface SplitterScope { /** * Set up handle part, this part of splitter would be measured and placed above [visiblePart] content. - * Size of handle will have no effect on split pane parts (first and second) sizes. + * The Size of the handle will have no effect on split pane parts (first and second) sizes. * - * @param alignment alignment of handle according to [visiblePart] could be: + * @param alignment alignment of the handle according to [visiblePart] could be: * * [SplitterHandleAlignment.BEFORE] if you place handle before [visiblePart], * * [SplitterHandleAlignment.ABOVE] if you place handle above [visiblePart] (will be centered) - * * and [SplitterHandleAlignment.AFTER] if you place handle after [visiblePart]. + * * and [SplitterHandleAlignment.AFTER] if you place the handle after [visiblePart]. * - * @param content composable item content provider. Uses [HandleScope] to allow mark any provided composable part - * as handle. + * @param content composable item content provider, Uses [HandleScope] to allow marking any provided composable part + * as a handle. * [content] will be placed only if [SplitPaneState.moveEnabled] is true */ fun handle( @@ -171,7 +171,7 @@ internal class SplitPaneScopeImpl( } /** - * creates a [SplitPaneState] and remembers it across composition + * Creates a [SplitPaneState] and remembers it across composition * * Changes to the provided initial values will **not** result in the state being recreated or * changed in any way if it has already been created. @@ -183,11 +183,13 @@ internal class SplitPaneScopeImpl( @Composable fun rememberSplitPaneState( initialPositionPercentage: Float = 0f, - moveEnabled: Boolean = true + moveEnabled: Boolean = true, + firstVisible: Boolean = true ): SplitPaneState { return remember { SplitPaneState( moveEnabled = moveEnabled, + firstVisible = firstVisible, initialPositionPercentage = initialPositionPercentage ) } diff --git a/components/SplitPane/library/src/commonMain/kotlin/org/jetbrains/compose/splitpane/SplitPaneState.kt b/components/SplitPane/library/src/commonMain/kotlin/org/jetbrains/compose/splitpane/SplitPaneState.kt index 0ea874f7086..8e52f24ed07 100644 --- a/components/SplitPane/library/src/commonMain/kotlin/org/jetbrains/compose/splitpane/SplitPaneState.kt +++ b/components/SplitPane/library/src/commonMain/kotlin/org/jetbrains/compose/splitpane/SplitPaneState.kt @@ -8,10 +8,13 @@ import androidx.compose.runtime.setValue class SplitPaneState( initialPositionPercentage: Float, moveEnabled: Boolean, + firstVisible: Boolean = true ) { var moveEnabled by mutableStateOf(moveEnabled) + var firstVisible by mutableStateOf(firstVisible) + private var _positionPercentage by mutableStateOf(initialPositionPercentage) var positionPercentage: Float get() = _positionPercentage diff --git a/components/SplitPane/library/src/desktopMain/kotlin/org/jetbrains/compose/splitpane/DesktopSplitPane.kt b/components/SplitPane/library/src/desktopMain/kotlin/org/jetbrains/compose/splitpane/DesktopSplitPane.kt index a8c1f00d22a..ca45ffabf58 100644 --- a/components/SplitPane/library/src/desktopMain/kotlin/org/jetbrains/compose/splitpane/DesktopSplitPane.kt +++ b/components/SplitPane/library/src/desktopMain/kotlin/org/jetbrains/compose/splitpane/DesktopSplitPane.kt @@ -14,8 +14,8 @@ private fun Constraints.withUnconstrainedWidth() = copy(minWidth = 0, maxWidth = private fun Constraints.withUnconstrainedHeight() = copy(minHeight = 0, maxHeight = Constraints.Infinity) -@OptIn(ExperimentalSplitPaneApi::class) @Composable +@OptIn(ExperimentalSplitPaneApi::class) internal actual fun SplitPane( modifier: Modifier, isHorizontal: Boolean, @@ -30,7 +30,7 @@ internal actual fun SplitPane( second?.let { Box(modifier) { it() } } return } - + Layout( { Box { @@ -77,8 +77,10 @@ internal actual fun SplitPane( minPosition = constrainedMin maxPosition = constrainedMax - val position = (constrainedMin * (1-positionPercentage) + constrainedMax * positionPercentage) - .roundToInt() + val position = + if (firstVisible) { + (constrainedMin * (1 - positionPercentage) + constrainedMax * positionPercentage).roundToInt() + } else 0 val firstPlaceable = firstMeasurable.measure( if (isHorizontal) { @@ -94,7 +96,7 @@ internal actual fun SplitPane( } ) - val secondPlaceablePosition = position + splitterSize + val secondPlaceablePosition = if (firstVisible) position + splitterSize else 0 val secondAvailableSize = (maxConstraintOnMainAxis - secondPlaceablePosition).coerceAtLeast(0) val secondPlaceable = secondMeasurable.measure( @@ -113,7 +115,7 @@ internal actual fun SplitPane( val handlePlaceable = handleMeasurable.measure(splitterConstraints) val handleSize = handlePlaceable.valueByDirection(isHorizontal) - // TODO support RTL + val handlePosition = when (splitter.alignment) { SplitterHandleAlignment.BEFORE -> position + splitterSize - handleSize SplitterHandleAlignment.ABOVE -> position + (splitterSize - handleSize) / 2 diff --git a/components/SplitPane/library/src/desktopMain/kotlin/org/jetbrains/compose/splitpane/DesktopSplitter.kt b/components/SplitPane/library/src/desktopMain/kotlin/org/jetbrains/compose/splitpane/DesktopSplitter.kt index 92ad6749e87..aedc32811ff 100644 --- a/components/SplitPane/library/src/desktopMain/kotlin/org/jetbrains/compose/splitpane/DesktopSplitter.kt +++ b/components/SplitPane/library/src/desktopMain/kotlin/org/jetbrains/compose/splitpane/DesktopSplitter.kt @@ -3,7 +3,6 @@ package org.jetbrains.compose.splitpane import androidx.compose.foundation.gestures.detectDragGestures import androidx.compose.foundation.layout.* import androidx.compose.runtime.Composable -import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier import androidx.compose.ui.input.pointer.* import androidx.compose.ui.platform.LocalLayoutDirection @@ -11,7 +10,6 @@ import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.dp import java.awt.Cursor -@OptIn(ExperimentalComposeUiApi::class) private fun Modifier.cursorForHorizontalResize(isHorizontal: Boolean): Modifier = pointerHoverIcon(PointerIcon(Cursor(if (isHorizontal) Cursor.E_RESIZE_CURSOR else Cursor.S_RESIZE_CURSOR)))