From 6d0c4471f153ec917088af7fcd5677f540956409 Mon Sep 17 00:00:00 2001 From: "Ilya.Kazakevich" Date: Tue, 4 Nov 2025 02:21:50 +0100 Subject: [PATCH] [python] PY-79486: (WIP): Frontend clean-up, add open/close arrow GitOrigin-RevId: 9154ad49cc17e2a0f1a3a9afebf5872f845d0405 --- .../frontend/src/components/ModuleList.kt | 65 ++++++++++++------- .../frontend/src/components/OpenArrow.kt | 25 +++++++ 2 files changed, 67 insertions(+), 23 deletions(-) create mode 100644 python/python-sdk-configurator/frontend/src/components/OpenArrow.kt diff --git a/python/python-sdk-configurator/frontend/src/components/ModuleList.kt b/python/python-sdk-configurator/frontend/src/components/ModuleList.kt index 6b05c5628d83..3b896b3b555c 100644 --- a/python/python-sdk-configurator/frontend/src/components/ModuleList.kt +++ b/python/python-sdk-configurator/frontend/src/components/ModuleList.kt @@ -2,11 +2,11 @@ package com.intellij.python.sdkConfigurator.frontend.components import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* -import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember +import androidx.compose.runtime.* import androidx.compose.runtime.snapshots.SnapshotStateSet import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.intellij.python.sdkConfigurator.common.impl.ModuleDTO @@ -15,9 +15,13 @@ import com.intellij.python.sdkConfigurator.common.impl.ToolIdDTO import com.intellij.python.sdkConfigurator.frontend.PySdkConfiguratorFrontendBundle import kotlinx.collections.immutable.ImmutableMap import kotlinx.collections.immutable.PersistentList +import org.jetbrains.jewel.foundation.Stroke +import org.jetbrains.jewel.foundation.modifier.border +import org.jetbrains.jewel.foundation.theme.JewelTheme import org.jetbrains.jewel.ui.Orientation import org.jetbrains.jewel.ui.component.* import org.jetbrains.jewel.ui.icon.IconKey +import org.jetbrains.jewel.ui.theme.dividerStyle @Composable @@ -30,25 +34,40 @@ internal fun ModuleList( projectStructureLabel: String, environmentLabel: String, ) { - Box { - VerticallyScrollableContainer { - val colPadding = 2.dp - val horizontalArrangement = Arrangement.spacedBy(colPadding) - Column(Modifier.width(IntrinsicSize.Max).height(IntrinsicSize.Max).padding(end = scrollbarContentSafePadding())) { - Text(text = topLabel) - Divider(Orientation.Horizontal, thickness = 5.dp) - Row { - val modifier = Modifier.weight(1f) - Text(projectStructureLabel, modifier = modifier) - Divider(Orientation.Vertical) - Text(environmentLabel, modifier = modifier) - } - Divider(Orientation.Horizontal) - for (module in moduleItems) { - Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = horizontalArrangement) { - Module(module.name in checked, onCheck, colPadding, module, icons) - } // Module children - for (childModule in module.childModules) { + VerticallyScrollableContainer { + val colPadding = 2.dp + val horizontalArrangement = Arrangement.spacedBy(colPadding) + Column(Modifier.width(IntrinsicSize.Max) + .padding(end = scrollbarContentSafePadding()) + .border(Stroke.Alignment.Inside, JewelTheme.dividerStyle.metrics.thickness, JewelTheme.dividerStyle.color) + .padding(5.dp) + + ) { + Text(text = topLabel, maxLines = 1, softWrap = false, modifier = Modifier + .padding(bottom = 10.dp) + ) + Divider(Orientation.Horizontal, thickness = 5.dp) + Row { + val modifier = Modifier.weight(1f) + Text(projectStructureLabel, modifier = modifier) + Divider(Orientation.Vertical) + Text(environmentLabel, modifier = modifier) + } + Divider(Orientation.Horizontal) + val hide = Modifier.alpha(0f) + for (module in moduleItems) { + var subModuleOpened by remember { mutableStateOf(false) } + Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = horizontalArrangement) { + OpenArrow(subModuleOpened, { subModuleOpened = !subModuleOpened }, + modifier = if (module.childModules.isEmpty()) hide else Modifier) + Module(module.name in checked, onCheck, colPadding, module, icons) + } // Module children + + for (childModule in module.childModules) { + Row(Modifier.alpha(if (subModuleOpened) 1f else 0f)) { + // Invisible elements are for padding only: will replace to the real padding + OpenArrow(false, {}, hide) + Checkbox(false, onCheckedChange = {}, modifier = hide) CheckboxRow( childModule, childModule in checked, @@ -56,7 +75,6 @@ internal fun ModuleList( softWrap = false, maxLines = 1, enabled = false, - modifier = Modifier.padding(start = colPadding + 26.dp) // Checkbox width ) } } @@ -70,7 +88,7 @@ private fun RowScope.Module( checked: Boolean, onCheck: (ModuleName) -> Unit, columnPadding: Dp, - moduleInfo: ModuleDTO, // For parent only + moduleInfo: ModuleDTO, icons: ImmutableMap, ) { val colModifier = Modifier.weight(1f) @@ -97,3 +115,4 @@ private fun RowScope.Module( Text(text, Modifier.clickable(onClick = { onCheck(moduleName) }), maxLines = 1, softWrap = false) } } + diff --git a/python/python-sdk-configurator/frontend/src/components/OpenArrow.kt b/python/python-sdk-configurator/frontend/src/components/OpenArrow.kt new file mode 100644 index 000000000000..76d10fb3b80e --- /dev/null +++ b/python/python-sdk-configurator/frontend/src/components/OpenArrow.kt @@ -0,0 +1,25 @@ +package com.intellij.python.sdkConfigurator.frontend.components + +import androidx.compose.foundation.clickable +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.rotate +import org.jetbrains.jewel.foundation.theme.JewelTheme +import org.jetbrains.jewel.ui.component.Icon +import org.jetbrains.jewel.ui.theme.comboBoxStyle + +/** + * Arrow to open/close block + */ +@Composable +internal fun OpenArrow(opened: Boolean, onOpenChangeState: (Boolean) -> Unit, modifier: Modifier = Modifier) { + var opened by remember { mutableStateOf(opened) } + val rotate = if (opened) 360f else 270f + Icon(key = JewelTheme.comboBoxStyle.icons.chevronDown, + "", + Modifier.rotate(rotate).clickable(onClick = { + opened = !opened + onOpenChangeState(opened) + }).then(modifier) + ) +} \ No newline at end of file