From 06f2d5a2d093673e883e924266d4fb35f2c12ee5 Mon Sep 17 00:00:00 2001 From: Fabrizio Scarponi <36624359+fscarponi@users.noreply.github.com> Date: Tue, 5 Dec 2023 15:50:07 +0100 Subject: [PATCH] Migrate Dropdown API to DropdownLink, fixes various cosmetics issues like spacing and color (#4) Created PackageSearchDropdownLink with a specific Style, injected top level (cherry picked from commit 3adb17ede10a5fd141d4759fac4b35f50f4c42dd) --- .../plugin/PackageSearchToolWindowFactory.kt | 11 +- .../plugin/ui/bridge/Components.kt | 56 +-------- .../plugin/ui/bridge/CustomStyles.kt | 112 ++++++++++++++++++ .../packages/PackageSearchPackageList.kt | 10 +- .../panels/packages/PackageSearchSearchBar.kt | 78 ------------ .../ui/panels/side/PackageOverviewInfo.kt | 18 ++- 6 files changed, 136 insertions(+), 149 deletions(-) create mode 100644 plugin/src/main/kotlin/com/jetbrains/packagesearch/plugin/ui/bridge/CustomStyles.kt diff --git a/plugin/src/main/kotlin/com/jetbrains/packagesearch/plugin/PackageSearchToolWindowFactory.kt b/plugin/src/main/kotlin/com/jetbrains/packagesearch/plugin/PackageSearchToolWindowFactory.kt index d24467c2..3f5138e3 100644 --- a/plugin/src/main/kotlin/com/jetbrains/packagesearch/plugin/PackageSearchToolWindowFactory.kt +++ b/plugin/src/main/kotlin/com/jetbrains/packagesearch/plugin/PackageSearchToolWindowFactory.kt @@ -7,9 +7,11 @@ import com.intellij.openapi.wm.ToolWindow import com.intellij.openapi.wm.ToolWindowFactory import com.jetbrains.packagesearch.plugin.ui.LocalComponentManager import com.jetbrains.packagesearch.plugin.ui.PackageSearchToolwindow -import com.jetbrains.packagesearch.plugin.ui.panels.packages.PackageSearchTabStyle -import com.jetbrains.packagesearch.plugin.ui.panels.packages.PackageSearchTreeStyle -import com.jetbrains.packagesearch.plugin.ui.panels.packages.PackageSearchGlobalColors +import com.jetbrains.packagesearch.plugin.ui.bridge.LocalPackageSearchDropdownLinkStyle +import com.jetbrains.packagesearch.plugin.ui.bridge.PackageSearchDropdownLinkStyle +import com.jetbrains.packagesearch.plugin.ui.bridge.PackageSearchGlobalColors +import com.jetbrains.packagesearch.plugin.ui.bridge.PackageSearchTabStyle +import com.jetbrains.packagesearch.plugin.ui.bridge.PackageSearchTreeStyle import com.jetbrains.packagesearch.plugin.utils.installActions import org.jetbrains.jewel.bridge.addComposeTab import org.jetbrains.jewel.foundation.LocalGlobalColors @@ -24,7 +26,8 @@ class PackageSearchToolWindowFactory : ToolWindowFactory, DumbAware { LocalComponentManager provides project, LocalGlobalColors provides PackageSearchGlobalColors(), LocalDefaultTabStyle provides PackageSearchTabStyle(), - LocalLazyTreeStyle provides PackageSearchTreeStyle() + LocalLazyTreeStyle provides PackageSearchTreeStyle(), + LocalPackageSearchDropdownLinkStyle provides PackageSearchDropdownLinkStyle(), ) { PackageSearchToolwindow() } diff --git a/plugin/src/main/kotlin/com/jetbrains/packagesearch/plugin/ui/bridge/Components.kt b/plugin/src/main/kotlin/com/jetbrains/packagesearch/plugin/ui/bridge/Components.kt index 59d18cd4..d583a81e 100644 --- a/plugin/src/main/kotlin/com/jetbrains/packagesearch/plugin/ui/bridge/Components.kt +++ b/plugin/src/main/kotlin/com/jetbrains/packagesearch/plugin/ui/bridge/Components.kt @@ -6,7 +6,6 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.TextLayoutResult import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontFamily @@ -20,15 +19,12 @@ import com.intellij.icons.AllIcons import com.jetbrains.packagesearch.plugin.ui.PackageSearchMetrics import org.jetbrains.jewel.foundation.theme.JewelTheme import org.jetbrains.jewel.foundation.theme.LocalTextStyle -import org.jetbrains.jewel.ui.component.Dropdown +import org.jetbrains.jewel.ui.component.DropdownLink import org.jetbrains.jewel.ui.component.Icon import org.jetbrains.jewel.ui.component.IconButton import org.jetbrains.jewel.ui.component.MenuScope import org.jetbrains.jewel.ui.component.PopupMenu import org.jetbrains.jewel.ui.component.Text -import org.jetbrains.jewel.ui.component.styling.DropdownColors -import org.jetbrains.jewel.ui.component.styling.DropdownStyle -import org.jetbrains.jewel.ui.theme.dropdownStyle @Composable fun LabelInfo( @@ -71,7 +67,7 @@ fun LabelInfo( @Composable -fun TextSelectionDropdown( +fun PackageSearchDropdownLink( modifier: Modifier, menuModifier: Modifier, items: List, @@ -79,11 +75,11 @@ fun TextSelectionDropdown( enabled: Boolean, onSelection: (String) -> Unit, ) { - Dropdown( + DropdownLink( modifier = modifier, menuModifier = menuModifier.heightIn(max = PackageSearchMetrics.Dropdown.maxHeight), enabled = enabled && items.isNotEmpty(), - style = packageSearchDropdownStyle(), + style = LocalPackageSearchDropdownLinkStyle.current, menuContent = { items.forEach { selectableItem( @@ -94,18 +90,11 @@ fun TextSelectionDropdown( } } }, - content = { - Text( - modifier = Modifier.align(Alignment.CenterEnd), - text = content, - maxLines = 1, - overflow = TextOverflow.Clip, - textAlign = TextAlign.End - ) - } + text = content ) } + @Composable internal fun PackageActionPopup( isOpen: Boolean, @@ -141,36 +130,3 @@ internal fun PackageActionPopup( } } } - -@Composable -private fun packageSearchDropdownStyle(): DropdownStyle { - val currentStyle = JewelTheme.dropdownStyle - return DropdownStyle( - colors = DropdownColors( - background = Color.Transparent, - backgroundDisabled = Color.Transparent, - backgroundFocused = Color.Transparent, - backgroundPressed = Color.Transparent, - backgroundHovered = Color.Transparent, - content = currentStyle.colors.content, - contentDisabled = currentStyle.colors.contentDisabled, - contentFocused = currentStyle.colors.contentFocused, - contentPressed = currentStyle.colors.contentPressed, - contentHovered = currentStyle.colors.contentHovered, - border = Color.Transparent, - borderDisabled = Color.Transparent, - borderFocused = Color.Transparent, - borderPressed = Color.Transparent, - borderHovered = Color.Transparent, - iconTintDisabled = Color.Transparent, - iconTint = currentStyle.colors.iconTint, - iconTintFocused = currentStyle.colors.iconTintFocused, - iconTintPressed = currentStyle.colors.iconTintPressed, - iconTintHovered = currentStyle.colors.iconTintHovered, - ), - metrics = currentStyle.metrics, - icons = currentStyle.icons, - textStyle = currentStyle.textStyle, - menuStyle = currentStyle.menuStyle, - ) -} \ No newline at end of file diff --git a/plugin/src/main/kotlin/com/jetbrains/packagesearch/plugin/ui/bridge/CustomStyles.kt b/plugin/src/main/kotlin/com/jetbrains/packagesearch/plugin/ui/bridge/CustomStyles.kt new file mode 100644 index 00000000..755aa56f --- /dev/null +++ b/plugin/src/main/kotlin/com/jetbrains/packagesearch/plugin/ui/bridge/CustomStyles.kt @@ -0,0 +1,112 @@ +package com.jetbrains.packagesearch.plugin.ui.bridge + +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.calculateStartPadding +import androidx.compose.runtime.Composable +import androidx.compose.runtime.ProvidableCompositionLocal +import androidx.compose.runtime.remember +import androidx.compose.runtime.staticCompositionLocalOf +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalLayoutDirection +import androidx.compose.ui.unit.dp +import com.jetbrains.packagesearch.plugin.ui.PackageSearchMetrics +import org.jetbrains.jewel.foundation.GlobalColors +import org.jetbrains.jewel.foundation.LocalGlobalColors +import org.jetbrains.jewel.foundation.OutlineColors +import org.jetbrains.jewel.foundation.theme.JewelTheme +import org.jetbrains.jewel.foundation.theme.LocalContentColor +import org.jetbrains.jewel.ui.component.styling.LazyTreeMetrics +import org.jetbrains.jewel.ui.component.styling.LazyTreeStyle +import org.jetbrains.jewel.ui.component.styling.LinkColors +import org.jetbrains.jewel.ui.component.styling.LinkStyle +import org.jetbrains.jewel.ui.component.styling.LocalDefaultTabStyle +import org.jetbrains.jewel.ui.component.styling.LocalLazyTreeStyle +import org.jetbrains.jewel.ui.component.styling.TabMetrics +import org.jetbrains.jewel.ui.component.styling.TabStyle +import org.jetbrains.jewel.ui.theme.linkStyle + + +@Composable +internal fun PackageSearchDropdownLinkStyle(): LinkStyle { + val currentStyle = JewelTheme.linkStyle + val contentColor = LocalContentColor.current + return LinkStyle( + colors = LinkColors( + content = contentColor, + contentDisabled = currentStyle.colors.contentDisabled, + contentHovered = contentColor, + contentPressed = contentColor, + contentFocused = contentColor, + contentVisited = contentColor, + ), + metrics = currentStyle.metrics, + icons = currentStyle.icons, + textStyles = currentStyle.textStyles, + ) +} + + +@Composable +internal fun PackageSearchTabStyle(): TabStyle { + val current = LocalDefaultTabStyle.current + return TabStyle( + colors = current.colors, + metrics = TabMetrics( + underlineThickness = current.metrics.underlineThickness, + tabPadding = current.metrics.tabPadding, + tabHeight = PackageSearchMetrics.searchBarHeight, + closeContentGap = current.metrics.closeContentGap, + ), + icons = current.icons, + contentAlpha = current.contentAlpha + ) +} + +@Composable +fun PackageSearchGlobalColors(): GlobalColors { + val colors = LocalGlobalColors.current + + return remember(colors) { + GlobalColors( + borders = colors.borders, + outlines = OutlineColors( + focused = Color.Transparent, + focusedWarning = colors.outlines.focusedWarning, + focusedError = colors.outlines.focusedError, + warning = colors.outlines.warning, + error = colors.outlines.error, + ), + infoContent = colors.infoContent, + paneBackground = colors.paneBackground, + ) + } +} + +@Composable +internal fun PackageSearchTreeStyle(): LazyTreeStyle { + val currentStyle = LocalLazyTreeStyle.current + val paddings = currentStyle.metrics.elementPadding + return LazyTreeStyle( + currentStyle.colors, + metrics = LazyTreeMetrics( + indentSize = currentStyle.metrics.indentSize, + elementPadding = PaddingValues( + top = paddings.calculateTopPadding(), + bottom = paddings.calculateBottomPadding(), + start = paddings.calculateStartPadding(LocalLayoutDirection.current), + end = 0.dp + ), + elementContentPadding = currentStyle.metrics.elementContentPadding, + elementMinHeight = currentStyle.metrics.elementMinHeight, + chevronContentGap = currentStyle.metrics.chevronContentGap, + elementBackgroundCornerSize = currentStyle.metrics.elementBackgroundCornerSize, + ), + currentStyle.icons, + ) +} + + +internal val LocalPackageSearchDropdownLinkStyle: ProvidableCompositionLocal = + staticCompositionLocalOf { + error("No PackageSearchDropdownLinkStyle provided. Have you forgotten the theme?") + } diff --git a/plugin/src/main/kotlin/com/jetbrains/packagesearch/plugin/ui/panels/packages/PackageSearchPackageList.kt b/plugin/src/main/kotlin/com/jetbrains/packagesearch/plugin/ui/panels/packages/PackageSearchPackageList.kt index c1cd2916..2f15a369 100644 --- a/plugin/src/main/kotlin/com/jetbrains/packagesearch/plugin/ui/panels/packages/PackageSearchPackageList.kt +++ b/plugin/src/main/kotlin/com/jetbrains/packagesearch/plugin/ui/panels/packages/PackageSearchPackageList.kt @@ -36,7 +36,7 @@ import com.jetbrains.packagesearch.plugin.ui.LearnMoreLink import com.jetbrains.packagesearch.plugin.ui.PackageSearchMetrics import com.jetbrains.packagesearch.plugin.ui.bridge.LabelInfo import com.jetbrains.packagesearch.plugin.ui.bridge.PackageActionPopup -import com.jetbrains.packagesearch.plugin.ui.bridge.TextSelectionDropdown +import com.jetbrains.packagesearch.plugin.ui.bridge.PackageSearchDropdownLink import com.jetbrains.packagesearch.plugin.ui.model.packageslist.PackageListItem import com.jetbrains.packagesearch.plugin.ui.model.packageslist.PackageListItemEvent import com.jetbrains.packagesearch.plugin.ui.model.packageslist.PackageListItemEvent.EditPackageEvent.SetPackageScope @@ -173,7 +173,6 @@ private fun ScopeAndVersionDropdowns( Row() { Box(modifier = Modifier.widthIn(max = 180.dp)) { ScopeSelectionDropdown( - modifier = Modifier.align(Alignment.CenterEnd), declaredScope = item.selectedScope, allowMissingScope = item.allowMissingScope, availableScopes = item.availableScopes, @@ -182,9 +181,8 @@ private fun ScopeAndVersionDropdowns( ) } - Box(modifier = Modifier.width(180.dp)) { + Box(modifier = Modifier.width(180.dp), contentAlignment = Alignment.CenterEnd) { VersionSelectionDropdown( - modifier = Modifier.align(Alignment.CenterEnd), declaredVersion = item.declaredVersion, availableVersions = item.availableVersions, latestVersion = item.latestVersion, @@ -439,7 +437,7 @@ fun VersionSelectionDropdown( } } } - TextSelectionDropdown( + PackageSearchDropdownLink( modifier = modifier, menuModifier = menuModifier, items = availableVersions, @@ -459,7 +457,7 @@ fun ScopeSelectionDropdown( enabled: Boolean, onScopeChanged: (String?) -> Unit, ) { - TextSelectionDropdown( + PackageSearchDropdownLink( modifier = modifier, menuModifier = menuModifier, items = buildList { diff --git a/plugin/src/main/kotlin/com/jetbrains/packagesearch/plugin/ui/panels/packages/PackageSearchSearchBar.kt b/plugin/src/main/kotlin/com/jetbrains/packagesearch/plugin/ui/panels/packages/PackageSearchSearchBar.kt index 3379b748..81cad39e 100644 --- a/plugin/src/main/kotlin/com/jetbrains/packagesearch/plugin/ui/panels/packages/PackageSearchSearchBar.kt +++ b/plugin/src/main/kotlin/com/jetbrains/packagesearch/plugin/ui/panels/packages/PackageSearchSearchBar.kt @@ -1,36 +1,22 @@ package com.jetbrains.packagesearch.plugin.ui.panels.packages import androidx.compose.animation.Crossfade -import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.calculateStartPadding import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.unit.dp import com.intellij.icons.AllIcons import com.jetbrains.packagesearch.plugin.PackageSearchBundle.message import com.jetbrains.packagesearch.plugin.ui.PackageSearchMetrics -import org.jetbrains.jewel.foundation.GlobalColors -import org.jetbrains.jewel.foundation.LocalGlobalColors -import org.jetbrains.jewel.foundation.OutlineColors import org.jetbrains.jewel.ui.component.Icon import org.jetbrains.jewel.ui.component.IconButton import org.jetbrains.jewel.ui.component.Text import org.jetbrains.jewel.ui.component.TextField -import org.jetbrains.jewel.ui.component.styling.LazyTreeMetrics -import org.jetbrains.jewel.ui.component.styling.LazyTreeStyle -import org.jetbrains.jewel.ui.component.styling.LocalDefaultTabStyle -import org.jetbrains.jewel.ui.component.styling.LocalLazyTreeStyle import org.jetbrains.jewel.ui.component.styling.LocalTextFieldStyle -import org.jetbrains.jewel.ui.component.styling.TabMetrics -import org.jetbrains.jewel.ui.component.styling.TabStyle @Composable fun PackageSearchSearchBar( @@ -84,68 +70,4 @@ fun PackageSearchSearchBar( ) } - } - -@Composable -internal fun PackageSearchTabStyle(): TabStyle { - val current = LocalDefaultTabStyle.current - return TabStyle( - colors = current.colors, - metrics = TabMetrics( - underlineThickness = current.metrics.underlineThickness, - tabPadding = current.metrics.tabPadding, - tabHeight = PackageSearchMetrics.searchBarHeight, - closeContentGap = current.metrics.closeContentGap, - ), - icons = current.icons, - contentAlpha = current.contentAlpha - ) -} - - -@Composable -fun PackageSearchGlobalColors(): GlobalColors { - val colors = LocalGlobalColors.current - - return remember(colors) { - GlobalColors( - borders = colors.borders, - outlines = OutlineColors( - focused = Color.Transparent, - focusedWarning = colors.outlines.focusedWarning, - focusedError = colors.outlines.focusedError, - warning = colors.outlines.warning, - error = colors.outlines.error, - ), - infoContent = colors.infoContent, - paneBackground = colors.paneBackground, - ) - } -} - - -@Composable -internal fun PackageSearchTreeStyle(): LazyTreeStyle { - val currentStyle = LocalLazyTreeStyle.current - val paddings = currentStyle.metrics.elementPadding - return LazyTreeStyle( - currentStyle.colors, - metrics = LazyTreeMetrics( - indentSize = currentStyle.metrics.indentSize, - elementPadding = PaddingValues( - top = paddings.calculateTopPadding(), - bottom = paddings.calculateBottomPadding(), - start = paddings.calculateStartPadding(LocalLayoutDirection.current), - end = 0.dp - ), - elementContentPadding = currentStyle.metrics.elementContentPadding, - elementMinHeight = currentStyle.metrics.elementMinHeight, - chevronContentGap = currentStyle.metrics.chevronContentGap, - elementBackgroundCornerSize = currentStyle.metrics.elementBackgroundCornerSize, - ), - currentStyle.icons, - ) -} - - diff --git a/plugin/src/main/kotlin/com/jetbrains/packagesearch/plugin/ui/panels/side/PackageOverviewInfo.kt b/plugin/src/main/kotlin/com/jetbrains/packagesearch/plugin/ui/panels/side/PackageOverviewInfo.kt index f4cdc9d7..fcaff406 100644 --- a/plugin/src/main/kotlin/com/jetbrains/packagesearch/plugin/ui/panels/side/PackageOverviewInfo.kt +++ b/plugin/src/main/kotlin/com/jetbrains/packagesearch/plugin/ui/panels/side/PackageOverviewInfo.kt @@ -18,7 +18,6 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp -import com.jetbrains.packagesearch.plugin.PackageSearchBundle import com.jetbrains.packagesearch.plugin.PackageSearchBundle.message import com.jetbrains.packagesearch.plugin.core.data.IconProvider import com.jetbrains.packagesearch.plugin.ui.bridge.LabelInfo @@ -50,10 +49,7 @@ internal fun PackageOverviewTab( verticalArrangement = Arrangement.spacedBy(4.dp), modifier = Modifier.fillMaxSize().padding(start = 4.dp) ) { - Row( - horizontalArrangement = Arrangement.spacedBy(4.dp), - verticalAlignment = Alignment.Top - ) { + Row(verticalAlignment = Alignment.Top) { InfoPanelPackageTitle(modifier = Modifier.weight(1f), content.title, content.subtitle) InfoPanelPackageActions(content, onPackageEvent) } @@ -63,7 +59,7 @@ internal fun PackageOverviewTab( ) { if (content is InfoPanelContent.PackageInfo.Declared) { Row( - horizontalArrangement = Arrangement.spacedBy(4.dp), + horizontalArrangement = Arrangement.spacedBy(2.dp), verticalAlignment = Alignment.Top ) { LabelInfo( @@ -80,7 +76,7 @@ internal fun PackageOverviewTab( } } Row( - horizontalArrangement = Arrangement.spacedBy(4.dp), + horizontalArrangement = Arrangement.spacedBy(2.dp), verticalAlignment = Alignment.Top ) { LabelInfo( @@ -222,7 +218,7 @@ private fun InfoPanelPackageActions( @Composable private fun PackageType(name: String, icon: IconProvider.Icon) { - Row(horizontalArrangement = Arrangement.spacedBy(4.dp), verticalAlignment = Alignment.CenterVertically) { + Row(horizontalArrangement = Arrangement.spacedBy(2.dp), verticalAlignment = Alignment.CenterVertically) { LabelInfo( modifier = Modifier.defaultMinSize(90.dp), text = message("packagesearch.ui.toolwindow.packages.columns.type") @@ -244,7 +240,7 @@ private fun InfoPanelPackageDetailLine(name: String, value: String) { verticalAlignment = Alignment.Top, ) { LabelInfo( - modifier = Modifier.defaultMinSize(90.dp), + modifier = Modifier.defaultMinSize(90.dp,16.dp), text = name ) Text(value) @@ -283,7 +279,7 @@ private fun InfoPanelPackageTitle( horizontalArrangement = Arrangement.spacedBy(4.dp) ) { Column(verticalArrangement = Arrangement.spacedBy(4.dp)) { - org.jetbrains.jewel.ui.component.Text(name ?: id, fontWeight = FontWeight.Bold) + Text(name ?: id, fontWeight = FontWeight.Bold) if (name != null) LabelInfo(id) } } @@ -300,7 +296,7 @@ private fun InfoPanelPackageLinks( ) { LabelInfo( modifier = Modifier.defaultMinSize(90.dp), - text = PackageSearchBundle.message("packagesearch.ui.toolwindow.packages.details.info.licenses") + text = message("packagesearch.ui.toolwindow.packages.details.info.licenses") ) licenses.forEachIndexed { index, license -> when (license.url) {