From 904bb804820a60178806d9aa446a845788fd5c3e Mon Sep 17 00:00:00 2001 From: fscarponi Date: Mon, 18 Dec 2023 16:28:53 +0100 Subject: [PATCH] Update the tab component for better customization TabScope now expose a new Api to allow a custom content inside the composable, updated standalone sample --- .../jewel/bridge/theme/IntUiBridge.kt | 4 +- .../intui/standalone/theme/IntUiTheme.kt | 6 +- .../samples/standalone/view/component/Tabs.kt | 98 +++++++++++++++++-- ui/api/ui.api | 38 +++++-- .../jewel/ui/DefaultComponentStyling.kt | 11 ++- .../jetbrains/jewel/ui/component/TabStrip.kt | 41 +++++--- .../org/jetbrains/jewel/ui/component/Tabs.kt | 34 ++++--- .../jewel/ui/component/styling/TabStyling.kt | 7 +- .../jetbrains/jewel/ui/theme/JewelTheme.kt | 12 ++- 9 files changed, 202 insertions(+), 49 deletions(-) diff --git a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/theme/IntUiBridge.kt b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/theme/IntUiBridge.kt index ce27c2f813..2db073b6c4 100644 --- a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/theme/IntUiBridge.kt +++ b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/theme/IntUiBridge.kt @@ -163,6 +163,7 @@ internal fun createBridgeComponentStyling( val textFieldStyle = readTextFieldStyle(textFieldTextStyle) val menuStyle = readMenuStyle() + val defaultTabStyle = readDefaultTabStyle() return DefaultComponentStyling( checkboxStyle = readCheckboxStyle(), @@ -170,7 +171,8 @@ internal fun createBridgeComponentStyling( circularProgressStyle = readCircularProgressStyle(theme.isDark), defaultButtonStyle = readDefaultButtonStyle(), defaultDropdownStyle = readDefaultDropdownStyle(menuStyle, dropdownTextStyle), - defaultTabStyle = readDefaultTabStyle(), + toolWindowTabStyle = readDefaultTabStyle(), + customTabStyle = defaultTabStyle, dividerStyle = readDividerStyle(), editorTabStyle = readEditorTabStyle(), groupHeaderStyle = readGroupHeaderStyle(), diff --git a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/theme/IntUiTheme.kt b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/theme/IntUiTheme.kt index 4fcecd1359..813523624f 100644 --- a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/theme/IntUiTheme.kt +++ b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/theme/IntUiTheme.kt @@ -116,7 +116,8 @@ public fun ComponentStyling.dark( circularProgressStyle = circularProgressStyle, defaultButtonStyle = defaultButtonStyle, defaultDropdownStyle = dropdownStyle, - defaultTabStyle = defaultTabStyle, + toolWindowTabStyle = defaultTabStyle, + customTabStyle = defaultTabStyle, dividerStyle = dividerStyle, editorTabStyle = editorTabStyle, groupHeaderStyle = groupHeaderStyle, @@ -168,7 +169,8 @@ public fun ComponentStyling.light( circularProgressStyle = circularProgressStyle, defaultButtonStyle = defaultButtonStyle, defaultDropdownStyle = dropdownStyle, - defaultTabStyle = defaultTabStyle, + toolWindowTabStyle = defaultTabStyle, + customTabStyle = defaultTabStyle, dividerStyle = dividerStyle, editorTabStyle = editorTabStyle, groupHeaderStyle = groupHeaderStyle, diff --git a/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/view/component/Tabs.kt b/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/view/component/Tabs.kt index 8fd2105ed6..3cda935e98 100644 --- a/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/view/component/Tabs.kt +++ b/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/view/component/Tabs.kt @@ -2,11 +2,16 @@ package org.jetbrains.jewel.samples.standalone.view.component +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -14,6 +19,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.graphics.Color import androidx.compose.ui.unit.dp import org.jetbrains.jewel.foundation.theme.JewelTheme import org.jetbrains.jewel.samples.standalone.StandaloneSampleIcons @@ -23,22 +29,100 @@ import org.jetbrains.jewel.ui.component.IconButton import org.jetbrains.jewel.ui.component.TabData import org.jetbrains.jewel.ui.component.TabStrip import org.jetbrains.jewel.ui.component.Text -import org.jetbrains.jewel.ui.theme.defaultTabStyle +import org.jetbrains.jewel.ui.theme.editorTabStyle import kotlin.math.max @Composable @View(title = "Tabs", position = 7) fun Tabs() { - Text("Default tabs", Modifier.fillMaxWidth()) - DefaultTabShowcase() + Text("Toolwindow tabs", Modifier.fillMaxWidth()) + ToolwindowTabShowcase() Spacer(Modifier.height(16.dp)) Text("Editor tabs", Modifier.fillMaxWidth()) EditorTabShowcase() + + Spacer(Modifier.height(16.dp)) + Text("Custom tabs", Modifier.fillMaxWidth()) + CustomTabShowcase() +} + +@Composable +fun CustomTabShowcase() { + var selectedTabIndex by remember { mutableStateOf(0) } + + var tabIds by remember { mutableStateOf((1..12).toList()) } + val maxId = remember(tabIds) { tabIds.maxOrNull() ?: 0 } + + val tabs = remember(tabIds, selectedTabIndex) { + tabIds.mapIndexed { index, id -> + TabData.Custom( + selected = index == selectedTabIndex, + content = { + Row( + horizontalArrangement = Arrangement.spacedBy(2.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + val textColor = when { + it.isHovered -> Color.Red + else -> Color.Unspecified + } + Text(text = "Custom tab $id") + Text(text = "($id)", color = textColor) + Box( + contentAlignment = Alignment.Center, + modifier = Modifier + .size(24.dp) + .background(color = Color.Yellow, shape = CircleShape) + .padding(2.dp), + ) { + Text(text = 'C'.toString()) + } + Box( + contentAlignment = Alignment.Center, + modifier = Modifier + .size(24.dp) + .background(color = Color.Green, shape = CircleShape) + .padding(2.dp), + ) { + Text(text = 'W'.toString()) + } + Box( + contentAlignment = Alignment.Center, + modifier = Modifier + .size(24.dp) + .background(color = Color.Magenta, shape = CircleShape) + .padding(2.dp), + ) { + Text(text = 'M'.toString()) + } + } + }, + onClose = { + tabIds = tabIds.toMutableList().apply { removeAt(index) } + if (selectedTabIndex >= index) { + val maxPossibleIndex = max(0, tabIds.lastIndex) + selectedTabIndex = (selectedTabIndex - 1) + .coerceIn(0..maxPossibleIndex) + } + }, + onClick = { selectedTabIndex = index }, + ) + } + } + + TabStripWithAddButton(tabs) { + val insertionIndex = (selectedTabIndex + 1).coerceIn(0..tabIds.size) + val nextTabId = maxId + 1 + + tabIds = tabIds.toMutableList() + .apply { add(insertionIndex, nextTabId) } + selectedTabIndex = insertionIndex + } } @Composable -private fun DefaultTabShowcase() { +private fun ToolwindowTabShowcase() { var selectedTabIndex by remember { mutableStateOf(0) } var tabIds by remember { mutableStateOf((1..12).toList()) } @@ -46,7 +130,7 @@ private fun DefaultTabShowcase() { val tabs = remember(tabIds, selectedTabIndex) { tabIds.mapIndexed { index, id -> - TabData.Default( + TabData.Default.ToolWindowTab( selected = index == selectedTabIndex, label = "Default tab $id", onClose = { @@ -81,7 +165,7 @@ private fun EditorTabShowcase() { val tabs = remember(tabIds, selectedTabIndex) { tabIds.mapIndexed { index, id -> - TabData.Editor( + TabData.Default.Editor( selected = index == selectedTabIndex, label = "Editor tab $id", onClose = { @@ -117,7 +201,7 @@ private fun TabStripWithAddButton( IconButton( onClick = onAddClick, - modifier = Modifier.size(JewelTheme.defaultTabStyle.metrics.tabHeight), + modifier = Modifier.size(JewelTheme.editorTabStyle.metrics.tabHeight), ) { Icon( resource = "expui/general/add.svg", diff --git a/ui/api/ui.api b/ui/api/ui.api index d26fbfe9d1..febaaddb31 100644 --- a/ui/api/ui.api +++ b/ui/api/ui.api @@ -25,14 +25,14 @@ public final class org/jetbrains/jewel/ui/ComponentStyling$DefaultImpls { public final class org/jetbrains/jewel/ui/DefaultComponentStyling : org/jetbrains/jewel/ui/ComponentStyling { public static final field $stable I - public fun (Lorg/jetbrains/jewel/ui/component/styling/CheckboxStyle;Lorg/jetbrains/jewel/ui/component/styling/ChipStyle;Lorg/jetbrains/jewel/ui/component/styling/CircularProgressStyle;Lorg/jetbrains/jewel/ui/component/styling/ButtonStyle;Lorg/jetbrains/jewel/ui/component/styling/DropdownStyle;Lorg/jetbrains/jewel/ui/component/styling/TabStyle;Lorg/jetbrains/jewel/ui/component/styling/DividerStyle;Lorg/jetbrains/jewel/ui/component/styling/TabStyle;Lorg/jetbrains/jewel/ui/component/styling/GroupHeaderStyle;Lorg/jetbrains/jewel/ui/component/styling/HorizontalProgressBarStyle;Lorg/jetbrains/jewel/ui/component/styling/IconButtonStyle;Lorg/jetbrains/jewel/ui/component/styling/LazyTreeStyle;Lorg/jetbrains/jewel/ui/component/styling/LinkStyle;Lorg/jetbrains/jewel/ui/component/styling/MenuStyle;Lorg/jetbrains/jewel/ui/component/styling/ButtonStyle;Lorg/jetbrains/jewel/ui/component/styling/RadioButtonStyle;Lorg/jetbrains/jewel/ui/component/styling/ScrollbarStyle;Lorg/jetbrains/jewel/ui/component/styling/SliderStyle;Lorg/jetbrains/jewel/ui/component/styling/TextAreaStyle;Lorg/jetbrains/jewel/ui/component/styling/TextFieldStyle;Lorg/jetbrains/jewel/ui/component/styling/TooltipStyle;Lorg/jetbrains/jewel/ui/component/styling/DropdownStyle;)V + public fun (Lorg/jetbrains/jewel/ui/component/styling/CheckboxStyle;Lorg/jetbrains/jewel/ui/component/styling/ChipStyle;Lorg/jetbrains/jewel/ui/component/styling/CircularProgressStyle;Lorg/jetbrains/jewel/ui/component/styling/ButtonStyle;Lorg/jetbrains/jewel/ui/component/styling/DropdownStyle;Lorg/jetbrains/jewel/ui/component/styling/TabStyle;Lorg/jetbrains/jewel/ui/component/styling/TabStyle;Lorg/jetbrains/jewel/ui/component/styling/TabStyle;Lorg/jetbrains/jewel/ui/component/styling/DividerStyle;Lorg/jetbrains/jewel/ui/component/styling/GroupHeaderStyle;Lorg/jetbrains/jewel/ui/component/styling/HorizontalProgressBarStyle;Lorg/jetbrains/jewel/ui/component/styling/IconButtonStyle;Lorg/jetbrains/jewel/ui/component/styling/LazyTreeStyle;Lorg/jetbrains/jewel/ui/component/styling/LinkStyle;Lorg/jetbrains/jewel/ui/component/styling/MenuStyle;Lorg/jetbrains/jewel/ui/component/styling/ButtonStyle;Lorg/jetbrains/jewel/ui/component/styling/RadioButtonStyle;Lorg/jetbrains/jewel/ui/component/styling/ScrollbarStyle;Lorg/jetbrains/jewel/ui/component/styling/SliderStyle;Lorg/jetbrains/jewel/ui/component/styling/TextAreaStyle;Lorg/jetbrains/jewel/ui/component/styling/TextFieldStyle;Lorg/jetbrains/jewel/ui/component/styling/TooltipStyle;Lorg/jetbrains/jewel/ui/component/styling/DropdownStyle;)V public fun equals (Ljava/lang/Object;)Z public final fun getCheckboxStyle ()Lorg/jetbrains/jewel/ui/component/styling/CheckboxStyle; public final fun getChipStyle ()Lorg/jetbrains/jewel/ui/component/styling/ChipStyle; public final fun getCircularProgressStyle ()Lorg/jetbrains/jewel/ui/component/styling/CircularProgressStyle; + public final fun getCustomTabStyle ()Lorg/jetbrains/jewel/ui/component/styling/TabStyle; public final fun getDefaultButtonStyle ()Lorg/jetbrains/jewel/ui/component/styling/ButtonStyle; public final fun getDefaultDropdownStyle ()Lorg/jetbrains/jewel/ui/component/styling/DropdownStyle; - public final fun getDefaultTabStyle ()Lorg/jetbrains/jewel/ui/component/styling/TabStyle; public final fun getDividerStyle ()Lorg/jetbrains/jewel/ui/component/styling/DividerStyle; public final fun getEditorTabStyle ()Lorg/jetbrains/jewel/ui/component/styling/TabStyle; public final fun getGroupHeaderStyle ()Lorg/jetbrains/jewel/ui/component/styling/GroupHeaderStyle; @@ -47,13 +47,16 @@ public final class org/jetbrains/jewel/ui/DefaultComponentStyling : org/jetbrain public final fun getSliderStyle ()Lorg/jetbrains/jewel/ui/component/styling/SliderStyle; public final fun getTextAreaStyle ()Lorg/jetbrains/jewel/ui/component/styling/TextAreaStyle; public final fun getTextFieldStyle ()Lorg/jetbrains/jewel/ui/component/styling/TextFieldStyle; + public final fun getToolWindowTabStyle ()Lorg/jetbrains/jewel/ui/component/styling/TabStyle; public final fun getTooltipStyle ()Lorg/jetbrains/jewel/ui/component/styling/TooltipStyle; public final fun getUndecoratedDropdownStyle ()Lorg/jetbrains/jewel/ui/component/styling/DropdownStyle; public fun hashCode ()I + public synthetic fun provide (Lkotlin/jvm/functions/Function0;)Lorg/jetbrains/jewel/ui/ComponentStyling; public fun provide (Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/jewel/ui/ComponentStyling; public fun provide ([Landroidx/compose/runtime/ProvidedValue;)Lorg/jetbrains/jewel/ui/ComponentStyling; public fun styles (Landroidx/compose/runtime/Composer;I)[Landroidx/compose/runtime/ProvidedValue; public fun toString ()Ljava/lang/String; + public synthetic fun with (Lkotlin/jvm/functions/Function0;)Lorg/jetbrains/jewel/ui/ComponentStyling; public fun with (Lkotlin/jvm/functions/Function2;)Lorg/jetbrains/jewel/ui/ComponentStyling; public fun with (Lorg/jetbrains/jewel/ui/ComponentStyling;)Lorg/jetbrains/jewel/ui/ComponentStyling; } @@ -598,13 +601,32 @@ public abstract class org/jetbrains/jewel/ui/component/TabData { public static final field $stable I public abstract fun getClosable ()Z public abstract fun getIcon ()Landroidx/compose/ui/graphics/painter/Painter; - public abstract fun getLabel ()Ljava/lang/String; public abstract fun getOnClick ()Lkotlin/jvm/functions/Function0; public abstract fun getOnClose ()Lkotlin/jvm/functions/Function0; public abstract fun getSelected ()Z } -public final class org/jetbrains/jewel/ui/component/TabData$Default : org/jetbrains/jewel/ui/component/TabData { +public final class org/jetbrains/jewel/ui/component/TabData$Custom : org/jetbrains/jewel/ui/component/TabData { + public static final field $stable I + public fun (ZLkotlin/jvm/functions/Function3;Landroidx/compose/ui/graphics/painter/Painter;ZLkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;)V + public synthetic fun (ZLkotlin/jvm/functions/Function3;Landroidx/compose/ui/graphics/painter/Painter;ZLkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun equals (Ljava/lang/Object;)Z + public fun getClosable ()Z + public final fun getContent ()Lkotlin/jvm/functions/Function3; + public fun getIcon ()Landroidx/compose/ui/graphics/painter/Painter; + public fun getOnClick ()Lkotlin/jvm/functions/Function0; + public fun getOnClose ()Lkotlin/jvm/functions/Function0; + public fun getSelected ()Z + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public abstract class org/jetbrains/jewel/ui/component/TabData$Default : org/jetbrains/jewel/ui/component/TabData { + public static final field $stable I + public abstract fun getLabel ()Ljava/lang/String; +} + +public final class org/jetbrains/jewel/ui/component/TabData$Default$Editor : org/jetbrains/jewel/ui/component/TabData$Default { public static final field $stable I public fun (ZLjava/lang/String;Landroidx/compose/ui/graphics/painter/Painter;ZLkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;)V public synthetic fun (ZLjava/lang/String;Landroidx/compose/ui/graphics/painter/Painter;ZLkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;ILkotlin/jvm/internal/DefaultConstructorMarker;)V @@ -619,7 +641,7 @@ public final class org/jetbrains/jewel/ui/component/TabData$Default : org/jetbra public fun toString ()Ljava/lang/String; } -public final class org/jetbrains/jewel/ui/component/TabData$Editor : org/jetbrains/jewel/ui/component/TabData { +public final class org/jetbrains/jewel/ui/component/TabData$Default$ToolWindowTab : org/jetbrains/jewel/ui/component/TabData$Default { public static final field $stable I public fun (ZLjava/lang/String;Landroidx/compose/ui/graphics/painter/Painter;ZLkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;)V public synthetic fun (ZLjava/lang/String;Landroidx/compose/ui/graphics/painter/Painter;ZLkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function0;ILkotlin/jvm/internal/DefaultConstructorMarker;)V @@ -1862,8 +1884,9 @@ public final class org/jetbrains/jewel/ui/component/styling/TabStyle$Companion { } public final class org/jetbrains/jewel/ui/component/styling/TabStylingKt { - public static final fun getLocalDefaultTabStyle ()Landroidx/compose/runtime/ProvidableCompositionLocal; + public static final fun getLocalCustomTabStyle ()Landroidx/compose/runtime/ProvidableCompositionLocal; public static final fun getLocalEditorTabStyle ()Landroidx/compose/runtime/ProvidableCompositionLocal; + public static final fun getLocalToolWindowTabStyle ()Landroidx/compose/runtime/ProvidableCompositionLocal; } public final class org/jetbrains/jewel/ui/component/styling/TextAreaColors : org/jetbrains/jewel/ui/component/styling/InputFieldColors { @@ -2295,8 +2318,8 @@ public final class org/jetbrains/jewel/ui/theme/JewelThemeKt { public static final fun getChipStyle (Lorg/jetbrains/jewel/foundation/theme/JewelTheme$Companion;Landroidx/compose/runtime/Composer;I)Lorg/jetbrains/jewel/ui/component/styling/ChipStyle; public static final fun getCircularProgressStyle (Lorg/jetbrains/jewel/foundation/theme/JewelTheme$Companion;Landroidx/compose/runtime/Composer;I)Lorg/jetbrains/jewel/ui/component/styling/CircularProgressStyle; public static final fun getColorPalette (Lorg/jetbrains/jewel/foundation/theme/JewelTheme$Companion;Landroidx/compose/runtime/Composer;I)Lorg/jetbrains/jewel/foundation/theme/ThemeColorPalette; + public static final fun getCustomTabStyle (Lorg/jetbrains/jewel/foundation/theme/JewelTheme$Companion;Landroidx/compose/runtime/Composer;I)Lorg/jetbrains/jewel/ui/component/styling/TabStyle; public static final fun getDefaultButtonStyle (Lorg/jetbrains/jewel/foundation/theme/JewelTheme$Companion;Landroidx/compose/runtime/Composer;I)Lorg/jetbrains/jewel/ui/component/styling/ButtonStyle; - public static final fun getDefaultTabStyle (Lorg/jetbrains/jewel/foundation/theme/JewelTheme$Companion;Landroidx/compose/runtime/Composer;I)Lorg/jetbrains/jewel/ui/component/styling/TabStyle; public static final fun getDividerStyle (Lorg/jetbrains/jewel/foundation/theme/JewelTheme$Companion;Landroidx/compose/runtime/Composer;I)Lorg/jetbrains/jewel/ui/component/styling/DividerStyle; public static final fun getDropdownStyle (Lorg/jetbrains/jewel/foundation/theme/JewelTheme$Companion;Landroidx/compose/runtime/Composer;I)Lorg/jetbrains/jewel/ui/component/styling/DropdownStyle; public static final fun getEditorTabStyle (Lorg/jetbrains/jewel/foundation/theme/JewelTheme$Companion;Landroidx/compose/runtime/Composer;I)Lorg/jetbrains/jewel/ui/component/styling/TabStyle; @@ -2312,6 +2335,7 @@ public final class org/jetbrains/jewel/ui/theme/JewelThemeKt { public static final fun getSliderStyle (Lorg/jetbrains/jewel/foundation/theme/JewelTheme$Companion;Landroidx/compose/runtime/Composer;I)Lorg/jetbrains/jewel/ui/component/styling/SliderStyle; public static final fun getTextAreaStyle (Lorg/jetbrains/jewel/foundation/theme/JewelTheme$Companion;Landroidx/compose/runtime/Composer;I)Lorg/jetbrains/jewel/ui/component/styling/TextAreaStyle; public static final fun getTextFieldStyle (Lorg/jetbrains/jewel/foundation/theme/JewelTheme$Companion;Landroidx/compose/runtime/Composer;I)Lorg/jetbrains/jewel/ui/component/styling/TextFieldStyle; + public static final fun getToolWindowTabStyle (Lorg/jetbrains/jewel/foundation/theme/JewelTheme$Companion;Landroidx/compose/runtime/Composer;I)Lorg/jetbrains/jewel/ui/component/styling/TabStyle; public static final fun getTooltipStyle (Lorg/jetbrains/jewel/foundation/theme/JewelTheme$Companion;Landroidx/compose/runtime/Composer;I)Lorg/jetbrains/jewel/ui/component/styling/TooltipStyle; public static final fun getTreeStyle (Lorg/jetbrains/jewel/foundation/theme/JewelTheme$Companion;Landroidx/compose/runtime/Composer;I)Lorg/jetbrains/jewel/ui/component/styling/LazyTreeStyle; } diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/DefaultComponentStyling.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/DefaultComponentStyling.kt index 55adc5e05c..8cafe15e0e 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/DefaultComponentStyling.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/DefaultComponentStyling.kt @@ -20,9 +20,9 @@ import org.jetbrains.jewel.ui.component.styling.LinkStyle import org.jetbrains.jewel.ui.component.styling.LocalCheckboxStyle import org.jetbrains.jewel.ui.component.styling.LocalChipStyle import org.jetbrains.jewel.ui.component.styling.LocalCircularProgressStyle +import org.jetbrains.jewel.ui.component.styling.LocalCustomTabStyle import org.jetbrains.jewel.ui.component.styling.LocalDefaultButtonStyle import org.jetbrains.jewel.ui.component.styling.LocalDefaultDropdownStyle -import org.jetbrains.jewel.ui.component.styling.LocalDefaultTabStyle import org.jetbrains.jewel.ui.component.styling.LocalDividerStyle import org.jetbrains.jewel.ui.component.styling.LocalEditorTabStyle import org.jetbrains.jewel.ui.component.styling.LocalGroupHeaderStyle @@ -37,6 +37,7 @@ import org.jetbrains.jewel.ui.component.styling.LocalScrollbarStyle import org.jetbrains.jewel.ui.component.styling.LocalSliderStyle import org.jetbrains.jewel.ui.component.styling.LocalTextAreaStyle import org.jetbrains.jewel.ui.component.styling.LocalTextFieldStyle +import org.jetbrains.jewel.ui.component.styling.LocalToolWindowTabStyle import org.jetbrains.jewel.ui.component.styling.LocalTooltipStyle import org.jetbrains.jewel.ui.component.styling.LocalUndecoratedDropdownStyle import org.jetbrains.jewel.ui.component.styling.MenuStyle @@ -56,9 +57,10 @@ public class DefaultComponentStyling( public val circularProgressStyle: CircularProgressStyle, public val defaultButtonStyle: ButtonStyle, public val defaultDropdownStyle: DropdownStyle, - public val defaultTabStyle: TabStyle, - public val dividerStyle: DividerStyle, + public val toolWindowTabStyle: TabStyle, public val editorTabStyle: TabStyle, + public val customTabStyle: TabStyle, + public val dividerStyle: DividerStyle, public val groupHeaderStyle: GroupHeaderStyle, public val horizontalProgressBarStyle: HorizontalProgressBarStyle, public val iconButtonStyle: IconButtonStyle, @@ -84,7 +86,8 @@ public class DefaultComponentStyling( LocalContextMenuRepresentation provides ContextMenuRepresentation, LocalDefaultButtonStyle provides defaultButtonStyle, LocalDefaultDropdownStyle provides defaultDropdownStyle, - LocalDefaultTabStyle provides defaultTabStyle, + LocalToolWindowTabStyle provides toolWindowTabStyle, + LocalCustomTabStyle provides toolWindowTabStyle, LocalDividerStyle provides dividerStyle, LocalEditorTabStyle provides editorTabStyle, LocalGroupHeaderStyle provides groupHeaderStyle, diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/TabStrip.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/TabStrip.kt index 5b37353139..6306d59ac6 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/TabStrip.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/TabStrip.kt @@ -30,6 +30,7 @@ import org.jetbrains.jewel.foundation.GenerateDataFunctions import org.jetbrains.jewel.foundation.modifier.onHover import org.jetbrains.jewel.foundation.state.CommonStateBitMask import org.jetbrains.jewel.foundation.state.FocusableComponentState +import org.jetbrains.jewel.foundation.state.InteractiveComponentState @Composable public fun TabStrip( @@ -81,28 +82,44 @@ public fun TabStrip( public sealed class TabData { public abstract val selected: Boolean - public abstract val label: String public abstract val icon: Painter? public abstract val closable: Boolean public abstract val onClose: () -> Unit public abstract val onClick: () -> Unit @Immutable - @GenerateDataFunctions - public class Default( - override val selected: Boolean, - override val label: String, - override val icon: Painter? = null, - override val closable: Boolean = true, - override val onClose: () -> Unit = {}, - override val onClick: () -> Unit = {}, - ) : TabData() + public sealed class Default : TabData() { + + public abstract val label: String + + @Immutable + @GenerateDataFunctions + public class ToolWindowTab( + override val selected: Boolean, + override val label: String, + override val icon: Painter? = null, + override val closable: Boolean = true, + override val onClose: () -> Unit = {}, + override val onClick: () -> Unit = {}, + ) : Default() + + @Immutable + @GenerateDataFunctions + public class Editor( + override val selected: Boolean, + override val label: String, + override val icon: Painter? = null, + override val closable: Boolean = true, + override val onClose: () -> Unit = {}, + override val onClick: () -> Unit = {}, + ) : Default() + } @Immutable @GenerateDataFunctions - public class Editor( + public class Custom( override val selected: Boolean, - override val label: String, + public val content: @Composable (tabState: InteractiveComponentState) -> Unit, override val icon: Painter? = null, override val closable: Boolean = true, override val onClose: () -> Unit = {}, diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Tabs.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Tabs.kt index 41df851fea..fb50dd9b33 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Tabs.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Tabs.kt @@ -45,8 +45,9 @@ import org.jetbrains.jewel.foundation.theme.JewelTheme import org.jetbrains.jewel.foundation.theme.LocalContentColor import org.jetbrains.jewel.ui.NoIndication import org.jetbrains.jewel.ui.painter.hints.Stateful -import org.jetbrains.jewel.ui.theme.defaultTabStyle +import org.jetbrains.jewel.ui.theme.customTabStyle import org.jetbrains.jewel.ui.theme.editorTabStyle +import org.jetbrains.jewel.ui.theme.toolWindowTabStyle @Composable internal fun TabImpl( @@ -57,8 +58,9 @@ internal fun TabImpl( ) { val tabStyle = when (tabData) { - is TabData.Default -> JewelTheme.defaultTabStyle - is TabData.Editor -> JewelTheme.editorTabStyle + is TabData.Default.ToolWindowTab -> JewelTheme.toolWindowTabStyle + is TabData.Default.Editor -> JewelTheme.editorTabStyle + is TabData.Custom -> JewelTheme.customTabStyle } var tabState by remember { @@ -127,17 +129,25 @@ internal fun TabImpl( Image(modifier = Modifier.alpha(iconAlpha), painter = icon, contentDescription = null) } - Text( - modifier = Modifier.alpha(labelAlpha), - text = tabData.label, - color = tabStyle.colors.contentFor(tabState).value, - ) + when (tabData) { + is TabData.Custom -> { + tabData.content(tabState) + } + + is TabData.Default -> { + Text( + modifier = Modifier.alpha(labelAlpha), + text = tabData.label, + color = tabStyle.colors.contentFor(tabState).value, + ) + } + } + val showCloseIcon = when (tabData) { - is TabData.Default -> tabData.closable - is TabData.Editor -> tabData.closable && (tabState.isHovered || tabState.isSelected) + is TabData.Default.ToolWindowTab -> tabData.closable + is TabData.Default.Editor, is TabData.Custom -> tabData.closable && (tabState.isHovered || tabState.isSelected) } - if (showCloseIcon) { val closeActionInteractionSource = remember { MutableInteractionSource() } LaunchedEffect(closeActionInteractionSource) { @@ -166,7 +176,7 @@ internal fun TabImpl( ) .size(16.dp), painter = closePainter, - contentDescription = "Close tab ${tabData.label}", + contentDescription = "Close tab", ) } else if (tabData.closable) { Spacer(Modifier.size(16.dp)) diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/styling/TabStyling.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/styling/TabStyling.kt index 67a5a8d9b3..dcdf99b2ad 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/styling/TabStyling.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/styling/TabStyling.kt @@ -180,7 +180,7 @@ private fun TabState.chooseValueIgnoreCompat( else -> normal } -public val LocalDefaultTabStyle: ProvidableCompositionLocal = +public val LocalToolWindowTabStyle: ProvidableCompositionLocal = staticCompositionLocalOf { error("No LocalTabStyle provided. Have you forgotten the theme?") } @@ -189,3 +189,8 @@ public val LocalEditorTabStyle: ProvidableCompositionLocal = staticCompositionLocalOf { error("No LocalTabStyle provided. Have you forgotten the theme?") } + +public val LocalCustomTabStyle: ProvidableCompositionLocal = + staticCompositionLocalOf { + error("No LocalTabStyle provided. Have you forgotten the theme?") + } diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/theme/JewelTheme.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/theme/JewelTheme.kt index 4b3f65997f..e207fbcac6 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/theme/JewelTheme.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/theme/JewelTheme.kt @@ -26,9 +26,9 @@ import org.jetbrains.jewel.ui.component.styling.LinkStyle import org.jetbrains.jewel.ui.component.styling.LocalCheckboxStyle import org.jetbrains.jewel.ui.component.styling.LocalChipStyle import org.jetbrains.jewel.ui.component.styling.LocalCircularProgressStyle +import org.jetbrains.jewel.ui.component.styling.LocalCustomTabStyle import org.jetbrains.jewel.ui.component.styling.LocalDefaultButtonStyle import org.jetbrains.jewel.ui.component.styling.LocalDefaultDropdownStyle -import org.jetbrains.jewel.ui.component.styling.LocalDefaultTabStyle import org.jetbrains.jewel.ui.component.styling.LocalDividerStyle import org.jetbrains.jewel.ui.component.styling.LocalEditorTabStyle import org.jetbrains.jewel.ui.component.styling.LocalGroupHeaderStyle @@ -43,6 +43,7 @@ import org.jetbrains.jewel.ui.component.styling.LocalScrollbarStyle import org.jetbrains.jewel.ui.component.styling.LocalSliderStyle import org.jetbrains.jewel.ui.component.styling.LocalTextAreaStyle import org.jetbrains.jewel.ui.component.styling.LocalTextFieldStyle +import org.jetbrains.jewel.ui.component.styling.LocalToolWindowTabStyle import org.jetbrains.jewel.ui.component.styling.LocalTooltipStyle import org.jetbrains.jewel.ui.component.styling.MenuStyle import org.jetbrains.jewel.ui.component.styling.RadioButtonStyle @@ -142,16 +143,21 @@ public val JewelTheme.Companion.treeStyle: LazyTreeStyle @ReadOnlyComposable get() = LocalLazyTreeStyle.current -public val JewelTheme.Companion.defaultTabStyle: TabStyle +public val JewelTheme.Companion.toolWindowTabStyle: TabStyle @Composable @ReadOnlyComposable - get() = LocalDefaultTabStyle.current + get() = LocalToolWindowTabStyle.current public val JewelTheme.Companion.editorTabStyle: TabStyle @Composable @ReadOnlyComposable get() = LocalEditorTabStyle.current +public val JewelTheme.Companion.customTabStyle: TabStyle + @Composable + @ReadOnlyComposable + get() = LocalCustomTabStyle.current + public val JewelTheme.Companion.circularProgressStyle: CircularProgressStyle @Composable @ReadOnlyComposable