From 3713d4574b5b9cd59244a2b0631fde6c88f845e3 Mon Sep 17 00:00:00 2001 From: Sebastiano Poggi Date: Mon, 15 Jul 2024 18:12:27 +0200 Subject: [PATCH] Add ActionButton component (#450) It's like IconActionButton, but it doesn't necessarily hold an icon. For example, it can be used to implement an equivalent to Swing's ActionButtonWithText component. There is a standalone sample, too --- .../standalone/view/component/Buttons.kt | 25 ++++ ui/api/ui.api | 5 + .../ui/component/styling/ActionButton.kt | 107 ++++++++++++++++++ .../ui/component/styling/IconActionButton.kt | 12 +- 4 files changed, 143 insertions(+), 6 deletions(-) create mode 100644 ui/src/main/kotlin/org/jetbrains/jewel/ui/component/styling/ActionButton.kt diff --git a/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/view/component/Buttons.kt b/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/view/component/Buttons.kt index 6e46928c0..93cc4d174 100644 --- a/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/view/component/Buttons.kt +++ b/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/view/component/Buttons.kt @@ -20,6 +20,7 @@ import org.jetbrains.jewel.ui.component.PlatformIcon import org.jetbrains.jewel.ui.component.SelectableIconButton import org.jetbrains.jewel.ui.component.Text import org.jetbrains.jewel.ui.component.Typography +import org.jetbrains.jewel.ui.component.styling.ActionButton import org.jetbrains.jewel.ui.component.styling.IconActionButton import org.jetbrains.jewel.ui.component.styling.LocalIconButtonStyle import org.jetbrains.jewel.ui.icons.AllIconsKeys @@ -35,6 +36,7 @@ fun Buttons() { NormalButtons() IconButtons() IconActionButtons() + ActionButtons() } } @@ -118,3 +120,26 @@ private fun IconActionButtons() { IconActionButton(key = AllIconsKeys.Actions.Copy, contentDescription = "IconButton", onClick = {}) } } + +@Composable +private fun ActionButtons() { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(16.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Text("ActionButton", style = Typography.h4TextStyle()) + + Text("With tooltip:") + + ActionButton(onClick = {}, tooltip = { Text("I am a tooltip") }) { + Text("Hover me!") + } + + Text("Without tooltip:") + + ActionButton(onClick = {}) { + Text("Do something") + } + } +} diff --git a/ui/api/ui.api b/ui/api/ui.api index 711b3b69f..84e9061bc 100644 --- a/ui/api/ui.api +++ b/ui/api/ui.api @@ -769,6 +769,11 @@ public final class org/jetbrains/jewel/ui/component/TypographyKt { public static final fun plus-NB67dxo (JJ)J } +public final class org/jetbrains/jewel/ui/component/styling/ActionButtonKt { + public static final fun ActionButton (Lkotlin/jvm/functions/Function0;Landroidx/compose/ui/Modifier;ZZLorg/jetbrains/jewel/ui/component/styling/IconButtonStyle;Landroidx/compose/foundation/layout/PaddingValues;Landroidx/compose/foundation/interaction/MutableInteractionSource;Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;II)V + public static final fun ActionButton (Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function2;Landroidx/compose/ui/Modifier;ZZLorg/jetbrains/jewel/ui/component/styling/IconButtonStyle;Landroidx/compose/foundation/layout/PaddingValues;Lorg/jetbrains/jewel/ui/component/styling/TooltipStyle;Landroidx/compose/foundation/TooltipPlacement;Landroidx/compose/foundation/interaction/MutableInteractionSource;Lkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;III)V +} + public final class org/jetbrains/jewel/ui/component/styling/ButtonColors { public static final field $stable I public static final field Companion Lorg/jetbrains/jewel/ui/component/styling/ButtonColors$Companion; diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/styling/ActionButton.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/styling/ActionButton.kt new file mode 100644 index 000000000..2cf44cd61 --- /dev/null +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/styling/ActionButton.kt @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.jewel.ui.component.styling + +import androidx.compose.foundation.TooltipPlacement +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.DpOffset +import androidx.compose.ui.unit.dp +import org.jetbrains.jewel.foundation.theme.JewelTheme +import org.jetbrains.jewel.ui.component.FixedCursorPoint +import org.jetbrains.jewel.ui.component.IconButton +import org.jetbrains.jewel.ui.component.Tooltip +import org.jetbrains.jewel.ui.theme.iconButtonStyle +import org.jetbrains.jewel.ui.theme.tooltipStyle + +@Composable +public fun ActionButton( + onClick: () -> Unit, + modifier: Modifier = Modifier, + enabled: Boolean = true, + focusable: Boolean = true, + style: IconButtonStyle = JewelTheme.iconButtonStyle, + contentPadding: PaddingValues = PaddingValues(horizontal = 4.dp), + interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, + content: @Composable () -> Unit, +) { + CoreActionButton( + onClick, + enabled, + focusable, + style, + interactionSource, + modifier, + ) { + Box(Modifier.padding(contentPadding)) { + content() + } + } +} + +@Composable +public fun ActionButton( + onClick: () -> Unit, + tooltip: @Composable () -> Unit, + modifier: Modifier = Modifier, + enabled: Boolean = true, + focusable: Boolean = true, + style: IconButtonStyle = JewelTheme.iconButtonStyle, + contentPadding: PaddingValues = PaddingValues(horizontal = 4.dp), + tooltipStyle: TooltipStyle = JewelTheme.tooltipStyle, + tooltipPlacement: TooltipPlacement = FixedCursorPoint(offset = DpOffset(0.dp, 16.dp)), + interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, + content: @Composable () -> Unit, +) { + Tooltip( + tooltip, + style = tooltipStyle, + tooltipPlacement = tooltipPlacement, + modifier = modifier, + ) { + CoreActionButton( + onClick = onClick, + enabled = enabled, + focusable = focusable, + style = style, + interactionSource = interactionSource, + ) { + Box(Modifier.padding(contentPadding)) { + content() + } + } + } +} + +@Composable +private fun CoreActionButton( + onClick: () -> Unit, + enabled: Boolean, + focusable: Boolean, + style: IconButtonStyle, + interactionSource: MutableInteractionSource, + modifier: Modifier = Modifier, + content: @Composable () -> Unit, +) { + IconButton(onClick, modifier, enabled, focusable, style, interactionSource) { + content() + } +} diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/styling/IconActionButton.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/styling/IconActionButton.kt index 077332cfc..701a2d4f1 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/styling/IconActionButton.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/styling/IconActionButton.kt @@ -44,7 +44,7 @@ public fun IconActionButton( interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, iconClass: Class<*> = key::class.java, ) { - CoreIconButton( + CoreIconActionButton( key, contentDescription, iconClass, @@ -78,7 +78,7 @@ public fun IconActionButton( tooltipPlacement = tooltipPlacement, modifier = modifier, ) { - CoreIconButton( + CoreIconActionButton( key = key, contentDescription = contentDescription, iconClass = iconClass, @@ -92,7 +92,7 @@ public fun IconActionButton( } @Composable -private fun CoreIconButton( +private fun CoreIconActionButton( key: IconKey, contentDescription: String?, iconClass: Class<*>, @@ -119,7 +119,7 @@ public fun IconActionButton( style: IconButtonStyle = JewelTheme.iconButtonStyle, interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, ) { - CoreIconButton( + CoreIconActionButton( painter, contentDescription, enabled, @@ -151,7 +151,7 @@ public fun IconActionButton( tooltipPlacement = tooltipPlacement, modifier = modifier, ) { - CoreIconButton( + CoreIconActionButton( painter = painter, contentDescription = contentDescription, enabled = enabled, @@ -164,7 +164,7 @@ public fun IconActionButton( } @Composable -private fun CoreIconButton( +private fun CoreIconActionButton( painter: Painter, contentDescription: String?, enabled: Boolean,