From b9e1c19a598034f33f7a7ec4d603acc8d633ed28 Mon Sep 17 00:00:00 2001 From: davide magli Date: Fri, 6 Oct 2023 16:52:21 +0200 Subject: [PATCH 01/12] wip (cherry picked from commit b51807c216d7c4d7a11797436cdd4bdc8bacabff) --- .../main/kotlin/org/jetbrains/jewel/Button.kt | 28 +++++++++++++++++++ .../jewel/samples/standalone/Main.kt | 2 +- .../samples/standalone/components/Buttons.kt | 16 ++++++++++- 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/core/src/main/kotlin/org/jetbrains/jewel/Button.kt b/core/src/main/kotlin/org/jetbrains/jewel/Button.kt index 7521dda449..67b881817f 100644 --- a/core/src/main/kotlin/org/jetbrains/jewel/Button.kt +++ b/core/src/main/kotlin/org/jetbrains/jewel/Button.kt @@ -34,6 +34,8 @@ import org.jetbrains.jewel.CommonStateBitMask.Hovered import org.jetbrains.jewel.CommonStateBitMask.Pressed import org.jetbrains.jewel.foundation.Stroke import org.jetbrains.jewel.foundation.border +import org.jetbrains.jewel.styling.ButtonColors +import org.jetbrains.jewel.styling.ButtonMetrics import org.jetbrains.jewel.styling.ButtonStyle @Composable @@ -78,6 +80,32 @@ fun OutlinedButton( ) } +@Composable +fun IconButton( + onClick: () -> Unit, + modifier: Modifier = Modifier, + enabled: Boolean = true, + interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, + style: ButtonStyle = object : ButtonStyle { + override val colors: ButtonColors = object : ButtonColors by IntelliJTheme.outlinedButtonStyle.colors { + } + override val metrics: ButtonMetrics = object : ButtonMetrics by IntelliJTheme.outlinedButtonStyle.metrics { + } + }, + textStyle: TextStyle = IntelliJTheme.textStyle, + content: @Composable RowScope.() -> Unit, +) { + ButtonImpl( + onClick = onClick, + modifier = modifier, + enabled = enabled, + interactionSource = interactionSource, + style = style, + content = content, + textStyle = textStyle, + ) +} + @Composable private fun ButtonImpl( onClick: () -> Unit, diff --git a/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/Main.kt b/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/Main.kt index b9785e2da1..1ed2fd48bf 100644 --- a/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/Main.kt +++ b/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/Main.kt @@ -100,7 +100,7 @@ private fun ComponentShowcase(svgLoader: JewelSvgLoader, resourceLoader: Resourc horizontalAlignment = Alignment.Start, ) { Borders() - Buttons() + Buttons(svgLoader, resourceLoader) Dropdowns() Checkboxes() RadioButtons() diff --git a/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/components/Buttons.kt b/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/components/Buttons.kt index 3096ed8849..d7d46092bd 100644 --- a/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/components/Buttons.kt +++ b/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/components/Buttons.kt @@ -3,17 +3,25 @@ package org.jetbrains.jewel.samples.standalone.components import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.size import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.res.ResourceLoader import androidx.compose.ui.unit.dp import org.jetbrains.jewel.DefaultButton import org.jetbrains.jewel.GroupHeader +import org.jetbrains.jewel.Icon +import org.jetbrains.jewel.IconButton +import org.jetbrains.jewel.JewelSvgLoader import org.jetbrains.jewel.OutlinedButton import org.jetbrains.jewel.Text +import org.jetbrains.jewel.styling.ResourcePainterProvider @Composable -fun Buttons() { +fun Buttons(svgLoader: JewelSvgLoader, resourceLoader: ResourceLoader) { GroupHeader("Buttons") Row( modifier = Modifier.fillMaxWidth(), @@ -35,5 +43,11 @@ fun Buttons() { DefaultButton(onClick = {}, enabled = false) { Text("Default disabled") } + + IconButton(onClick = {}) { + val jewelLogoProvider = remember { ResourcePainterProvider.stateless("icons/jewel-logo.svg", svgLoader) } + val jewelLogo by jewelLogoProvider.getPainter(resourceLoader) + Icon(painter = jewelLogo, "icon", modifier = Modifier.size(50.dp)) + } } } From d696b33d1c7eefa4a8d2e668c46b598b058e55d6 Mon Sep 17 00:00:00 2001 From: davide magli Date: Tue, 10 Oct 2023 12:47:44 +0200 Subject: [PATCH 02/12] draft (cherry picked from commit ecbaa1ac7c4b33ffb8d01cbdf6c0559ffc6352d0) --- .../main/kotlin/org/jetbrains/jewel/Button.kt | 62 ++++++++++++++----- .../jewel/IntelliJComponentStyling.kt | 4 ++ .../org/jetbrains/jewel/IntelliJTheme.kt | 6 ++ .../jewel/styling/IconButtonMetrics.kt | 17 +++++ gradle/libs.versions.toml | 2 +- .../org/jetbrains/jewel/bridge/IntUiBridge.kt | 2 + .../jewel/intui/core/BaseIntUiTheme.kt | 2 + .../jewel/intui/standalone/IntUiTheme.kt | 6 ++ .../styling/IntUiIconButtonMetrics.kt | 15 +++++ .../samples/standalone/components/Buttons.kt | 19 ++++-- 10 files changed, 113 insertions(+), 22 deletions(-) create mode 100644 core/src/main/kotlin/org/jetbrains/jewel/styling/IconButtonMetrics.kt create mode 100644 int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiIconButtonMetrics.kt diff --git a/core/src/main/kotlin/org/jetbrains/jewel/Button.kt b/core/src/main/kotlin/org/jetbrains/jewel/Button.kt index 67b881817f..a44f804c21 100644 --- a/core/src/main/kotlin/org/jetbrains/jewel/Button.kt +++ b/core/src/main/kotlin/org/jetbrains/jewel/Button.kt @@ -8,6 +8,7 @@ import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.interaction.PressInteraction import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.defaultMinSize @@ -24,6 +25,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.takeOrElse import androidx.compose.ui.semantics.Role import androidx.compose.ui.text.TextStyle @@ -34,9 +36,8 @@ import org.jetbrains.jewel.CommonStateBitMask.Hovered import org.jetbrains.jewel.CommonStateBitMask.Pressed import org.jetbrains.jewel.foundation.Stroke import org.jetbrains.jewel.foundation.border -import org.jetbrains.jewel.styling.ButtonColors -import org.jetbrains.jewel.styling.ButtonMetrics import org.jetbrains.jewel.styling.ButtonStyle +import org.jetbrains.jewel.styling.IconButtonMetrics @Composable fun DefaultButton( @@ -85,24 +86,51 @@ fun IconButton( onClick: () -> Unit, modifier: Modifier = Modifier, enabled: Boolean = true, + metrics: IconButtonMetrics = IntelliJTheme.iconButtonMetrics, interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, - style: ButtonStyle = object : ButtonStyle { - override val colors: ButtonColors = object : ButtonColors by IntelliJTheme.outlinedButtonStyle.colors { + content: @Composable (BoxScope.(ButtonState) -> Unit), +) { + var buttonState by remember(interactionSource) { + mutableStateOf(ButtonState.of(enabled = enabled)) + } + + remember(enabled) { + buttonState = buttonState.copy(enabled = enabled) + } + + LaunchedEffect(interactionSource) { + interactionSource.interactions.collect { interaction -> + when (interaction) { + is PressInteraction.Press -> buttonState = buttonState.copy(pressed = true) + is PressInteraction.Cancel, is PressInteraction.Release -> + buttonState = + buttonState.copy(pressed = false) + + is HoverInteraction.Enter -> buttonState = buttonState.copy(hovered = true) + is HoverInteraction.Exit -> buttonState = buttonState.copy(hovered = false) + is FocusInteraction.Focus -> buttonState = buttonState.copy(focused = true) + is FocusInteraction.Unfocus -> buttonState = buttonState.copy(focused = false) + } } - override val metrics: ButtonMetrics = object : ButtonMetrics by IntelliJTheme.outlinedButtonStyle.metrics { + } + val shape = RoundedCornerShape(metrics.cornerSize) + Box( + modifier = modifier + .defaultMinSize(metrics.minSize.width, metrics.minSize.height) + .clickable( + onClick = onClick, + enabled = enabled, + role = Role.Button, + interactionSource = interactionSource, + indication = NoIndication, + ) + .clip(shape) + .padding(metrics.padding), + propagateMinConstraints = true, + contentAlignment = Alignment.Center, + content = { + content(buttonState) } - }, - textStyle: TextStyle = IntelliJTheme.textStyle, - content: @Composable RowScope.() -> Unit, -) { - ButtonImpl( - onClick = onClick, - modifier = modifier, - enabled = enabled, - interactionSource = interactionSource, - style = style, - content = content, - textStyle = textStyle, ) } diff --git a/core/src/main/kotlin/org/jetbrains/jewel/IntelliJComponentStyling.kt b/core/src/main/kotlin/org/jetbrains/jewel/IntelliJComponentStyling.kt index 95edef502d..6c34fed642 100644 --- a/core/src/main/kotlin/org/jetbrains/jewel/IntelliJComponentStyling.kt +++ b/core/src/main/kotlin/org/jetbrains/jewel/IntelliJComponentStyling.kt @@ -9,6 +9,7 @@ import org.jetbrains.jewel.styling.DividerStyle import org.jetbrains.jewel.styling.DropdownStyle import org.jetbrains.jewel.styling.GroupHeaderStyle import org.jetbrains.jewel.styling.HorizontalProgressBarStyle +import org.jetbrains.jewel.styling.IconButtonMetrics import org.jetbrains.jewel.styling.LabelledTextFieldStyle import org.jetbrains.jewel.styling.LazyTreeStyle import org.jetbrains.jewel.styling.LinkStyle @@ -42,6 +43,7 @@ class IntelliJComponentStyling( val textFieldStyle: TextFieldStyle, val circularProgressStyle: CircularProgressStyle, val tooltipStyle: TooltipStyle, + val iconButtonMetrics: IconButtonMetrics, ) { override fun equals(other: Any?): Boolean { @@ -70,6 +72,7 @@ class IntelliJComponentStyling( if (textFieldStyle != other.textFieldStyle) return false if (circularProgressStyle != other.circularProgressStyle) return false if (tooltipStyle != other.tooltipStyle) return false + if (iconButtonMetrics != other.iconButtonMetrics) return false return true } @@ -95,6 +98,7 @@ class IntelliJComponentStyling( result = 31 * result + textFieldStyle.hashCode() result = 31 * result + circularProgressStyle.hashCode() result = 31 * result + tooltipStyle.hashCode() + result = 31 * result + iconButtonMetrics.hashCode() return result } diff --git a/core/src/main/kotlin/org/jetbrains/jewel/IntelliJTheme.kt b/core/src/main/kotlin/org/jetbrains/jewel/IntelliJTheme.kt index 0b7bf49d26..0bd5231817 100644 --- a/core/src/main/kotlin/org/jetbrains/jewel/IntelliJTheme.kt +++ b/core/src/main/kotlin/org/jetbrains/jewel/IntelliJTheme.kt @@ -14,6 +14,7 @@ import org.jetbrains.jewel.styling.DividerStyle import org.jetbrains.jewel.styling.DropdownStyle import org.jetbrains.jewel.styling.GroupHeaderStyle import org.jetbrains.jewel.styling.HorizontalProgressBarStyle +import org.jetbrains.jewel.styling.IconButtonMetrics import org.jetbrains.jewel.styling.LabelledTextFieldStyle import org.jetbrains.jewel.styling.LazyTreeStyle import org.jetbrains.jewel.styling.LinkStyle @@ -27,6 +28,7 @@ import org.jetbrains.jewel.styling.LocalDropdownStyle import org.jetbrains.jewel.styling.LocalEditorTabStyle import org.jetbrains.jewel.styling.LocalGroupHeaderStyle import org.jetbrains.jewel.styling.LocalHorizontalProgressBarStyle +import org.jetbrains.jewel.styling.LocalIconButtonMetrics import org.jetbrains.jewel.styling.LocalLabelledTextFieldStyle import org.jetbrains.jewel.styling.LocalLazyTreeStyle import org.jetbrains.jewel.styling.LocalLinkStyle @@ -196,6 +198,10 @@ interface IntelliJTheme { @Composable @ReadOnlyComposable get() = LocalTooltipStyle.current + val iconButtonMetrics: IconButtonMetrics + @Composable + @ReadOnlyComposable + get() = LocalIconButtonMetrics.current } } diff --git a/core/src/main/kotlin/org/jetbrains/jewel/styling/IconButtonMetrics.kt b/core/src/main/kotlin/org/jetbrains/jewel/styling/IconButtonMetrics.kt new file mode 100644 index 0000000000..3f6419f469 --- /dev/null +++ b/core/src/main/kotlin/org/jetbrains/jewel/styling/IconButtonMetrics.kt @@ -0,0 +1,17 @@ +package org.jetbrains.jewel.styling + +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.shape.CornerSize +import androidx.compose.runtime.staticCompositionLocalOf +import androidx.compose.ui.unit.DpSize + +interface IconButtonMetrics { + + val cornerSize: CornerSize + val padding: PaddingValues + val minSize: DpSize +} + +val LocalIconButtonMetrics = staticCompositionLocalOf { + error("No outlined ButtonStyle provided") +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 370a2df4d3..0750416a19 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -composeDesktop = "1.5.2" +composeDesktop = "1.5.10-beta01" coroutines = "1.7.3" detekt = "1.23.1" idea232 = "232.8660.185" diff --git a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/IntUiBridge.kt b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/IntUiBridge.kt index 8321102a52..0576b2b32e 100644 --- a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/IntUiBridge.kt +++ b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/IntUiBridge.kt @@ -50,6 +50,7 @@ import org.jetbrains.jewel.intui.standalone.styling.IntUiGroupHeaderStyle import org.jetbrains.jewel.intui.standalone.styling.IntUiHorizontalProgressBarColors import org.jetbrains.jewel.intui.standalone.styling.IntUiHorizontalProgressBarMetrics import org.jetbrains.jewel.intui.standalone.styling.IntUiHorizontalProgressBarStyle +import org.jetbrains.jewel.intui.standalone.styling.IntUiIconButtonMetrics import org.jetbrains.jewel.intui.standalone.styling.IntUiLabelledTextFieldColors import org.jetbrains.jewel.intui.standalone.styling.IntUiLabelledTextFieldMetrics import org.jetbrains.jewel.intui.standalone.styling.IntUiLabelledTextFieldStyle @@ -172,6 +173,7 @@ internal fun createSwingIntUiComponentStyling( circularProgressStyle = readCircularProgressStyle(theme.isDark), tooltipStyle = readTooltipStyle(), textFieldStyle = textFieldStyle, + iconButtonMetrics = IntUiIconButtonMetrics() ) } diff --git a/int-ui/int-ui-core/src/main/kotlin/org/jetbrains/jewel/intui/core/BaseIntUiTheme.kt b/int-ui/int-ui-core/src/main/kotlin/org/jetbrains/jewel/intui/core/BaseIntUiTheme.kt index 814dfbb2aa..3d10993fc0 100644 --- a/int-ui/int-ui-core/src/main/kotlin/org/jetbrains/jewel/intui/core/BaseIntUiTheme.kt +++ b/int-ui/int-ui-core/src/main/kotlin/org/jetbrains/jewel/intui/core/BaseIntUiTheme.kt @@ -37,6 +37,7 @@ import org.jetbrains.jewel.styling.LocalDropdownStyle import org.jetbrains.jewel.styling.LocalEditorTabStyle import org.jetbrains.jewel.styling.LocalGroupHeaderStyle import org.jetbrains.jewel.styling.LocalHorizontalProgressBarStyle +import org.jetbrains.jewel.styling.LocalIconButtonMetrics import org.jetbrains.jewel.styling.LocalLabelledTextFieldStyle import org.jetbrains.jewel.styling.LocalLazyTreeStyle import org.jetbrains.jewel.styling.LocalLinkStyle @@ -233,6 +234,7 @@ fun BaseIntUiTheme( LocalIndication provides NoIndication, LocalCircularProgressStyle provides componentStyling.circularProgressStyle, LocalTooltipStyle provides componentStyling.tooltipStyle, + LocalIconButtonMetrics provides componentStyling.iconButtonMetrics, ) { IntelliJTheme(theme, swingCompatMode, content) } diff --git a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/IntUiTheme.kt b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/IntUiTheme.kt index 1f1795a284..86514c6272 100644 --- a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/IntUiTheme.kt +++ b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/IntUiTheme.kt @@ -40,6 +40,7 @@ import org.jetbrains.jewel.intui.standalone.styling.IntUiDividerStyle import org.jetbrains.jewel.intui.standalone.styling.IntUiDropdownStyle import org.jetbrains.jewel.intui.standalone.styling.IntUiGroupHeaderStyle import org.jetbrains.jewel.intui.standalone.styling.IntUiHorizontalProgressBarStyle +import org.jetbrains.jewel.intui.standalone.styling.IntUiIconButtonMetrics import org.jetbrains.jewel.intui.standalone.styling.IntUiLabelledTextFieldStyle import org.jetbrains.jewel.intui.standalone.styling.IntUiLazyTreeStyle import org.jetbrains.jewel.intui.standalone.styling.IntUiLinkStyle @@ -58,6 +59,7 @@ import org.jetbrains.jewel.styling.DividerStyle import org.jetbrains.jewel.styling.DropdownStyle import org.jetbrains.jewel.styling.GroupHeaderStyle import org.jetbrains.jewel.styling.HorizontalProgressBarStyle +import org.jetbrains.jewel.styling.IconButtonMetrics import org.jetbrains.jewel.styling.LabelledTextFieldStyle import org.jetbrains.jewel.styling.LazyTreeStyle import org.jetbrains.jewel.styling.LinkStyle @@ -136,6 +138,7 @@ object IntUiTheme : BaseIntUiTheme { editorTabStyle: TabStyle = IntUiTabStyle.Editor.dark(svgLoader), circularProgressStyle: CircularProgressStyle = IntUiCircularProgressStyle.dark(), tooltipStyle: IntUiTooltipStyle = IntUiTooltipStyle.dark(), + iconButtonMetrics: IconButtonMetrics = IntUiIconButtonMetrics(), ) = IntelliJComponentStyling( checkboxStyle = checkboxStyle, @@ -158,6 +161,7 @@ object IntUiTheme : BaseIntUiTheme { textFieldStyle = textFieldStyle, circularProgressStyle = circularProgressStyle, tooltipStyle = tooltipStyle, + iconButtonMetrics ) @Composable @@ -183,6 +187,7 @@ object IntUiTheme : BaseIntUiTheme { editorTabStyle: TabStyle = IntUiTabStyle.Editor.light(svgLoader), circularProgressStyle: CircularProgressStyle = IntUiCircularProgressStyle.light(), tooltipStyle: IntUiTooltipStyle = IntUiTooltipStyle.light(), + iconButtonMetrics: IconButtonMetrics = IntUiIconButtonMetrics(), ) = IntelliJComponentStyling( checkboxStyle = checkboxStyle, chipStyle = chipStyle, @@ -204,6 +209,7 @@ object IntUiTheme : BaseIntUiTheme { textFieldStyle = textFieldStyle, circularProgressStyle = circularProgressStyle, tooltipStyle = tooltipStyle, + iconButtonMetrics = iconButtonMetrics ) } diff --git a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiIconButtonMetrics.kt b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiIconButtonMetrics.kt new file mode 100644 index 0000000000..9bd43f0ca2 --- /dev/null +++ b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiIconButtonMetrics.kt @@ -0,0 +1,15 @@ +package org.jetbrains.jewel.intui.standalone.styling + +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.shape.CornerSize +import androidx.compose.runtime.Stable +import androidx.compose.ui.unit.DpSize +import androidx.compose.ui.unit.dp +import org.jetbrains.jewel.styling.IconButtonMetrics + +@Stable +data class IntUiIconButtonMetrics( + override val cornerSize: CornerSize = CornerSize(4.dp), + override val padding: PaddingValues = PaddingValues(horizontal = 0.dp, vertical = 0.dp), + override val minSize: DpSize = DpSize(16.dp, 16.dp), +) : IconButtonMetrics diff --git a/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/components/Buttons.kt b/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/components/Buttons.kt index d7d46092bd..ac61f69780 100644 --- a/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/components/Buttons.kt +++ b/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/components/Buttons.kt @@ -1,5 +1,6 @@ package org.jetbrains.jewel.samples.standalone.components +import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth @@ -9,16 +10,19 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.res.ResourceLoader import androidx.compose.ui.unit.dp import org.jetbrains.jewel.DefaultButton import org.jetbrains.jewel.GroupHeader import org.jetbrains.jewel.Icon import org.jetbrains.jewel.IconButton +import org.jetbrains.jewel.IntelliJTheme import org.jetbrains.jewel.JewelSvgLoader import org.jetbrains.jewel.OutlinedButton import org.jetbrains.jewel.Text import org.jetbrains.jewel.styling.ResourcePainterProvider +import org.jetbrains.jewel.util.appendIf @Composable fun Buttons(svgLoader: JewelSvgLoader, resourceLoader: ResourceLoader) { @@ -44,10 +48,17 @@ fun Buttons(svgLoader: JewelSvgLoader, resourceLoader: ResourceLoader) { Text("Default disabled") } - IconButton(onClick = {}) { - val jewelLogoProvider = remember { ResourcePainterProvider.stateless("icons/jewel-logo.svg", svgLoader) } - val jewelLogo by jewelLogoProvider.getPainter(resourceLoader) - Icon(painter = jewelLogo, "icon", modifier = Modifier.size(50.dp)) + IconButton(onClick = {}, modifier = Modifier.size(30.dp)) { + val iconProvider = remember { ResourcePainterProvider.stateless("icons/close.svg", svgLoader) } + val iconPainter by iconProvider.getPainter(resourceLoader) + Icon( + painter = iconPainter, + "icon", + modifier = Modifier.appendIf(it.isPressed || it.isHovered) { + background(SolidColor(IntelliJTheme.contentColor.copy(alpha = 0.1f))) + } + + ) } } } From 04d2d3c04f35452ac08d9806a7497c4a8c5a4d24 Mon Sep 17 00:00:00 2001 From: davide magli Date: Tue, 10 Oct 2023 12:52:32 +0200 Subject: [PATCH 03/12] lint (cherry picked from commit da55acd356066032e57544eedd544d9877266ca0) --- core/src/main/kotlin/org/jetbrains/jewel/Button.kt | 2 +- .../src/main/kotlin/org/jetbrains/jewel/bridge/IntUiBridge.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/kotlin/org/jetbrains/jewel/Button.kt b/core/src/main/kotlin/org/jetbrains/jewel/Button.kt index a44f804c21..8d0f6691fd 100644 --- a/core/src/main/kotlin/org/jetbrains/jewel/Button.kt +++ b/core/src/main/kotlin/org/jetbrains/jewel/Button.kt @@ -130,7 +130,7 @@ fun IconButton( contentAlignment = Alignment.Center, content = { content(buttonState) - } + }, ) } diff --git a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/IntUiBridge.kt b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/IntUiBridge.kt index 0576b2b32e..33634e3019 100644 --- a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/IntUiBridge.kt +++ b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/IntUiBridge.kt @@ -173,7 +173,7 @@ internal fun createSwingIntUiComponentStyling( circularProgressStyle = readCircularProgressStyle(theme.isDark), tooltipStyle = readTooltipStyle(), textFieldStyle = textFieldStyle, - iconButtonMetrics = IntUiIconButtonMetrics() + iconButtonMetrics = IntUiIconButtonMetrics(), ) } From 4698825eb478d1eb1a4dbb271bcb9e20de0c9c95 Mon Sep 17 00:00:00 2001 From: fscarponi Date: Tue, 10 Oct 2023 18:11:29 +0200 Subject: [PATCH 04/12] Replace IconButtonMetrics with IconButtonStyle for effective theming The existing metric defining approach, IconButtonMetrics, was restricting the theming of the IconButton component effectively. Thus, the 'IconButtonMetrics' was replaced by 'IconButtonStyle' and the necessary changes for the field change were implemented. This would assist in providing the same theme across different platforms. The 'IconButton' has been made theme-aware by allowing access to theme and style via properties. Changes were made in implementations concerning IntelliJTheme, BaseIntUiTheme, and ComponentShowcaseTab. File names were also appropriately renamed. --- .../main/kotlin/org/jetbrains/jewel/Button.kt | 56 ------------- .../kotlin/org/jetbrains/jewel/IconButton.kt | 79 ++++++++++++++++++ .../jewel/IntelliJComponentStyling.kt | 10 +-- .../org/jetbrains/jewel/IntelliJTheme.kt | 8 +- .../jewel/styling/IconButtonMetrics.kt | 39 ++++++++- .../org/jetbrains/jewel/bridge/IntUiBridge.kt | 21 ++++- .../jewel/intui/core/BaseIntUiTheme.kt | 4 +- .../jewel/intui/standalone/IntUiTheme.kt | 12 +-- .../styling/IntUiIconButtonMetrics.kt | 15 ---- .../styling/IntUiIconButtonStyling.kt | 82 +++++++++++++++++++ .../samples/ideplugin/ComponentShowcaseTab.kt | 11 ++- .../samples/standalone/components/Buttons.kt | 8 -- 12 files changed, 242 insertions(+), 103 deletions(-) create mode 100644 core/src/main/kotlin/org/jetbrains/jewel/IconButton.kt delete mode 100644 int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiIconButtonMetrics.kt create mode 100644 int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiIconButtonStyling.kt diff --git a/core/src/main/kotlin/org/jetbrains/jewel/Button.kt b/core/src/main/kotlin/org/jetbrains/jewel/Button.kt index 8d0f6691fd..7521dda449 100644 --- a/core/src/main/kotlin/org/jetbrains/jewel/Button.kt +++ b/core/src/main/kotlin/org/jetbrains/jewel/Button.kt @@ -8,7 +8,6 @@ import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.interaction.PressInteraction import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.defaultMinSize @@ -25,7 +24,6 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.takeOrElse import androidx.compose.ui.semantics.Role import androidx.compose.ui.text.TextStyle @@ -37,7 +35,6 @@ import org.jetbrains.jewel.CommonStateBitMask.Pressed import org.jetbrains.jewel.foundation.Stroke import org.jetbrains.jewel.foundation.border import org.jetbrains.jewel.styling.ButtonStyle -import org.jetbrains.jewel.styling.IconButtonMetrics @Composable fun DefaultButton( @@ -81,59 +78,6 @@ fun OutlinedButton( ) } -@Composable -fun IconButton( - onClick: () -> Unit, - modifier: Modifier = Modifier, - enabled: Boolean = true, - metrics: IconButtonMetrics = IntelliJTheme.iconButtonMetrics, - interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, - content: @Composable (BoxScope.(ButtonState) -> Unit), -) { - var buttonState by remember(interactionSource) { - mutableStateOf(ButtonState.of(enabled = enabled)) - } - - remember(enabled) { - buttonState = buttonState.copy(enabled = enabled) - } - - LaunchedEffect(interactionSource) { - interactionSource.interactions.collect { interaction -> - when (interaction) { - is PressInteraction.Press -> buttonState = buttonState.copy(pressed = true) - is PressInteraction.Cancel, is PressInteraction.Release -> - buttonState = - buttonState.copy(pressed = false) - - is HoverInteraction.Enter -> buttonState = buttonState.copy(hovered = true) - is HoverInteraction.Exit -> buttonState = buttonState.copy(hovered = false) - is FocusInteraction.Focus -> buttonState = buttonState.copy(focused = true) - is FocusInteraction.Unfocus -> buttonState = buttonState.copy(focused = false) - } - } - } - val shape = RoundedCornerShape(metrics.cornerSize) - Box( - modifier = modifier - .defaultMinSize(metrics.minSize.width, metrics.minSize.height) - .clickable( - onClick = onClick, - enabled = enabled, - role = Role.Button, - interactionSource = interactionSource, - indication = NoIndication, - ) - .clip(shape) - .padding(metrics.padding), - propagateMinConstraints = true, - contentAlignment = Alignment.Center, - content = { - content(buttonState) - }, - ) -} - @Composable private fun ButtonImpl( onClick: () -> Unit, diff --git a/core/src/main/kotlin/org/jetbrains/jewel/IconButton.kt b/core/src/main/kotlin/org/jetbrains/jewel/IconButton.kt new file mode 100644 index 0000000000..b682cde80d --- /dev/null +++ b/core/src/main/kotlin/org/jetbrains/jewel/IconButton.kt @@ -0,0 +1,79 @@ +package org.jetbrains.jewel + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.FocusInteraction +import androidx.compose.foundation.interaction.HoverInteraction +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.interaction.PressInteraction +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxScope +import androidx.compose.foundation.layout.defaultMinSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.semantics.Role +import org.jetbrains.jewel.styling.IconButtonStyle + +@Composable +fun IconButton( + onClick: () -> Unit, + modifier: Modifier = Modifier, + enabled: Boolean = true, + style: IconButtonStyle = IntelliJTheme.iconButtonStyle, + interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, + content: @Composable (BoxScope.(ButtonState) -> Unit), +) { + var buttonState by remember(interactionSource) { + mutableStateOf(ButtonState.of(enabled = enabled)) + } + + remember(enabled) { + buttonState = buttonState.copy(enabled = enabled) + } + + LaunchedEffect(interactionSource) { + interactionSource.interactions.collect { interaction -> + when (interaction) { + is PressInteraction.Press -> buttonState = buttonState.copy(pressed = true) + is PressInteraction.Cancel, is PressInteraction.Release -> + buttonState = + buttonState.copy(pressed = false) + + is HoverInteraction.Enter -> buttonState = buttonState.copy(hovered = true) + is HoverInteraction.Exit -> buttonState = buttonState.copy(hovered = false) + is FocusInteraction.Focus -> buttonState = buttonState.copy(focused = true) + is FocusInteraction.Unfocus -> buttonState = buttonState.copy(focused = false) + } + } + } + val shape = RoundedCornerShape(style.metrics.cornerSize) + val background by style.colors.backgroundFor(buttonState) + Box( + modifier = modifier + .defaultMinSize(style.metrics.minSize.width, style.metrics.minSize.height) + .clickable( + onClick = onClick, + enabled = enabled, + role = Role.Button, + interactionSource = interactionSource, + indication = NoIndication, + ) + .clip(shape) + .padding(style.metrics.padding) + .background(background), + propagateMinConstraints = true, + contentAlignment = Alignment.Center, + content = { + content(buttonState) + }, + ) +} diff --git a/core/src/main/kotlin/org/jetbrains/jewel/IntelliJComponentStyling.kt b/core/src/main/kotlin/org/jetbrains/jewel/IntelliJComponentStyling.kt index 6c34fed642..53b478cc74 100644 --- a/core/src/main/kotlin/org/jetbrains/jewel/IntelliJComponentStyling.kt +++ b/core/src/main/kotlin/org/jetbrains/jewel/IntelliJComponentStyling.kt @@ -9,7 +9,7 @@ import org.jetbrains.jewel.styling.DividerStyle import org.jetbrains.jewel.styling.DropdownStyle import org.jetbrains.jewel.styling.GroupHeaderStyle import org.jetbrains.jewel.styling.HorizontalProgressBarStyle -import org.jetbrains.jewel.styling.IconButtonMetrics +import org.jetbrains.jewel.styling.IconButtonStyle import org.jetbrains.jewel.styling.LabelledTextFieldStyle import org.jetbrains.jewel.styling.LazyTreeStyle import org.jetbrains.jewel.styling.LinkStyle @@ -43,7 +43,7 @@ class IntelliJComponentStyling( val textFieldStyle: TextFieldStyle, val circularProgressStyle: CircularProgressStyle, val tooltipStyle: TooltipStyle, - val iconButtonMetrics: IconButtonMetrics, + val iconButtonStyle: IconButtonStyle, ) { override fun equals(other: Any?): Boolean { @@ -72,7 +72,7 @@ class IntelliJComponentStyling( if (textFieldStyle != other.textFieldStyle) return false if (circularProgressStyle != other.circularProgressStyle) return false if (tooltipStyle != other.tooltipStyle) return false - if (iconButtonMetrics != other.iconButtonMetrics) return false + if (iconButtonStyle != other.iconButtonStyle) return false return true } @@ -98,7 +98,7 @@ class IntelliJComponentStyling( result = 31 * result + textFieldStyle.hashCode() result = 31 * result + circularProgressStyle.hashCode() result = 31 * result + tooltipStyle.hashCode() - result = 31 * result + iconButtonMetrics.hashCode() + result = 31 * result + iconButtonStyle.hashCode() return result } @@ -110,5 +110,5 @@ class IntelliJComponentStyling( "labelledTextFieldStyle=$labelledTextFieldStyle, lazyTreeStyle=$lazyTreeStyle, linkStyle=$linkStyle, " + "menuStyle=$menuStyle, outlinedButtonStyle=$outlinedButtonStyle, radioButtonStyle=$radioButtonStyle, " + "scrollbarStyle=$scrollbarStyle, textAreaStyle=$textAreaStyle, textFieldStyle=$textFieldStyle, " + - "circularProgressStyle=$circularProgressStyle, tooltipStyle=$tooltipStyle)" + "circularProgressStyle=$circularProgressStyle, tooltipStyle=$tooltipStyle, iconButtonStyle=$iconButtonStyle)" } diff --git a/core/src/main/kotlin/org/jetbrains/jewel/IntelliJTheme.kt b/core/src/main/kotlin/org/jetbrains/jewel/IntelliJTheme.kt index 0bd5231817..9b5472886d 100644 --- a/core/src/main/kotlin/org/jetbrains/jewel/IntelliJTheme.kt +++ b/core/src/main/kotlin/org/jetbrains/jewel/IntelliJTheme.kt @@ -14,7 +14,7 @@ import org.jetbrains.jewel.styling.DividerStyle import org.jetbrains.jewel.styling.DropdownStyle import org.jetbrains.jewel.styling.GroupHeaderStyle import org.jetbrains.jewel.styling.HorizontalProgressBarStyle -import org.jetbrains.jewel.styling.IconButtonMetrics +import org.jetbrains.jewel.styling.IconButtonStyle import org.jetbrains.jewel.styling.LabelledTextFieldStyle import org.jetbrains.jewel.styling.LazyTreeStyle import org.jetbrains.jewel.styling.LinkStyle @@ -28,7 +28,7 @@ import org.jetbrains.jewel.styling.LocalDropdownStyle import org.jetbrains.jewel.styling.LocalEditorTabStyle import org.jetbrains.jewel.styling.LocalGroupHeaderStyle import org.jetbrains.jewel.styling.LocalHorizontalProgressBarStyle -import org.jetbrains.jewel.styling.LocalIconButtonMetrics +import org.jetbrains.jewel.styling.LocalIconButtonStyle import org.jetbrains.jewel.styling.LocalLabelledTextFieldStyle import org.jetbrains.jewel.styling.LocalLazyTreeStyle import org.jetbrains.jewel.styling.LocalLinkStyle @@ -198,10 +198,10 @@ interface IntelliJTheme { @Composable @ReadOnlyComposable get() = LocalTooltipStyle.current - val iconButtonMetrics: IconButtonMetrics + val iconButtonStyle: IconButtonStyle @Composable @ReadOnlyComposable - get() = LocalIconButtonMetrics.current + get() = LocalIconButtonStyle.current } } diff --git a/core/src/main/kotlin/org/jetbrains/jewel/styling/IconButtonMetrics.kt b/core/src/main/kotlin/org/jetbrains/jewel/styling/IconButtonMetrics.kt index 3f6419f469..c09b674ca8 100644 --- a/core/src/main/kotlin/org/jetbrains/jewel/styling/IconButtonMetrics.kt +++ b/core/src/main/kotlin/org/jetbrains/jewel/styling/IconButtonMetrics.kt @@ -2,8 +2,43 @@ package org.jetbrains.jewel.styling import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.shape.CornerSize +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Immutable +import androidx.compose.runtime.Stable +import androidx.compose.runtime.rememberUpdatedState import androidx.compose.runtime.staticCompositionLocalOf +import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.DpSize +import org.jetbrains.jewel.ButtonState + +@Stable +interface IconButtonStyle { + + val colors: IconButtonColors + val metrics: IconButtonMetrics +} + +@Immutable +interface IconButtonColors { + + val background: Color + val backgroundDisabled: Color + val backgroundFocused: Color + val backgroundPressed: Color + val backgroundHovered: Color + + @Composable + fun backgroundFor(state: ButtonState) = rememberUpdatedState( + state.chooseValue( + normal = background, + disabled = backgroundDisabled, + focused = backgroundFocused, + pressed = backgroundPressed, + hovered = backgroundHovered, + active = background, + ) + ) +} interface IconButtonMetrics { @@ -12,6 +47,6 @@ interface IconButtonMetrics { val minSize: DpSize } -val LocalIconButtonMetrics = staticCompositionLocalOf { - error("No outlined ButtonStyle provided") +val LocalIconButtonStyle = staticCompositionLocalOf { + error("No IconButtonStyle provided") } diff --git a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/IntUiBridge.kt b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/IntUiBridge.kt index 33634e3019..4192ed3798 100644 --- a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/IntUiBridge.kt +++ b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/IntUiBridge.kt @@ -50,7 +50,9 @@ import org.jetbrains.jewel.intui.standalone.styling.IntUiGroupHeaderStyle import org.jetbrains.jewel.intui.standalone.styling.IntUiHorizontalProgressBarColors import org.jetbrains.jewel.intui.standalone.styling.IntUiHorizontalProgressBarMetrics import org.jetbrains.jewel.intui.standalone.styling.IntUiHorizontalProgressBarStyle +import org.jetbrains.jewel.intui.standalone.styling.IntUiIconButtonColors import org.jetbrains.jewel.intui.standalone.styling.IntUiIconButtonMetrics +import org.jetbrains.jewel.intui.standalone.styling.IntUiIconButtonStyle import org.jetbrains.jewel.intui.standalone.styling.IntUiLabelledTextFieldColors import org.jetbrains.jewel.intui.standalone.styling.IntUiLabelledTextFieldMetrics import org.jetbrains.jewel.intui.standalone.styling.IntUiLabelledTextFieldStyle @@ -173,7 +175,7 @@ internal fun createSwingIntUiComponentStyling( circularProgressStyle = readCircularProgressStyle(theme.isDark), tooltipStyle = readTooltipStyle(), textFieldStyle = textFieldStyle, - iconButtonMetrics = IntUiIconButtonMetrics(), + iconButtonStyle = readIconButtonStyle(), ) } @@ -910,8 +912,8 @@ private fun readCircularProgressStyle( ?: if (isDark) Color(0xFF6F737A) else Color(0xFFA8ADBD), ) -private fun readTooltipStyle(): IntUiTooltipStyle { - return IntUiTooltipStyle( +private fun readTooltipStyle(): IntUiTooltipStyle = + IntUiTooltipStyle( metrics = IntUiTooltipMetrics(), colors = IntUiTooltipColors( content = retrieveColorOrUnspecified("ToolTip.foreground"), @@ -920,4 +922,15 @@ private fun readTooltipStyle(): IntUiTooltipStyle { shadow = Color.Black.copy(alpha = .6f), ), ) -} + +private fun readIconButtonStyle(): IntUiIconButtonStyle = + IntUiIconButtonStyle( + metrics = IntUiIconButtonMetrics(), + colors = IntUiIconButtonColors( + Color.Unspecified, + Color.Unspecified, + Color.Unspecified, + retrieveColorOrUnspecified("ActionButton.pressedBackground"), + retrieveColorOrUnspecified("ActionButton.hoverBackground"), + ) + ) diff --git a/int-ui/int-ui-core/src/main/kotlin/org/jetbrains/jewel/intui/core/BaseIntUiTheme.kt b/int-ui/int-ui-core/src/main/kotlin/org/jetbrains/jewel/intui/core/BaseIntUiTheme.kt index 3d10993fc0..01464dec50 100644 --- a/int-ui/int-ui-core/src/main/kotlin/org/jetbrains/jewel/intui/core/BaseIntUiTheme.kt +++ b/int-ui/int-ui-core/src/main/kotlin/org/jetbrains/jewel/intui/core/BaseIntUiTheme.kt @@ -37,7 +37,7 @@ import org.jetbrains.jewel.styling.LocalDropdownStyle import org.jetbrains.jewel.styling.LocalEditorTabStyle import org.jetbrains.jewel.styling.LocalGroupHeaderStyle import org.jetbrains.jewel.styling.LocalHorizontalProgressBarStyle -import org.jetbrains.jewel.styling.LocalIconButtonMetrics +import org.jetbrains.jewel.styling.LocalIconButtonStyle import org.jetbrains.jewel.styling.LocalLabelledTextFieldStyle import org.jetbrains.jewel.styling.LocalLazyTreeStyle import org.jetbrains.jewel.styling.LocalLinkStyle @@ -234,7 +234,7 @@ fun BaseIntUiTheme( LocalIndication provides NoIndication, LocalCircularProgressStyle provides componentStyling.circularProgressStyle, LocalTooltipStyle provides componentStyling.tooltipStyle, - LocalIconButtonMetrics provides componentStyling.iconButtonMetrics, + LocalIconButtonStyle provides componentStyling.iconButtonStyle, ) { IntelliJTheme(theme, swingCompatMode, content) } diff --git a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/IntUiTheme.kt b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/IntUiTheme.kt index 86514c6272..b73e871503 100644 --- a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/IntUiTheme.kt +++ b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/IntUiTheme.kt @@ -40,7 +40,7 @@ import org.jetbrains.jewel.intui.standalone.styling.IntUiDividerStyle import org.jetbrains.jewel.intui.standalone.styling.IntUiDropdownStyle import org.jetbrains.jewel.intui.standalone.styling.IntUiGroupHeaderStyle import org.jetbrains.jewel.intui.standalone.styling.IntUiHorizontalProgressBarStyle -import org.jetbrains.jewel.intui.standalone.styling.IntUiIconButtonMetrics +import org.jetbrains.jewel.intui.standalone.styling.IntUiIconButtonStyle import org.jetbrains.jewel.intui.standalone.styling.IntUiLabelledTextFieldStyle import org.jetbrains.jewel.intui.standalone.styling.IntUiLazyTreeStyle import org.jetbrains.jewel.intui.standalone.styling.IntUiLinkStyle @@ -59,7 +59,7 @@ import org.jetbrains.jewel.styling.DividerStyle import org.jetbrains.jewel.styling.DropdownStyle import org.jetbrains.jewel.styling.GroupHeaderStyle import org.jetbrains.jewel.styling.HorizontalProgressBarStyle -import org.jetbrains.jewel.styling.IconButtonMetrics +import org.jetbrains.jewel.styling.IconButtonStyle import org.jetbrains.jewel.styling.LabelledTextFieldStyle import org.jetbrains.jewel.styling.LazyTreeStyle import org.jetbrains.jewel.styling.LinkStyle @@ -138,7 +138,7 @@ object IntUiTheme : BaseIntUiTheme { editorTabStyle: TabStyle = IntUiTabStyle.Editor.dark(svgLoader), circularProgressStyle: CircularProgressStyle = IntUiCircularProgressStyle.dark(), tooltipStyle: IntUiTooltipStyle = IntUiTooltipStyle.dark(), - iconButtonMetrics: IconButtonMetrics = IntUiIconButtonMetrics(), + iconButtonStyle: IconButtonStyle = IntUiIconButtonStyle.dark(), ) = IntelliJComponentStyling( checkboxStyle = checkboxStyle, @@ -161,7 +161,7 @@ object IntUiTheme : BaseIntUiTheme { textFieldStyle = textFieldStyle, circularProgressStyle = circularProgressStyle, tooltipStyle = tooltipStyle, - iconButtonMetrics + iconButtonStyle = iconButtonStyle ) @Composable @@ -187,7 +187,7 @@ object IntUiTheme : BaseIntUiTheme { editorTabStyle: TabStyle = IntUiTabStyle.Editor.light(svgLoader), circularProgressStyle: CircularProgressStyle = IntUiCircularProgressStyle.light(), tooltipStyle: IntUiTooltipStyle = IntUiTooltipStyle.light(), - iconButtonMetrics: IconButtonMetrics = IntUiIconButtonMetrics(), + iconButtonStyle: IconButtonStyle = IntUiIconButtonStyle.light(), ) = IntelliJComponentStyling( checkboxStyle = checkboxStyle, chipStyle = chipStyle, @@ -209,7 +209,7 @@ object IntUiTheme : BaseIntUiTheme { textFieldStyle = textFieldStyle, circularProgressStyle = circularProgressStyle, tooltipStyle = tooltipStyle, - iconButtonMetrics = iconButtonMetrics + iconButtonStyle = iconButtonStyle ) } diff --git a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiIconButtonMetrics.kt b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiIconButtonMetrics.kt deleted file mode 100644 index 9bd43f0ca2..0000000000 --- a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiIconButtonMetrics.kt +++ /dev/null @@ -1,15 +0,0 @@ -package org.jetbrains.jewel.intui.standalone.styling - -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.shape.CornerSize -import androidx.compose.runtime.Stable -import androidx.compose.ui.unit.DpSize -import androidx.compose.ui.unit.dp -import org.jetbrains.jewel.styling.IconButtonMetrics - -@Stable -data class IntUiIconButtonMetrics( - override val cornerSize: CornerSize = CornerSize(4.dp), - override val padding: PaddingValues = PaddingValues(horizontal = 0.dp, vertical = 0.dp), - override val minSize: DpSize = DpSize(16.dp, 16.dp), -) : IconButtonMetrics diff --git a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiIconButtonStyling.kt b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiIconButtonStyling.kt new file mode 100644 index 0000000000..ea2bf83d9d --- /dev/null +++ b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiIconButtonStyling.kt @@ -0,0 +1,82 @@ +package org.jetbrains.jewel.intui.standalone.styling + +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.shape.CornerSize +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Immutable +import androidx.compose.runtime.Stable +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.DpSize +import androidx.compose.ui.unit.dp +import org.jetbrains.jewel.intui.core.theme.IntUiLightTheme +import org.jetbrains.jewel.styling.IconButtonColors +import org.jetbrains.jewel.styling.IconButtonMetrics +import org.jetbrains.jewel.styling.IconButtonStyle + +@Stable +data class IntUiIconButtonStyle( + override val colors: IntUiIconButtonColors, + override val metrics: IntUiIconButtonMetrics, +) : IconButtonStyle { + + companion object { + + @Composable + fun light() = IntUiIconButtonStyle(IntUiIconButtonColors.light(), IntUiIconButtonMetrics()) + + @Composable + fun dark() = IntUiIconButtonStyle(IntUiIconButtonColors.dark(), IntUiIconButtonMetrics()) + } +} + +@Immutable +data class IntUiIconButtonColors( + override val background: Color, + override val backgroundDisabled: Color, + override val backgroundFocused: Color, + override val backgroundPressed: Color, + override val backgroundHovered: Color, +) : IconButtonColors { + + companion object { + + @Composable + fun light( + background: Color = Color.Unspecified, + backgroundDisabled: Color = Color.Unspecified, + backgroundFocused: Color = background, + backgroundPressed: Color = IntUiLightTheme.colors.grey(11), + backgroundHovered: Color = IntUiLightTheme.colors.grey(12), + ) = + IntUiIconButtonColors( + background, + backgroundDisabled, + backgroundFocused, + backgroundPressed, + backgroundHovered, + ) + + @Composable + fun dark( + background: Color = Color.Unspecified, + backgroundDisabled: Color = Color.Unspecified, + backgroundFocused: Color = background, + backgroundPressed: Color = IntUiLightTheme.colors.grey(12), + backgroundHovered: Color = IntUiLightTheme.colors.grey(11), + ) = + IntUiIconButtonColors( + background, + backgroundDisabled, + backgroundFocused, + backgroundPressed, + backgroundHovered, + ) + } +} + +@Stable +data class IntUiIconButtonMetrics( + override val cornerSize: CornerSize = CornerSize(4.dp), + override val padding: PaddingValues = PaddingValues(horizontal = 0.dp, vertical = 0.dp), + override val minSize: DpSize = DpSize(16.dp, 16.dp), +) : IconButtonMetrics diff --git a/samples/ide-plugin/src/main/kotlin/org/jetbrains/jewel/samples/ideplugin/ComponentShowcaseTab.kt b/samples/ide-plugin/src/main/kotlin/org/jetbrains/jewel/samples/ideplugin/ComponentShowcaseTab.kt index 823e23b71e..88ca64e644 100644 --- a/samples/ide-plugin/src/main/kotlin/org/jetbrains/jewel/samples/ideplugin/ComponentShowcaseTab.kt +++ b/samples/ide-plugin/src/main/kotlin/org/jetbrains/jewel/samples/ideplugin/ComponentShowcaseTab.kt @@ -31,6 +31,7 @@ import org.jetbrains.jewel.CircularProgressIndicator import org.jetbrains.jewel.CircularProgressIndicatorBig import org.jetbrains.jewel.DefaultButton import org.jetbrains.jewel.Icon +import org.jetbrains.jewel.IconButton import org.jetbrains.jewel.LazyTree import org.jetbrains.jewel.LocalResourceLoader import org.jetbrains.jewel.OutlinedButton @@ -124,11 +125,19 @@ private fun RowScope.ColumnOne(resourceLoader: ResourceLoader) { val svgLoader = service().svgLoader Row { - val painterProvider = retrieveStatelessIcon("actions/close.svg", svgLoader, IntUiTheme.iconData) + val painterProvider = retrieveStatelessIcon("actions/more.svg", svgLoader, IntUiTheme.iconData) val painter by painterProvider.getPainter(resourceLoader) Icon(painter = painter, modifier = Modifier.border(1.dp, Color.Magenta), contentDescription = "An icon") } + Row { + IconButton(onClick = { }) { + val painterProvider = retrieveStatelessIcon("actions/close.svg", svgLoader, IntUiTheme.iconData) + val painter by painterProvider.getPainter(resourceLoader) + Icon(painter = painter, contentDescription = "An icon") + } + } + Row { Text("Circular progress small: ") CircularProgressIndicator(svgLoader) diff --git a/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/components/Buttons.kt b/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/components/Buttons.kt index ac61f69780..3185083ca4 100644 --- a/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/components/Buttons.kt +++ b/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/components/Buttons.kt @@ -1,6 +1,5 @@ package org.jetbrains.jewel.samples.standalone.components -import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth @@ -10,19 +9,16 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.res.ResourceLoader import androidx.compose.ui.unit.dp import org.jetbrains.jewel.DefaultButton import org.jetbrains.jewel.GroupHeader import org.jetbrains.jewel.Icon import org.jetbrains.jewel.IconButton -import org.jetbrains.jewel.IntelliJTheme import org.jetbrains.jewel.JewelSvgLoader import org.jetbrains.jewel.OutlinedButton import org.jetbrains.jewel.Text import org.jetbrains.jewel.styling.ResourcePainterProvider -import org.jetbrains.jewel.util.appendIf @Composable fun Buttons(svgLoader: JewelSvgLoader, resourceLoader: ResourceLoader) { @@ -54,10 +50,6 @@ fun Buttons(svgLoader: JewelSvgLoader, resourceLoader: ResourceLoader) { Icon( painter = iconPainter, "icon", - modifier = Modifier.appendIf(it.isPressed || it.isHovered) { - background(SolidColor(IntelliJTheme.contentColor.copy(alpha = 0.1f))) - } - ) } } From c2622ffe60405e3f6c9dc74e96963a6984aff130 Mon Sep 17 00:00:00 2001 From: fscarponi Date: Tue, 10 Oct 2023 19:14:03 +0200 Subject: [PATCH 05/12] Refactor button state logic & tidy method declarations Revised the button state logic of the IconButton component in IconButtonMetrics.kt with a more intuitive 'when' statement, improving readability. Likewise, method declarations in the IntUiBridge.kt file were reformatted for brevity. This maintenance will enhance the code's readability and thus its maintainability. Changes in IconButton.kt reflect the updated logic and background colour application. The @Stable annotation was attached to the IconButtonMetrics interface to indicate thread-safe and side-effect-free operations, a useful indicator for composing efficient composable functions in Jetpack Compose. --- .../kotlin/org/jetbrains/jewel/IconButton.kt | 5 +- .../jewel/styling/IconButtonMetrics.kt | 16 +++--- .../org/jetbrains/jewel/bridge/IntUiBridge.kt | 53 +++++++++---------- 3 files changed, 36 insertions(+), 38 deletions(-) diff --git a/core/src/main/kotlin/org/jetbrains/jewel/IconButton.kt b/core/src/main/kotlin/org/jetbrains/jewel/IconButton.kt index b682cde80d..2ad0109fed 100644 --- a/core/src/main/kotlin/org/jetbrains/jewel/IconButton.kt +++ b/core/src/main/kotlin/org/jetbrains/jewel/IconButton.kt @@ -50,13 +50,14 @@ fun IconButton( is HoverInteraction.Enter -> buttonState = buttonState.copy(hovered = true) is HoverInteraction.Exit -> buttonState = buttonState.copy(hovered = false) + is FocusInteraction.Focus -> buttonState = buttonState.copy(focused = true) is FocusInteraction.Unfocus -> buttonState = buttonState.copy(focused = false) } } } val shape = RoundedCornerShape(style.metrics.cornerSize) - val background by style.colors.backgroundFor(buttonState) + val background = style.colors.backgroundFor(buttonState) Box( modifier = modifier .defaultMinSize(style.metrics.minSize.width, style.metrics.minSize.height) @@ -69,7 +70,7 @@ fun IconButton( ) .clip(shape) .padding(style.metrics.padding) - .background(background), + .background(background.value), propagateMinConstraints = true, contentAlignment = Alignment.Center, content = { diff --git a/core/src/main/kotlin/org/jetbrains/jewel/styling/IconButtonMetrics.kt b/core/src/main/kotlin/org/jetbrains/jewel/styling/IconButtonMetrics.kt index c09b674ca8..7e07c48d83 100644 --- a/core/src/main/kotlin/org/jetbrains/jewel/styling/IconButtonMetrics.kt +++ b/core/src/main/kotlin/org/jetbrains/jewel/styling/IconButtonMetrics.kt @@ -29,17 +29,17 @@ interface IconButtonColors { @Composable fun backgroundFor(state: ButtonState) = rememberUpdatedState( - state.chooseValue( - normal = background, - disabled = backgroundDisabled, - focused = backgroundFocused, - pressed = backgroundPressed, - hovered = backgroundHovered, - active = background, - ) + when { + !state.isEnabled -> backgroundDisabled + state.isPressed -> backgroundPressed + state.isFocused -> backgroundFocused + state.isHovered -> backgroundHovered + else -> background + }, ) } +@Stable interface IconButtonMetrics { val cornerSize: CornerSize diff --git a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/IntUiBridge.kt b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/IntUiBridge.kt index 4192ed3798..0e03b322df 100644 --- a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/IntUiBridge.kt +++ b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/IntUiBridge.kt @@ -904,33 +904,30 @@ private fun readEditorTabStyle(iconData: IntelliJThemeIconData, svgLoader: SvgLo private fun readCircularProgressStyle( isDark: Boolean, -): IntUiCircularProgressStyle = - IntUiCircularProgressStyle( - frameTime = 125.milliseconds, - color = retrieveColorOrUnspecified("ProgressIcon.color") - .takeIf { it.isSpecified } - ?: if (isDark) Color(0xFF6F737A) else Color(0xFFA8ADBD), - ) - -private fun readTooltipStyle(): IntUiTooltipStyle = - IntUiTooltipStyle( - metrics = IntUiTooltipMetrics(), - colors = IntUiTooltipColors( - content = retrieveColorOrUnspecified("ToolTip.foreground"), - background = retrieveColorOrUnspecified("ToolTip.background"), - border = retrieveColorOrUnspecified("ToolTip.borderColor"), - shadow = Color.Black.copy(alpha = .6f), - ), - ) +): IntUiCircularProgressStyle = IntUiCircularProgressStyle( + frameTime = 125.milliseconds, + color = retrieveColorOrUnspecified("ProgressIcon.color") + .takeIf { it.isSpecified } + ?: if (isDark) Color(0xFF6F737A) else Color(0xFFA8ADBD), +) + +private fun readTooltipStyle(): IntUiTooltipStyle = IntUiTooltipStyle( + metrics = IntUiTooltipMetrics(), + colors = IntUiTooltipColors( + content = retrieveColorOrUnspecified("ToolTip.foreground"), + background = retrieveColorOrUnspecified("ToolTip.background"), + border = retrieveColorOrUnspecified("ToolTip.borderColor"), + shadow = Color.Black.copy(alpha = .6f), + ), +) -private fun readIconButtonStyle(): IntUiIconButtonStyle = - IntUiIconButtonStyle( - metrics = IntUiIconButtonMetrics(), - colors = IntUiIconButtonColors( - Color.Unspecified, - Color.Unspecified, - Color.Unspecified, - retrieveColorOrUnspecified("ActionButton.pressedBackground"), - retrieveColorOrUnspecified("ActionButton.hoverBackground"), - ) +private fun readIconButtonStyle(): IntUiIconButtonStyle = IntUiIconButtonStyle( + metrics = IntUiIconButtonMetrics(), + colors = IntUiIconButtonColors( + background = Color.Unspecified, + backgroundDisabled = Color.Unspecified, + backgroundFocused = Color.Unspecified, + backgroundPressed = retrieveColorOrUnspecified("ActionButton.pressedBackground"), + backgroundHovered = retrieveColorOrUnspecified("ActionButton.hoverBackground"), ) +) From 6c54dee89d67431475fdac1210a05bbff84ecd28 Mon Sep 17 00:00:00 2001 From: fscarponi Date: Tue, 10 Oct 2023 19:18:16 +0200 Subject: [PATCH 06/12] Refactor IconButton state selection logic The methodology for selecting the state of the IconButton was refactored from a 'when' statement to the 'chooseValue' --- .../jetbrains/jewel/styling/IconButtonMetrics.kt | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/core/src/main/kotlin/org/jetbrains/jewel/styling/IconButtonMetrics.kt b/core/src/main/kotlin/org/jetbrains/jewel/styling/IconButtonMetrics.kt index 7e07c48d83..a06571196e 100644 --- a/core/src/main/kotlin/org/jetbrains/jewel/styling/IconButtonMetrics.kt +++ b/core/src/main/kotlin/org/jetbrains/jewel/styling/IconButtonMetrics.kt @@ -29,13 +29,14 @@ interface IconButtonColors { @Composable fun backgroundFor(state: ButtonState) = rememberUpdatedState( - when { - !state.isEnabled -> backgroundDisabled - state.isPressed -> backgroundPressed - state.isFocused -> backgroundFocused - state.isHovered -> backgroundHovered - else -> background - }, + state.chooseValue( + normal = background, + disabled = backgroundDisabled, + focused = backgroundFocused, + pressed = backgroundPressed, + hovered = backgroundHovered, + active = background, + ), ) } From 19cb40f092952afc21f46e9ea611f3a6d9b08a27 Mon Sep 17 00:00:00 2001 From: fscarponi Date: Wed, 11 Oct 2023 12:47:17 +0200 Subject: [PATCH 07/12] Update button styling in IntUiDarkTheme The IntUiDarkTheme now uses different colors for the "pressed" and "hovered" states of a button. Additionally, the background color selection logic has been refactored in IconButtonMetrics.kt to use a simpler and more readable 'when' construct. --- .../main/kotlin/org/jetbrains/jewel/IconButton.kt | 4 ++-- .../jetbrains/jewel/styling/IconButtonMetrics.kt | 15 +++++++-------- .../standalone/styling/IntUiIconButtonStyling.kt | 5 +++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/core/src/main/kotlin/org/jetbrains/jewel/IconButton.kt b/core/src/main/kotlin/org/jetbrains/jewel/IconButton.kt index 2ad0109fed..6e0ad2c4ad 100644 --- a/core/src/main/kotlin/org/jetbrains/jewel/IconButton.kt +++ b/core/src/main/kotlin/org/jetbrains/jewel/IconButton.kt @@ -57,7 +57,7 @@ fun IconButton( } } val shape = RoundedCornerShape(style.metrics.cornerSize) - val background = style.colors.backgroundFor(buttonState) + val backgroundColor by style.colors.backgroundFor(buttonState) Box( modifier = modifier .defaultMinSize(style.metrics.minSize.width, style.metrics.minSize.height) @@ -70,7 +70,7 @@ fun IconButton( ) .clip(shape) .padding(style.metrics.padding) - .background(background.value), + .background(backgroundColor), propagateMinConstraints = true, contentAlignment = Alignment.Center, content = { diff --git a/core/src/main/kotlin/org/jetbrains/jewel/styling/IconButtonMetrics.kt b/core/src/main/kotlin/org/jetbrains/jewel/styling/IconButtonMetrics.kt index a06571196e..fb4b108504 100644 --- a/core/src/main/kotlin/org/jetbrains/jewel/styling/IconButtonMetrics.kt +++ b/core/src/main/kotlin/org/jetbrains/jewel/styling/IconButtonMetrics.kt @@ -29,14 +29,13 @@ interface IconButtonColors { @Composable fun backgroundFor(state: ButtonState) = rememberUpdatedState( - state.chooseValue( - normal = background, - disabled = backgroundDisabled, - focused = backgroundFocused, - pressed = backgroundPressed, - hovered = backgroundHovered, - active = background, - ), + when { + !state.isEnabled -> backgroundDisabled + state.isPressed -> backgroundPressed + state.isHovered -> backgroundHovered + state.isFocused -> backgroundFocused + else -> background + } ) } diff --git a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiIconButtonStyling.kt b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiIconButtonStyling.kt index ea2bf83d9d..ebdf0bc829 100644 --- a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiIconButtonStyling.kt +++ b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiIconButtonStyling.kt @@ -8,6 +8,7 @@ import androidx.compose.runtime.Stable import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.dp +import org.jetbrains.jewel.intui.core.theme.IntUiDarkTheme import org.jetbrains.jewel.intui.core.theme.IntUiLightTheme import org.jetbrains.jewel.styling.IconButtonColors import org.jetbrains.jewel.styling.IconButtonMetrics @@ -61,8 +62,8 @@ data class IntUiIconButtonColors( background: Color = Color.Unspecified, backgroundDisabled: Color = Color.Unspecified, backgroundFocused: Color = background, - backgroundPressed: Color = IntUiLightTheme.colors.grey(12), - backgroundHovered: Color = IntUiLightTheme.colors.grey(11), + backgroundPressed: Color = IntUiDarkTheme.colors.grey(5), + backgroundHovered: Color = IntUiDarkTheme.colors.grey(3), ) = IntUiIconButtonColors( background, From 2ae1d28fae2a9bd7d667249a07b75324035f2a14 Mon Sep 17 00:00:00 2001 From: fscarponi Date: Wed, 11 Oct 2023 12:49:01 +0200 Subject: [PATCH 08/12] reverted wrong downgrade --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0750416a19..370a2df4d3 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -composeDesktop = "1.5.10-beta01" +composeDesktop = "1.5.2" coroutines = "1.7.3" detekt = "1.23.1" idea232 = "232.8660.185" From dbda0c28bf448fe0abe5b3c3cd29739c1e9b21da Mon Sep 17 00:00:00 2001 From: fscarponi Date: Wed, 11 Oct 2023 12:56:05 +0200 Subject: [PATCH 09/12] happy lint --- .../kotlin/org/jetbrains/jewel/styling/IconButtonMetrics.kt | 2 +- .../src/main/kotlin/org/jetbrains/jewel/bridge/IntUiBridge.kt | 2 +- .../kotlin/org/jetbrains/jewel/intui/standalone/IntUiTheme.kt | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/src/main/kotlin/org/jetbrains/jewel/styling/IconButtonMetrics.kt b/core/src/main/kotlin/org/jetbrains/jewel/styling/IconButtonMetrics.kt index fb4b108504..ab08e520f3 100644 --- a/core/src/main/kotlin/org/jetbrains/jewel/styling/IconButtonMetrics.kt +++ b/core/src/main/kotlin/org/jetbrains/jewel/styling/IconButtonMetrics.kt @@ -35,7 +35,7 @@ interface IconButtonColors { state.isHovered -> backgroundHovered state.isFocused -> backgroundFocused else -> background - } + }, ) } diff --git a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/IntUiBridge.kt b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/IntUiBridge.kt index 0e03b322df..82f51417d1 100644 --- a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/IntUiBridge.kt +++ b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/IntUiBridge.kt @@ -929,5 +929,5 @@ private fun readIconButtonStyle(): IntUiIconButtonStyle = IntUiIconButtonStyle( backgroundFocused = Color.Unspecified, backgroundPressed = retrieveColorOrUnspecified("ActionButton.pressedBackground"), backgroundHovered = retrieveColorOrUnspecified("ActionButton.hoverBackground"), - ) + ), ) diff --git a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/IntUiTheme.kt b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/IntUiTheme.kt index b73e871503..f3d94c5d09 100644 --- a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/IntUiTheme.kt +++ b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/IntUiTheme.kt @@ -161,7 +161,7 @@ object IntUiTheme : BaseIntUiTheme { textFieldStyle = textFieldStyle, circularProgressStyle = circularProgressStyle, tooltipStyle = tooltipStyle, - iconButtonStyle = iconButtonStyle + iconButtonStyle = iconButtonStyle, ) @Composable @@ -209,7 +209,7 @@ object IntUiTheme : BaseIntUiTheme { textFieldStyle = textFieldStyle, circularProgressStyle = circularProgressStyle, tooltipStyle = tooltipStyle, - iconButtonStyle = iconButtonStyle + iconButtonStyle = iconButtonStyle, ) } From 9643b1df3a6220afea29173aa2e128eb6e370d49 Mon Sep 17 00:00:00 2001 From: fscarponi Date: Thu, 12 Oct 2023 09:07:18 +0200 Subject: [PATCH 10/12] Change button icon and adjustments on display elements This commit replaces the 'more' button icon with a 'close' button icon in ComponentShowcaseTab.kt. It also removes the 'propagateMinConstraints' property from IconButton.kt. In addition, it adjusts IconButton to not necessarily need 'Modifier.size' in Buttons.kt. These changes are made to improve the UI's look and functionality. --- core/src/main/kotlin/org/jetbrains/jewel/IconButton.kt | 1 - .../jetbrains/jewel/samples/ideplugin/ComponentShowcaseTab.kt | 2 +- .../jetbrains/jewel/samples/standalone/components/Buttons.kt | 3 +-- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/core/src/main/kotlin/org/jetbrains/jewel/IconButton.kt b/core/src/main/kotlin/org/jetbrains/jewel/IconButton.kt index 6e0ad2c4ad..51fddc6e5c 100644 --- a/core/src/main/kotlin/org/jetbrains/jewel/IconButton.kt +++ b/core/src/main/kotlin/org/jetbrains/jewel/IconButton.kt @@ -71,7 +71,6 @@ fun IconButton( .clip(shape) .padding(style.metrics.padding) .background(backgroundColor), - propagateMinConstraints = true, contentAlignment = Alignment.Center, content = { content(buttonState) diff --git a/samples/ide-plugin/src/main/kotlin/org/jetbrains/jewel/samples/ideplugin/ComponentShowcaseTab.kt b/samples/ide-plugin/src/main/kotlin/org/jetbrains/jewel/samples/ideplugin/ComponentShowcaseTab.kt index 88ca64e644..41d35cae25 100644 --- a/samples/ide-plugin/src/main/kotlin/org/jetbrains/jewel/samples/ideplugin/ComponentShowcaseTab.kt +++ b/samples/ide-plugin/src/main/kotlin/org/jetbrains/jewel/samples/ideplugin/ComponentShowcaseTab.kt @@ -125,7 +125,7 @@ private fun RowScope.ColumnOne(resourceLoader: ResourceLoader) { val svgLoader = service().svgLoader Row { - val painterProvider = retrieveStatelessIcon("actions/more.svg", svgLoader, IntUiTheme.iconData) + val painterProvider = retrieveStatelessIcon("actions/close.svg", svgLoader, IntUiTheme.iconData) val painter by painterProvider.getPainter(resourceLoader) Icon(painter = painter, modifier = Modifier.border(1.dp, Color.Magenta), contentDescription = "An icon") } diff --git a/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/components/Buttons.kt b/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/components/Buttons.kt index 3185083ca4..36277b54c2 100644 --- a/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/components/Buttons.kt +++ b/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/components/Buttons.kt @@ -3,7 +3,6 @@ package org.jetbrains.jewel.samples.standalone.components import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.size import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.remember @@ -44,7 +43,7 @@ fun Buttons(svgLoader: JewelSvgLoader, resourceLoader: ResourceLoader) { Text("Default disabled") } - IconButton(onClick = {}, modifier = Modifier.size(30.dp)) { + IconButton(onClick = {}) { val iconProvider = remember { ResourcePainterProvider.stateless("icons/close.svg", svgLoader) } val iconPainter by iconProvider.getPainter(resourceLoader) Icon( From 89f28402eb268751b56411f33b780f02c4d1a065 Mon Sep 17 00:00:00 2001 From: fscarponi Date: Thu, 12 Oct 2023 09:10:00 +0200 Subject: [PATCH 11/12] updates improve visibility and user interaction by providing a more intuitive interface. Default background color for disabled buttons has been set --- .../intui/standalone/styling/IntUiIconButtonStyling.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiIconButtonStyling.kt b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiIconButtonStyling.kt index ebdf0bc829..7dabbb81a1 100644 --- a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiIconButtonStyling.kt +++ b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiIconButtonStyling.kt @@ -44,7 +44,7 @@ data class IntUiIconButtonColors( @Composable fun light( background: Color = Color.Unspecified, - backgroundDisabled: Color = Color.Unspecified, + backgroundDisabled: Color = background, backgroundFocused: Color = background, backgroundPressed: Color = IntUiLightTheme.colors.grey(11), backgroundHovered: Color = IntUiLightTheme.colors.grey(12), @@ -60,7 +60,7 @@ data class IntUiIconButtonColors( @Composable fun dark( background: Color = Color.Unspecified, - backgroundDisabled: Color = Color.Unspecified, + backgroundDisabled: Color = background, backgroundFocused: Color = background, backgroundPressed: Color = IntUiDarkTheme.colors.grey(5), backgroundHovered: Color = IntUiDarkTheme.colors.grey(3), @@ -78,6 +78,6 @@ data class IntUiIconButtonColors( @Stable data class IntUiIconButtonMetrics( override val cornerSize: CornerSize = CornerSize(4.dp), - override val padding: PaddingValues = PaddingValues(horizontal = 0.dp, vertical = 0.dp), + override val padding: PaddingValues = PaddingValues(0.dp), override val minSize: DpSize = DpSize(16.dp, 16.dp), ) : IconButtonMetrics From 277a2f8effb78081510ad1b42bb09008151a564f Mon Sep 17 00:00:00 2001 From: fscarponi Date: Thu, 12 Oct 2023 10:39:18 +0200 Subject: [PATCH 12/12] "Add border styling to IconButton This update adds border styling to the IconButton component. The main changes include importing 'border' from the compose foundation, defining border color for different button states, and applying the border in the IconButton component. This change was made to improve the overall visual appearance of the button, especially in different states, providing a more intuitive interface. It also helps better distinguish the buttons from the background, improving user interaction." --- .../kotlin/org/jetbrains/jewel/IconButton.kt | 7 +++- .../jewel/styling/IconButtonMetrics.kt | 19 +++++++++ .../org/jetbrains/jewel/bridge/IntUiBridge.kt | 42 +++++++++++-------- .../styling/IntUiIconButtonStyling.kt | 27 ++++++++++++ 4 files changed, 76 insertions(+), 19 deletions(-) diff --git a/core/src/main/kotlin/org/jetbrains/jewel/IconButton.kt b/core/src/main/kotlin/org/jetbrains/jewel/IconButton.kt index 51fddc6e5c..3b6d9a4280 100644 --- a/core/src/main/kotlin/org/jetbrains/jewel/IconButton.kt +++ b/core/src/main/kotlin/org/jetbrains/jewel/IconButton.kt @@ -1,6 +1,7 @@ package org.jetbrains.jewel import androidx.compose.foundation.background +import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.FocusInteraction import androidx.compose.foundation.interaction.HoverInteraction @@ -57,7 +58,8 @@ fun IconButton( } } val shape = RoundedCornerShape(style.metrics.cornerSize) - val backgroundColor by style.colors.backgroundFor(buttonState) + val background by style.colors.backgroundFor(buttonState) + val border by style.colors.borderFor(buttonState) Box( modifier = modifier .defaultMinSize(style.metrics.minSize.width, style.metrics.minSize.height) @@ -70,7 +72,8 @@ fun IconButton( ) .clip(shape) .padding(style.metrics.padding) - .background(backgroundColor), + .background(background) + .border(style.metrics.borderWidth, border), contentAlignment = Alignment.Center, content = { content(buttonState) diff --git a/core/src/main/kotlin/org/jetbrains/jewel/styling/IconButtonMetrics.kt b/core/src/main/kotlin/org/jetbrains/jewel/styling/IconButtonMetrics.kt index ab08e520f3..04541a1b18 100644 --- a/core/src/main/kotlin/org/jetbrains/jewel/styling/IconButtonMetrics.kt +++ b/core/src/main/kotlin/org/jetbrains/jewel/styling/IconButtonMetrics.kt @@ -8,6 +8,7 @@ import androidx.compose.runtime.Stable import androidx.compose.runtime.rememberUpdatedState import androidx.compose.runtime.staticCompositionLocalOf import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.DpSize import org.jetbrains.jewel.ButtonState @@ -27,6 +28,12 @@ interface IconButtonColors { val backgroundPressed: Color val backgroundHovered: Color + val border: Color + val borderDisabled: Color + val borderFocused: Color + val borderPressed: Color + val borderHovered: Color + @Composable fun backgroundFor(state: ButtonState) = rememberUpdatedState( when { @@ -37,12 +44,24 @@ interface IconButtonColors { else -> background }, ) + + @Composable + fun borderFor(state: ButtonState) = rememberUpdatedState( + when { + !state.isEnabled -> borderDisabled + state.isPressed -> borderPressed + state.isHovered -> borderHovered + state.isFocused -> borderFocused + else -> border + }, + ) } @Stable interface IconButtonMetrics { val cornerSize: CornerSize + val borderWidth: Dp val padding: PaddingValues val minSize: DpSize } diff --git a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/IntUiBridge.kt b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/IntUiBridge.kt index 82f51417d1..f79e1f3c69 100644 --- a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/IntUiBridge.kt +++ b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/IntUiBridge.kt @@ -904,30 +904,38 @@ private fun readEditorTabStyle(iconData: IntelliJThemeIconData, svgLoader: SvgLo private fun readCircularProgressStyle( isDark: Boolean, -): IntUiCircularProgressStyle = IntUiCircularProgressStyle( - frameTime = 125.milliseconds, - color = retrieveColorOrUnspecified("ProgressIcon.color") - .takeIf { it.isSpecified } - ?: if (isDark) Color(0xFF6F737A) else Color(0xFFA8ADBD), -) - -private fun readTooltipStyle(): IntUiTooltipStyle = IntUiTooltipStyle( - metrics = IntUiTooltipMetrics(), - colors = IntUiTooltipColors( - content = retrieveColorOrUnspecified("ToolTip.foreground"), - background = retrieveColorOrUnspecified("ToolTip.background"), - border = retrieveColorOrUnspecified("ToolTip.borderColor"), - shadow = Color.Black.copy(alpha = .6f), - ), -) +): IntUiCircularProgressStyle = + IntUiCircularProgressStyle( + frameTime = 125.milliseconds, + color = retrieveColorOrUnspecified("ProgressIcon.color") + .takeIf { it.isSpecified } + ?: if (isDark) Color(0xFF6F737A) else Color(0xFFA8ADBD), + ) + +private fun readTooltipStyle(): IntUiTooltipStyle { + return IntUiTooltipStyle( + metrics = IntUiTooltipMetrics(), + colors = IntUiTooltipColors( + content = retrieveColorOrUnspecified("ToolTip.foreground"), + background = retrieveColorOrUnspecified("ToolTip.background"), + border = retrieveColorOrUnspecified("ToolTip.borderColor"), + shadow = retrieveColorOrUnspecified("Notification.Shadow.bottom1Color"), + ), + ) +} private fun readIconButtonStyle(): IntUiIconButtonStyle = IntUiIconButtonStyle( - metrics = IntUiIconButtonMetrics(), + metrics = IntUiIconButtonMetrics(CornerSize(DarculaUIUtil.BUTTON_ARC.dp / 2)), colors = IntUiIconButtonColors( background = Color.Unspecified, backgroundDisabled = Color.Unspecified, backgroundFocused = Color.Unspecified, backgroundPressed = retrieveColorOrUnspecified("ActionButton.pressedBackground"), backgroundHovered = retrieveColorOrUnspecified("ActionButton.hoverBackground"), + border = Color.Unspecified, + borderDisabled = Color.Unspecified, + borderFocused = retrieveColorOrUnspecified("ActionButton.focusedBorderColor"), + borderPressed = retrieveColorOrUnspecified("ActionButton.pressedBorderColor"), + borderHovered = retrieveColorOrUnspecified("ActionButton.hoverBorderColor"), ), ) diff --git a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiIconButtonStyling.kt b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiIconButtonStyling.kt index 7dabbb81a1..4d212b1174 100644 --- a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiIconButtonStyling.kt +++ b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiIconButtonStyling.kt @@ -6,6 +6,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.Immutable import androidx.compose.runtime.Stable import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.dp import org.jetbrains.jewel.intui.core.theme.IntUiDarkTheme @@ -37,6 +38,11 @@ data class IntUiIconButtonColors( override val backgroundFocused: Color, override val backgroundPressed: Color, override val backgroundHovered: Color, + override val border: Color, + override val borderDisabled: Color, + override val borderFocused: Color, + override val borderPressed: Color, + override val borderHovered: Color, ) : IconButtonColors { companion object { @@ -48,6 +54,11 @@ data class IntUiIconButtonColors( backgroundFocused: Color = background, backgroundPressed: Color = IntUiLightTheme.colors.grey(11), backgroundHovered: Color = IntUiLightTheme.colors.grey(12), + border: Color = background, + borderDisabled: Color = border, + borderFocused: Color = IntUiLightTheme.colors.blue(5), + borderPressed: Color = backgroundPressed, + borderHovered: Color = backgroundHovered, ) = IntUiIconButtonColors( background, @@ -55,6 +66,11 @@ data class IntUiIconButtonColors( backgroundFocused, backgroundPressed, backgroundHovered, + border, + borderDisabled, + borderFocused, + borderPressed, + borderHovered, ) @Composable @@ -64,6 +80,11 @@ data class IntUiIconButtonColors( backgroundFocused: Color = background, backgroundPressed: Color = IntUiDarkTheme.colors.grey(5), backgroundHovered: Color = IntUiDarkTheme.colors.grey(3), + border: Color = background, + borderDisabled: Color = border, + borderFocused: Color = IntUiDarkTheme.colors.blue(6), + borderPressed: Color = backgroundPressed, + borderHovered: Color = backgroundHovered, ) = IntUiIconButtonColors( background, @@ -71,6 +92,11 @@ data class IntUiIconButtonColors( backgroundFocused, backgroundPressed, backgroundHovered, + border, + borderDisabled, + borderFocused, + borderPressed, + borderHovered, ) } } @@ -78,6 +104,7 @@ data class IntUiIconButtonColors( @Stable data class IntUiIconButtonMetrics( override val cornerSize: CornerSize = CornerSize(4.dp), + override val borderWidth: Dp = 1.dp, override val padding: PaddingValues = PaddingValues(0.dp), override val minSize: DpSize = DpSize(16.dp, 16.dp), ) : IconButtonMetrics