Create Slider component (#270)

Introduce Slider component following general IntUI style
GitOrigin-RevId: 58b0402c3576be8fd2fe756626f661dde569c2b8
This commit is contained in:
Sebastiano Poggi
2023-12-12 00:26:33 -08:00
committed by intellij-monorepo-bot
parent c616b98475
commit fb31ac7ec1
14 changed files with 1250 additions and 10 deletions

View File

@@ -73,6 +73,15 @@ public final class org/jetbrains/jewel/bridge/theme/BridgeGlobalMetricsKt {
public static final fun readFromLaF (Lorg/jetbrains/jewel/foundation/GlobalMetrics$Companion;)Lorg/jetbrains/jewel/foundation/GlobalMetrics;
}
public final class org/jetbrains/jewel/bridge/theme/BridgeSliderStylingKt {
public static final fun dark-7HESe_I (Lorg/jetbrains/jewel/ui/component/styling/SliderColors$Companion;JJJJJJJJJJJJJJJ)Lorg/jetbrains/jewel/ui/component/styling/SliderColors;
public static synthetic fun dark-7HESe_I$default (Lorg/jetbrains/jewel/ui/component/styling/SliderColors$Companion;JJJJJJJJJJJJJJJILjava/lang/Object;)Lorg/jetbrains/jewel/ui/component/styling/SliderColors;
public static final fun defaults-IDSuZpE (Lorg/jetbrains/jewel/ui/component/styling/SliderMetrics$Companion;FJFFFF)Lorg/jetbrains/jewel/ui/component/styling/SliderMetrics;
public static synthetic fun defaults-IDSuZpE$default (Lorg/jetbrains/jewel/ui/component/styling/SliderMetrics$Companion;FJFFFFILjava/lang/Object;)Lorg/jetbrains/jewel/ui/component/styling/SliderMetrics;
public static final fun light-7HESe_I (Lorg/jetbrains/jewel/ui/component/styling/SliderColors$Companion;JJJJJJJJJJJJJJJ)Lorg/jetbrains/jewel/ui/component/styling/SliderColors;
public static synthetic fun light-7HESe_I$default (Lorg/jetbrains/jewel/ui/component/styling/SliderColors$Companion;JJJJJJJJJJJJJJJILjava/lang/Object;)Lorg/jetbrains/jewel/ui/component/styling/SliderColors;
}
public final class org/jetbrains/jewel/bridge/theme/BridgeThemeColorPaletteKt {
public static final fun getWindowsPopupBorder (Lorg/jetbrains/jewel/foundation/theme/ThemeColorPalette;)Landroidx/compose/ui/graphics/Color;
public static final fun readFromLaF (Lorg/jetbrains/jewel/foundation/theme/ThemeColorPalette$Companion;)Lorg/jetbrains/jewel/foundation/theme/ThemeColorPalette;

View File

@@ -0,0 +1,88 @@
package org.jetbrains.jewel.bridge.theme
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.takeOrElse
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
import org.jetbrains.jewel.bridge.retrieveColorOrUnspecified
import org.jetbrains.jewel.ui.component.styling.SliderColors
import org.jetbrains.jewel.ui.component.styling.SliderMetrics
public fun SliderColors.Companion.light(
track: Color = retrieveColorOrUnspecified("ColorPalette.Grey10").takeOrElse { Color(0xFFD3D5DB) },
trackFilled: Color = retrieveColorOrUnspecified("ColorPalette.Blue6").takeOrElse { Color(0xFF588CF3) },
trackDisabled: Color = retrieveColorOrUnspecified("ColorPalette.Grey12").takeOrElse { Color(0xFFEBECF0) },
trackFilledDisabled: Color = retrieveColorOrUnspecified("ColorPalette.Grey11").takeOrElse { Color(0xFFDFE1E5) },
stepMarker: Color = track,
thumbFill: Color = retrieveColorOrUnspecified("ColorPalette.Grey14").takeOrElse { Color(0xFFFFFFFF) },
thumbFillDisabled: Color = thumbFill,
thumbFillFocused: Color = thumbFill,
thumbFillPressed: Color = thumbFill,
thumbFillHovered: Color = thumbFill,
thumbBorder: Color = retrieveColorOrUnspecified("ColorPalette.Grey8").takeOrElse { Color(0xFFA8ADBD) },
thumbBorderFocused: Color = retrieveColorOrUnspecified("ColorPalette.Blue4").takeOrElse { Color(0xFF3574F0) },
thumbBorderDisabled: Color = retrieveColorOrUnspecified("ColorPalette.Grey11").takeOrElse { Color(0xFFDFE1E5) },
thumbBorderPressed: Color = retrieveColorOrUnspecified("ColorPalette.Grey7").takeOrElse { Color(0xFF818594) },
thumbBorderHovered: Color = retrieveColorOrUnspecified("ColorPalette.Grey9").takeOrElse { Color(0xFFC9CCD6) },
): SliderColors = SliderColors(
track,
trackFilled,
trackDisabled,
trackFilledDisabled,
stepMarker,
thumbFill,
thumbFillDisabled,
thumbFillFocused,
thumbFillPressed,
thumbFillHovered,
thumbBorder,
thumbBorderFocused,
thumbBorderDisabled,
thumbBorderPressed,
thumbBorderHovered,
)
public fun SliderColors.Companion.dark(
track: Color = retrieveColorOrUnspecified("ColorPalette.Grey4").takeOrElse { Color(0xFF43454A) },
trackFilled: Color = retrieveColorOrUnspecified("ColorPalette.Blue7").takeOrElse { Color(0xFF467FF2) },
trackDisabled: Color = retrieveColorOrUnspecified("ColorPalette.Grey3").takeOrElse { Color(0xFF393B40) },
trackFilledDisabled: Color = retrieveColorOrUnspecified("ColorPalette.Grey4").takeOrElse { Color(0xFF43454A) },
stepMarker: Color = track,
thumbFill: Color = retrieveColorOrUnspecified("ColorPalette.Grey2").takeOrElse { Color(0xFF2B2D30) },
thumbFillDisabled: Color = retrieveColorOrUnspecified("ColorPalette.Grey3").takeOrElse { Color(0xFF393B40) },
thumbFillFocused: Color = thumbFill,
thumbFillPressed: Color = thumbFill,
thumbFillHovered: Color = thumbFill,
thumbBorder: Color = retrieveColorOrUnspecified("ColorPalette.Grey7").takeOrElse { Color(0xFF6F737A) },
thumbBorderFocused: Color = retrieveColorOrUnspecified("ColorPalette.Blue6").takeOrElse { Color(0xFF3574F0) },
thumbBorderDisabled: Color = retrieveColorOrUnspecified("ColorPalette.Grey5").takeOrElse { Color(0xFF4E5157) },
thumbBorderPressed: Color = retrieveColorOrUnspecified("ColorPalette.Grey8").takeOrElse { Color(0xFF868A91) },
thumbBorderHovered: Color = retrieveColorOrUnspecified("ColorPalette.Grey9").takeOrElse { Color(0xFF9DA0A8) },
): SliderColors = SliderColors(
track,
trackFilled,
trackDisabled,
trackFilledDisabled,
stepMarker,
thumbFill,
thumbFillDisabled,
thumbFillFocused,
thumbFillPressed,
thumbFillHovered,
thumbBorder,
thumbBorderFocused,
thumbBorderDisabled,
thumbBorderPressed,
thumbBorderHovered,
)
public fun SliderMetrics.Companion.defaults(
trackHeight: Dp = 4.dp,
thumbSize: DpSize = DpSize(14.dp, 14.dp),
thumbBorderWidth: Dp = 1.dp,
stepLineHeight: Dp = 8.dp,
stepLineWidth: Dp = 1.dp,
trackToStepSpacing: Dp = thumbSize.height / 2 + 4.dp,
): SliderMetrics =
SliderMetrics(trackHeight, thumbSize, thumbBorderWidth, stepLineHeight, stepLineWidth, trackToStepSpacing)

View File

@@ -1,6 +1,7 @@
package org.jetbrains.jewel.bridge.theme
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.CornerSize
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
@@ -87,6 +88,9 @@ import org.jetbrains.jewel.ui.component.styling.RadioButtonStyle
import org.jetbrains.jewel.ui.component.styling.ScrollbarColors
import org.jetbrains.jewel.ui.component.styling.ScrollbarMetrics
import org.jetbrains.jewel.ui.component.styling.ScrollbarStyle
import org.jetbrains.jewel.ui.component.styling.SliderColors
import org.jetbrains.jewel.ui.component.styling.SliderMetrics
import org.jetbrains.jewel.ui.component.styling.SliderStyle
import org.jetbrains.jewel.ui.component.styling.SubmenuMetrics
import org.jetbrains.jewel.ui.component.styling.TabColors
import org.jetbrains.jewel.ui.component.styling.TabContentAlpha
@@ -178,6 +182,7 @@ internal fun createBridgeComponentStyling(
outlinedButtonStyle = readOutlinedButtonStyle(),
radioButtonStyle = readRadioButtonStyle(),
scrollbarStyle = readScrollbarStyle(theme.isDark),
sliderStyle = readSliderStyle(theme.isDark),
textAreaStyle = readTextAreaStyle(textAreaTextStyle, textFieldStyle.metrics),
textFieldStyle = textFieldStyle,
tooltipStyle = readTooltipStyle(),
@@ -627,6 +632,14 @@ private fun readScrollbarStyle(isDark: Boolean) =
hoverDuration = 300.milliseconds,
)
private fun readSliderStyle(dark: Boolean): SliderStyle {
// There are no values for sliders in IntUi, so we're essentially reusing the
// standalone colors logic, reading the palette values (and falling back to
// hardcoded defaults).
val colors = if (dark) SliderColors.dark() else SliderColors.light()
return SliderStyle(colors, SliderMetrics.defaults(), CircleShape)
}
private fun readTextAreaStyle(textStyle: TextStyle, metrics: TextFieldMetrics): TextAreaStyle {
val normalBackground = retrieveColorOrUnspecified("TextArea.background")
val normalContent = retrieveColorOrUnspecified("TextArea.foreground")

View File

@@ -254,6 +254,14 @@ public final class org/jetbrains/jewel/intui/standalone/styling/IntUiScrollbarSt
public static final fun light-RIQooxk (Lorg/jetbrains/jewel/ui/component/styling/ScrollbarColors$Companion;JJLandroidx/compose/runtime/Composer;II)Lorg/jetbrains/jewel/ui/component/styling/ScrollbarColors;
}
public final class org/jetbrains/jewel/intui/standalone/styling/IntUiSliderStylingKt {
public static final fun dark (Lorg/jetbrains/jewel/ui/component/styling/SliderStyle$Companion;Lorg/jetbrains/jewel/ui/component/styling/SliderColors;Lorg/jetbrains/jewel/ui/component/styling/SliderMetrics;Landroidx/compose/ui/graphics/Shape;Landroidx/compose/runtime/Composer;II)Lorg/jetbrains/jewel/ui/component/styling/SliderStyle;
public static final fun dark-8v1krLo (Lorg/jetbrains/jewel/ui/component/styling/SliderColors$Companion;JJJJJJJJJJJJJJJLandroidx/compose/runtime/Composer;III)Lorg/jetbrains/jewel/ui/component/styling/SliderColors;
public static final fun defaults-nDjVmYc (Lorg/jetbrains/jewel/ui/component/styling/SliderMetrics$Companion;FJFFFFLandroidx/compose/runtime/Composer;II)Lorg/jetbrains/jewel/ui/component/styling/SliderMetrics;
public static final fun light (Lorg/jetbrains/jewel/ui/component/styling/SliderStyle$Companion;Lorg/jetbrains/jewel/ui/component/styling/SliderColors;Lorg/jetbrains/jewel/ui/component/styling/SliderMetrics;Landroidx/compose/ui/graphics/Shape;Landroidx/compose/runtime/Composer;II)Lorg/jetbrains/jewel/ui/component/styling/SliderStyle;
public static final fun light-8v1krLo (Lorg/jetbrains/jewel/ui/component/styling/SliderColors$Companion;JJJJJJJJJJJJJJJLandroidx/compose/runtime/Composer;III)Lorg/jetbrains/jewel/ui/component/styling/SliderColors;
}
public final class org/jetbrains/jewel/intui/standalone/styling/IntUiTabStylingKt {
public static final fun default (Lorg/jetbrains/jewel/ui/component/styling/TabContentAlpha$Companion;FFFFFFFFFF)Lorg/jetbrains/jewel/ui/component/styling/TabContentAlpha;
public static synthetic fun default$default (Lorg/jetbrains/jewel/ui/component/styling/TabContentAlpha$Companion;FFFFFFFFFFILjava/lang/Object;)Lorg/jetbrains/jewel/ui/component/styling/TabContentAlpha;
@@ -325,11 +333,11 @@ public final class org/jetbrains/jewel/intui/standalone/theme/IntUiGlobalMetrics
public final class org/jetbrains/jewel/intui/standalone/theme/IntUiThemeKt {
public static final fun IntUiTheme (Lorg/jetbrains/jewel/foundation/theme/ThemeDefinition;Lorg/jetbrains/jewel/ui/ComponentStyling;ZLkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;II)V
public static final fun IntUiTheme (ZZLkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;II)V
public static final fun dark (Lorg/jetbrains/jewel/ui/ComponentStyling;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/TabStyle;Lorg/jetbrains/jewel/ui/component/styling/DividerStyle;Lorg/jetbrains/jewel/ui/component/styling/DropdownStyle;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/TextAreaStyle;Lorg/jetbrains/jewel/ui/component/styling/TextFieldStyle;Lorg/jetbrains/jewel/ui/component/styling/TooltipStyle;Lorg/jetbrains/jewel/ui/component/styling/DropdownStyle;Landroidx/compose/runtime/Composer;IIII)Lorg/jetbrains/jewel/ui/ComponentStyling;
public static final fun dark (Lorg/jetbrains/jewel/ui/ComponentStyling;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/TabStyle;Lorg/jetbrains/jewel/ui/component/styling/DividerStyle;Lorg/jetbrains/jewel/ui/component/styling/DropdownStyle;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;Landroidx/compose/runtime/Composer;IIII)Lorg/jetbrains/jewel/ui/ComponentStyling;
public static final fun darkThemeDefinition-RFMEUTM (Lorg/jetbrains/jewel/foundation/theme/JewelTheme$Companion;Lorg/jetbrains/jewel/foundation/GlobalColors;Lorg/jetbrains/jewel/foundation/GlobalMetrics;Lorg/jetbrains/jewel/foundation/theme/ThemeColorPalette;Lorg/jetbrains/jewel/foundation/theme/ThemeIconData;Landroidx/compose/ui/text/TextStyle;JLandroidx/compose/runtime/Composer;II)Lorg/jetbrains/jewel/foundation/theme/ThemeDefinition;
public static final fun default (Lorg/jetbrains/jewel/ui/ComponentStyling;Landroidx/compose/runtime/Composer;I)Lorg/jetbrains/jewel/ui/ComponentStyling;
public static final fun getDefaultTextStyle (Lorg/jetbrains/jewel/foundation/theme/JewelTheme$Companion;)Landroidx/compose/ui/text/TextStyle;
public static final fun light (Lorg/jetbrains/jewel/ui/ComponentStyling;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/TabStyle;Lorg/jetbrains/jewel/ui/component/styling/DividerStyle;Lorg/jetbrains/jewel/ui/component/styling/DropdownStyle;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/TextAreaStyle;Lorg/jetbrains/jewel/ui/component/styling/TextFieldStyle;Lorg/jetbrains/jewel/ui/component/styling/TooltipStyle;Lorg/jetbrains/jewel/ui/component/styling/DropdownStyle;Landroidx/compose/runtime/Composer;IIII)Lorg/jetbrains/jewel/ui/ComponentStyling;
public static final fun light (Lorg/jetbrains/jewel/ui/ComponentStyling;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/TabStyle;Lorg/jetbrains/jewel/ui/component/styling/DividerStyle;Lorg/jetbrains/jewel/ui/component/styling/DropdownStyle;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;Landroidx/compose/runtime/Composer;IIII)Lorg/jetbrains/jewel/ui/ComponentStyling;
public static final fun lightThemeDefinition-RFMEUTM (Lorg/jetbrains/jewel/foundation/theme/JewelTheme$Companion;Lorg/jetbrains/jewel/foundation/GlobalColors;Lorg/jetbrains/jewel/foundation/GlobalMetrics;Lorg/jetbrains/jewel/foundation/theme/ThemeColorPalette;Lorg/jetbrains/jewel/foundation/theme/ThemeIconData;Landroidx/compose/ui/text/TextStyle;JLandroidx/compose/runtime/Composer;II)Lorg/jetbrains/jewel/foundation/theme/ThemeDefinition;
}

View File

@@ -0,0 +1,109 @@
package org.jetbrains.jewel.intui.standalone.styling
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
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
import org.jetbrains.jewel.intui.core.theme.IntUiLightTheme
import org.jetbrains.jewel.ui.component.styling.SliderColors
import org.jetbrains.jewel.ui.component.styling.SliderMetrics
import org.jetbrains.jewel.ui.component.styling.SliderStyle
@Composable
public fun SliderStyle.Companion.light(
colors: SliderColors = SliderColors.light(),
metrics: SliderMetrics = SliderMetrics.defaults(),
thumbShape: Shape = CircleShape,
): SliderStyle = SliderStyle(colors, metrics, thumbShape)
@Composable
public fun SliderStyle.Companion.dark(
colors: SliderColors = SliderColors.dark(),
metrics: SliderMetrics = SliderMetrics.defaults(),
thumbShape: Shape = CircleShape,
): SliderStyle = SliderStyle(colors, metrics, thumbShape)
@Composable
public fun SliderColors.Companion.light(
track: Color = IntUiLightTheme.colors.grey(10),
trackFilled: Color = IntUiLightTheme.colors.blue(6),
trackDisabled: Color = IntUiLightTheme.colors.grey(12),
trackFilledDisabled: Color = IntUiLightTheme.colors.grey(11),
stepMarker: Color = track,
thumbFill: Color = IntUiLightTheme.colors.grey(14),
thumbFillDisabled: Color = thumbFill,
thumbFillFocused: Color = thumbFill,
thumbFillPressed: Color = thumbFill,
thumbFillHovered: Color = thumbFill,
thumbBorder: Color = IntUiLightTheme.colors.grey(8),
thumbBorderFocused: Color = IntUiLightTheme.colors.blue(4),
thumbBorderDisabled: Color = IntUiLightTheme.colors.grey(11),
thumbBorderPressed: Color = IntUiLightTheme.colors.grey(7),
thumbBorderHovered: Color = IntUiLightTheme.colors.grey(9),
): SliderColors = SliderColors(
track,
trackFilled,
trackDisabled,
trackFilledDisabled,
stepMarker,
thumbFill,
thumbFillDisabled,
thumbFillFocused,
thumbFillPressed,
thumbFillHovered,
thumbBorder,
thumbBorderFocused,
thumbBorderDisabled,
thumbBorderPressed,
thumbBorderHovered,
)
@Composable
public fun SliderColors.Companion.dark(
track: Color = IntUiDarkTheme.colors.grey(4),
trackFilled: Color = IntUiDarkTheme.colors.blue(7),
trackDisabled: Color = IntUiDarkTheme.colors.grey(3),
trackFilledDisabled: Color = IntUiDarkTheme.colors.grey(4),
stepMarker: Color = track,
thumbFill: Color = IntUiDarkTheme.colors.grey(2),
thumbFillDisabled: Color = IntUiDarkTheme.colors.grey(3),
thumbFillFocused: Color = thumbFill,
thumbFillPressed: Color = thumbFill,
thumbFillHovered: Color = thumbFill,
thumbBorder: Color = IntUiDarkTheme.colors.grey(7),
thumbBorderFocused: Color = IntUiDarkTheme.colors.blue(6),
thumbBorderDisabled: Color = IntUiDarkTheme.colors.grey(5),
thumbBorderPressed: Color = IntUiDarkTheme.colors.grey(8),
thumbBorderHovered: Color = IntUiDarkTheme.colors.grey(9),
): SliderColors = SliderColors(
track,
trackFilled,
trackDisabled,
trackFilledDisabled,
stepMarker,
thumbFill,
thumbFillDisabled,
thumbFillFocused,
thumbFillPressed,
thumbFillHovered,
thumbBorder,
thumbBorderFocused,
thumbBorderDisabled,
thumbBorderPressed,
thumbBorderHovered,
)
@Composable
public fun SliderMetrics.Companion.defaults(
trackHeight: Dp = 4.dp,
thumbSize: DpSize = DpSize(14.dp, 14.dp),
thumbBorderWidth: Dp = 1.dp,
stepLineHeight: Dp = 8.dp,
stepLineWidth: Dp = 1.dp,
trackToStepSpacing: Dp = thumbSize.height / 2 + 4.dp,
): SliderMetrics =
SliderMetrics(trackHeight, thumbSize, thumbBorderWidth, stepLineHeight, stepLineWidth, trackToStepSpacing)

View File

@@ -40,6 +40,7 @@ import org.jetbrains.jewel.ui.component.styling.LinkStyle
import org.jetbrains.jewel.ui.component.styling.MenuStyle
import org.jetbrains.jewel.ui.component.styling.RadioButtonStyle
import org.jetbrains.jewel.ui.component.styling.ScrollbarStyle
import org.jetbrains.jewel.ui.component.styling.SliderStyle
import org.jetbrains.jewel.ui.component.styling.TabStyle
import org.jetbrains.jewel.ui.component.styling.TextAreaStyle
import org.jetbrains.jewel.ui.component.styling.TextFieldStyle
@@ -102,6 +103,7 @@ public fun ComponentStyling.dark(
outlinedButtonStyle: ButtonStyle = ButtonStyle.Outlined.dark(),
radioButtonStyle: RadioButtonStyle = RadioButtonStyle.dark(),
scrollbarStyle: ScrollbarStyle = ScrollbarStyle.dark(),
sliderStyle: SliderStyle = SliderStyle.dark(),
textAreaStyle: TextAreaStyle = TextAreaStyle.dark(),
textFieldStyle: TextFieldStyle = TextFieldStyle.dark(),
tooltipStyle: TooltipStyle = TooltipStyle.dark(),
@@ -126,6 +128,7 @@ public fun ComponentStyling.dark(
outlinedButtonStyle = outlinedButtonStyle,
radioButtonStyle = radioButtonStyle,
scrollbarStyle = scrollbarStyle,
sliderStyle = sliderStyle,
textAreaStyle = textAreaStyle,
textFieldStyle = textFieldStyle,
tooltipStyle = tooltipStyle,
@@ -152,6 +155,7 @@ public fun ComponentStyling.light(
outlinedButtonStyle: ButtonStyle = ButtonStyle.Outlined.light(),
radioButtonStyle: RadioButtonStyle = RadioButtonStyle.light(),
scrollbarStyle: ScrollbarStyle = ScrollbarStyle.light(),
sliderStyle: SliderStyle = SliderStyle.light(),
textAreaStyle: TextAreaStyle = TextAreaStyle.light(),
textFieldStyle: TextFieldStyle = TextFieldStyle.light(),
tooltipStyle: TooltipStyle = TooltipStyle.light(),
@@ -176,6 +180,7 @@ public fun ComponentStyling.light(
outlinedButtonStyle = outlinedButtonStyle,
radioButtonStyle = radioButtonStyle,
scrollbarStyle = scrollbarStyle,
sliderStyle = sliderStyle,
textAreaStyle = textAreaStyle,
textFieldStyle = textFieldStyle,
tooltipStyle = tooltipStyle,

View File

@@ -27,7 +27,6 @@ import com.intellij.icons.AllIcons
import com.intellij.ui.JBColor
import icons.JewelIcons
import org.jetbrains.jewel.bridge.LocalComponent
import org.jetbrains.jewel.bridge.ToolWindowScope
import org.jetbrains.jewel.bridge.toComposeColor
import org.jetbrains.jewel.foundation.lazy.tree.buildTree
import org.jetbrains.jewel.foundation.modifier.onActivated
@@ -43,12 +42,13 @@ import org.jetbrains.jewel.ui.component.IconButton
import org.jetbrains.jewel.ui.component.LazyTree
import org.jetbrains.jewel.ui.component.OutlinedButton
import org.jetbrains.jewel.ui.component.RadioButtonRow
import org.jetbrains.jewel.ui.component.Slider
import org.jetbrains.jewel.ui.component.Text
import org.jetbrains.jewel.ui.component.TextField
import org.jetbrains.jewel.ui.component.Tooltip
@Composable
internal fun ToolWindowScope.ComponentShowcaseTab() {
internal fun ComponentShowcaseTab() {
val bgColor by remember(JewelTheme.isDark) { mutableStateOf(JBColor.PanelBackground.toComposeColor()) }
val scrollState = rememberScrollState()
@@ -178,6 +178,9 @@ private fun RowScope.ColumnOne() {
)
}
}
var sliderValue by remember { mutableStateOf(.15f) }
Slider(sliderValue, { sliderValue = it }, steps = 5)
}
}

View File

@@ -0,0 +1,43 @@
package org.jetbrains.jewel.samples.standalone.view.component
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import org.jetbrains.jewel.samples.standalone.viewmodel.View
import org.jetbrains.jewel.ui.component.Slider
@Composable
@View(title = "Sliders", position = 12)
fun Sliders() {
var value1 by remember { mutableStateOf(.45f) }
Slider(
value = value1,
onValueChange = { value1 = it },
)
var value2 by remember { mutableStateOf(.7f) }
Slider(
value = value2,
onValueChange = { value2 = it },
enabled = false,
)
var value3 by remember { mutableStateOf(33f) }
Slider(
value = value3,
onValueChange = { value3 = it },
steps = 10,
valueRange = 0f..100f,
)
var value4 by remember { mutableStateOf(23f) }
Slider(
value = value4,
onValueChange = { value4 = it },
steps = 10,
valueRange = 0f..100f,
enabled = false,
)
}

View File

@@ -25,7 +25,7 @@ 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 <init> (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/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 <init> (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 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;
@@ -44,6 +44,7 @@ public final class org/jetbrains/jewel/ui/DefaultComponentStyling : org/jetbrain
public final fun getOutlinedButtonStyle ()Lorg/jetbrains/jewel/ui/component/styling/ButtonStyle;
public final fun getRadioButtonStyle ()Lorg/jetbrains/jewel/ui/component/styling/RadioButtonStyle;
public final fun getScrollbarStyle ()Lorg/jetbrains/jewel/ui/component/styling/ScrollbarStyle;
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 getTooltipStyle ()Lorg/jetbrains/jewel/ui/component/styling/TooltipStyle;
@@ -551,6 +552,44 @@ public final class org/jetbrains/jewel/ui/component/ScrollbarsKt {
public static final fun VerticalScrollbar (Landroidx/compose/foundation/v2/ScrollbarAdapter;Landroidx/compose/ui/Modifier;ZLandroidx/compose/foundation/interaction/MutableInteractionSource;Lorg/jetbrains/jewel/ui/component/styling/ScrollbarStyle;Landroidx/compose/runtime/Composer;II)V
}
public final class org/jetbrains/jewel/ui/component/SliderKt {
public static final fun Slider (FLkotlin/jvm/functions/Function1;Landroidx/compose/ui/Modifier;ZLkotlin/ranges/ClosedFloatingPointRange;ILkotlin/jvm/functions/Function0;Landroidx/compose/foundation/interaction/MutableInteractionSource;Lorg/jetbrains/jewel/ui/component/styling/SliderStyle;Landroidx/compose/runtime/Composer;II)V
}
public final class org/jetbrains/jewel/ui/component/SliderState : org/jetbrains/jewel/foundation/state/FocusableComponentState {
public static final field Companion Lorg/jetbrains/jewel/ui/component/SliderState$Companion;
public static final synthetic fun box-impl (J)Lorg/jetbrains/jewel/ui/component/SliderState;
public fun chooseValue (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Landroidx/compose/runtime/Composer;I)Ljava/lang/Object;
public static fun chooseValue-impl (JLjava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Landroidx/compose/runtime/Composer;I)Ljava/lang/Object;
public static fun constructor-impl (J)J
public static final fun copy-GPhM_18 (JZZZZZ)J
public static synthetic fun copy-GPhM_18$default (JZZZZZILjava/lang/Object;)J
public fun equals (Ljava/lang/Object;)Z
public static fun equals-impl (JLjava/lang/Object;)Z
public static final fun equals-impl0 (JJ)Z
public final fun getState-s-VKNKU ()J
public fun hashCode ()I
public static fun hashCode-impl (J)I
public fun isActive ()Z
public static fun isActive-impl (J)Z
public fun isEnabled ()Z
public static fun isEnabled-impl (J)Z
public fun isFocused ()Z
public static fun isFocused-impl (J)Z
public fun isHovered ()Z
public static fun isHovered-impl (J)Z
public fun isPressed ()Z
public static fun isPressed-impl (J)Z
public fun toString ()Ljava/lang/String;
public static fun toString-impl (J)Ljava/lang/String;
public final synthetic fun unbox-impl ()J
}
public final class org/jetbrains/jewel/ui/component/SliderState$Companion {
public final fun of-GPhM_18 (ZZZZZ)J
public static synthetic fun of-GPhM_18$default (Lorg/jetbrains/jewel/ui/component/SliderState$Companion;ZZZZZILjava/lang/Object;)J
}
public final class org/jetbrains/jewel/ui/component/SplitLayoutKt {
public static final fun HorizontalSplitLayout-BssWTFQ (Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Landroidx/compose/ui/Modifier;JFFFFFFLandroidx/compose/runtime/Composer;II)V
public static final fun VerticalSplitLayout-BssWTFQ (Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function3;Landroidx/compose/ui/Modifier;JFFFFFFLandroidx/compose/runtime/Composer;II)V
@@ -1637,6 +1676,72 @@ public final class org/jetbrains/jewel/ui/component/styling/ScrollbarStylingKt {
public static final fun getLocalScrollbarStyle ()Landroidx/compose/runtime/ProvidableCompositionLocal;
}
public final class org/jetbrains/jewel/ui/component/styling/SliderColors {
public static final field $stable I
public static final field Companion Lorg/jetbrains/jewel/ui/component/styling/SliderColors$Companion;
public synthetic fun <init> (JJJJJJJJJJJJJJJLkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun equals (Ljava/lang/Object;)Z
public final fun getStepMarker-0d7_KjU ()J
public final fun getThumbBorder-0d7_KjU ()J
public final fun getThumbBorderDisabled-0d7_KjU ()J
public final fun getThumbBorderFocused-0d7_KjU ()J
public final fun getThumbBorderHovered-0d7_KjU ()J
public final fun getThumbBorderPressed-0d7_KjU ()J
public final fun getThumbFill-0d7_KjU ()J
public final fun getThumbFillDisabled-0d7_KjU ()J
public final fun getThumbFillFocused-0d7_KjU ()J
public final fun getThumbFillHovered-0d7_KjU ()J
public final fun getThumbFillPressed-0d7_KjU ()J
public final fun getTrack-0d7_KjU ()J
public final fun getTrackDisabled-0d7_KjU ()J
public final fun getTrackFilled-0d7_KjU ()J
public final fun getTrackFilledDisabled-0d7_KjU ()J
public fun hashCode ()I
public final fun thumbBorderFor-p6gmeQ4 (JLandroidx/compose/runtime/Composer;I)Landroidx/compose/runtime/State;
public final fun thumbFillFor-p6gmeQ4 (JLandroidx/compose/runtime/Composer;I)Landroidx/compose/runtime/State;
public fun toString ()Ljava/lang/String;
}
public final class org/jetbrains/jewel/ui/component/styling/SliderColors$Companion {
}
public final class org/jetbrains/jewel/ui/component/styling/SliderMetrics {
public static final field $stable I
public static final field Companion Lorg/jetbrains/jewel/ui/component/styling/SliderMetrics$Companion;
public synthetic fun <init> (FJFFFFLkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun equals (Ljava/lang/Object;)Z
public final fun getStepLineHeight-D9Ej5fM ()F
public final fun getStepLineWidth-D9Ej5fM ()F
public final fun getThumbBorderWidth-D9Ej5fM ()F
public final fun getThumbSize-MYxV2XQ ()J
public final fun getTrackHeight-D9Ej5fM ()F
public final fun getTrackToStepSpacing-D9Ej5fM ()F
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class org/jetbrains/jewel/ui/component/styling/SliderMetrics$Companion {
}
public final class org/jetbrains/jewel/ui/component/styling/SliderStyle {
public static final field $stable I
public static final field Companion Lorg/jetbrains/jewel/ui/component/styling/SliderStyle$Companion;
public fun <init> (Lorg/jetbrains/jewel/ui/component/styling/SliderColors;Lorg/jetbrains/jewel/ui/component/styling/SliderMetrics;Landroidx/compose/ui/graphics/Shape;)V
public fun equals (Ljava/lang/Object;)Z
public final fun getColors ()Lorg/jetbrains/jewel/ui/component/styling/SliderColors;
public final fun getMetrics ()Lorg/jetbrains/jewel/ui/component/styling/SliderMetrics;
public final fun getThumbShape ()Landroidx/compose/ui/graphics/Shape;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class org/jetbrains/jewel/ui/component/styling/SliderStyle$Companion {
}
public final class org/jetbrains/jewel/ui/component/styling/SliderStylingKt {
public static final fun getLocalSliderStyle ()Landroidx/compose/runtime/ProvidableCompositionLocal;
}
public final class org/jetbrains/jewel/ui/component/styling/SubmenuMetrics {
public static final field $stable I
public static final field Companion Lorg/jetbrains/jewel/ui/component/styling/SubmenuMetrics$Companion;
@@ -2197,6 +2302,7 @@ public final class org/jetbrains/jewel/ui/theme/JewelThemeKt {
public static final fun getOutlinedButtonStyle (Lorg/jetbrains/jewel/foundation/theme/JewelTheme$Companion;Landroidx/compose/runtime/Composer;I)Lorg/jetbrains/jewel/ui/component/styling/ButtonStyle;
public static final fun getRadioButtonStyle (Lorg/jetbrains/jewel/foundation/theme/JewelTheme$Companion;Landroidx/compose/runtime/Composer;I)Lorg/jetbrains/jewel/ui/component/styling/RadioButtonStyle;
public static final fun getScrollbarStyle (Lorg/jetbrains/jewel/foundation/theme/JewelTheme$Companion;Landroidx/compose/runtime/Composer;I)Lorg/jetbrains/jewel/ui/component/styling/ScrollbarStyle;
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 getTooltipStyle (Lorg/jetbrains/jewel/foundation/theme/JewelTheme$Companion;Landroidx/compose/runtime/Composer;I)Lorg/jetbrains/jewel/ui/component/styling/TooltipStyle;

View File

@@ -34,6 +34,7 @@ import org.jetbrains.jewel.ui.component.styling.LocalMenuStyle
import org.jetbrains.jewel.ui.component.styling.LocalOutlinedButtonStyle
import org.jetbrains.jewel.ui.component.styling.LocalRadioButtonStyle
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.LocalTooltipStyle
@@ -41,6 +42,7 @@ import org.jetbrains.jewel.ui.component.styling.LocalUndecoratedDropdownStyle
import org.jetbrains.jewel.ui.component.styling.MenuStyle
import org.jetbrains.jewel.ui.component.styling.RadioButtonStyle
import org.jetbrains.jewel.ui.component.styling.ScrollbarStyle
import org.jetbrains.jewel.ui.component.styling.SliderStyle
import org.jetbrains.jewel.ui.component.styling.TabStyle
import org.jetbrains.jewel.ui.component.styling.TextAreaStyle
import org.jetbrains.jewel.ui.component.styling.TextFieldStyle
@@ -66,6 +68,7 @@ public class DefaultComponentStyling(
public val outlinedButtonStyle: ButtonStyle,
public val radioButtonStyle: RadioButtonStyle,
public val scrollbarStyle: ScrollbarStyle,
public val sliderStyle: SliderStyle,
public val textAreaStyle: TextAreaStyle,
public val textFieldStyle: TextFieldStyle,
public val tooltipStyle: TooltipStyle,
@@ -93,6 +96,7 @@ public class DefaultComponentStyling(
LocalOutlinedButtonStyle provides outlinedButtonStyle,
LocalRadioButtonStyle provides radioButtonStyle,
LocalScrollbarStyle provides scrollbarStyle,
LocalSliderStyle provides sliderStyle,
LocalTextAreaStyle provides textAreaStyle,
LocalTextFieldStyle provides textFieldStyle,
LocalTooltipStyle provides tooltipStyle,

View File

@@ -94,8 +94,9 @@ private fun ButtonImpl(
textStyle: TextStyle,
content: @Composable RowScope.() -> Unit,
) {
var buttonState by
remember(interactionSource) { mutableStateOf(ButtonState.of(enabled = enabled)) }
var buttonState by remember(interactionSource) {
mutableStateOf(ButtonState.of(enabled = enabled))
}
remember(enabled) { buttonState = buttonState.copy(enabled = enabled) }
@@ -103,9 +104,9 @@ private fun ButtonImpl(
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 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)

View File

@@ -0,0 +1,735 @@
package org.jetbrains.jewel.ui.component
import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.TweenSpec
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.MutatePriority
import androidx.compose.foundation.MutatorMutex
import androidx.compose.foundation.background
import androidx.compose.foundation.focusable
import androidx.compose.foundation.gestures.DragScope
import androidx.compose.foundation.gestures.DraggableState
import androidx.compose.foundation.gestures.GestureCancellationException
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.gestures.draggable
import androidx.compose.foundation.hoverable
import androidx.compose.foundation.interaction.DragInteraction
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.BoxWithConstraints
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.requiredSizeIn
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.progressSemantics
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.State
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.lerp
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.input.key.KeyEvent
import androidx.compose.ui.input.key.KeyEventType
import androidx.compose.ui.input.key.key
import androidx.compose.ui.input.key.nativeKeyCode
import androidx.compose.ui.input.key.onKeyEvent
import androidx.compose.ui.input.key.type
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.platform.debugInspectorInfo
import androidx.compose.ui.semantics.disabled
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.setProgress
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import org.jetbrains.jewel.foundation.Stroke
import org.jetbrains.jewel.foundation.modifier.border
import org.jetbrains.jewel.foundation.state.CommonStateBitMask.Active
import org.jetbrains.jewel.foundation.state.CommonStateBitMask.Enabled
import org.jetbrains.jewel.foundation.state.CommonStateBitMask.Focused
import org.jetbrains.jewel.foundation.state.CommonStateBitMask.Hovered
import org.jetbrains.jewel.foundation.state.CommonStateBitMask.Pressed
import org.jetbrains.jewel.foundation.state.FocusableComponentState
import org.jetbrains.jewel.foundation.theme.JewelTheme
import org.jetbrains.jewel.ui.component.styling.SliderStyle
import org.jetbrains.jewel.ui.focusOutline
import org.jetbrains.jewel.ui.theme.sliderStyle
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min
// Note: a lot of code in this file is from the Material 2 implementation
@Composable
public fun Slider(
value: Float,
onValueChange: (Float) -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
valueRange: ClosedFloatingPointRange<Float> = 0f..1f,
steps: Int = 0,
onValueChangeFinished: (() -> Unit)? = null,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
style: SliderStyle = JewelTheme.sliderStyle,
) {
require(steps >= 0) { "The number of steps must be >= 0" }
val onValueChangeState = rememberUpdatedState(onValueChange)
val onValueChangeFinishedState = rememberUpdatedState(onValueChangeFinished)
val tickFractions = remember(steps) {
stepsToTickFractions(steps)
}
val isRtl = LocalLayoutDirection.current == LayoutDirection.Rtl
val focusRequester = remember { FocusRequester() }
val thumbSize = style.metrics.thumbSize
val ticksHeight = if (tickFractions.isNotEmpty()) {
style.metrics.trackToStepSpacing + style.metrics.stepLineHeight
} else {
0.dp
}
val minHeight = thumbSize.height + style.metrics.thumbBorderWidth * 2 + ticksHeight
BoxWithConstraints(
modifier
.requiredSizeIn(minWidth = thumbSize.height * 2, minHeight = minHeight)
.sliderSemantics(value, enabled, onValueChange, onValueChangeFinished, valueRange, steps)
.focusRequester(focusRequester)
.focusable(enabled, interactionSource)
.slideOnKeyEvents(enabled, steps, valueRange, value, isRtl, onValueChangeState, onValueChangeFinishedState),
) {
val widthPx = constraints.maxWidth.toFloat()
val maxPx: Float
val minPx: Float
with(LocalDensity.current) {
maxPx = max(widthPx - thumbSize.width.toPx(), 0f)
minPx = min(thumbSize.width.toPx(), maxPx)
}
fun scaleToUserValue(offset: Float) =
scale(minPx, maxPx, offset, valueRange.start, valueRange.endInclusive)
fun scaleToOffset(userValue: Float) =
scale(valueRange.start, valueRange.endInclusive, userValue, minPx, maxPx)
val scope = rememberCoroutineScope()
val rawOffset = remember { mutableFloatStateOf(scaleToOffset(value)) }
val pressOffset = remember { mutableFloatStateOf(0f) }
val draggableState = remember(minPx, maxPx, valueRange) {
SliderDraggableState {
rawOffset.floatValue = (rawOffset.floatValue + it + pressOffset.floatValue)
pressOffset.floatValue = 0f
val offsetInTrack = rawOffset.floatValue.coerceIn(minPx, maxPx)
onValueChangeState.value.invoke(scaleToUserValue(offsetInTrack))
}
}
CorrectValueSideEffect(::scaleToOffset, valueRange, minPx..maxPx, rawOffset, value)
val canAnimate = !JewelTheme.isSwingCompatMode
val gestureEndAction = rememberUpdatedState<(Float) -> Unit> { velocity: Float ->
val current = rawOffset.floatValue
val target = snapValueToTick(current, tickFractions, minPx, maxPx)
focusRequester.requestFocus()
if (current != target) {
scope.launch {
if (canAnimate) {
animateToTarget(draggableState, current, target, velocity)
} else {
draggableState.drag {
dragBy(target - current)
}
}
onValueChangeFinished?.invoke()
}
} else if (!draggableState.isDragging) {
// check ifDragging in case the change is still in progress (touch -> drag case)
onValueChangeFinished?.invoke()
}
}
val press = Modifier.sliderTapModifier(
draggableState,
interactionSource,
widthPx,
isRtl,
rawOffset,
gestureEndAction,
pressOffset,
enabled,
)
val drag = Modifier.draggable(
orientation = Orientation.Horizontal,
reverseDirection = isRtl,
enabled = enabled,
interactionSource = interactionSource,
onDragStopped = { velocity -> gestureEndAction.value.invoke(velocity) },
startDragImmediately = draggableState.isDragging,
state = draggableState,
)
val coerced = value.coerceIn(valueRange.start, valueRange.endInclusive)
val fraction = calcFraction(valueRange.start, valueRange.endInclusive, coerced)
SliderImpl(
enabled = enabled,
positionFraction = fraction,
tickFractions = tickFractions,
style = style,
minHeight = minHeight,
width = maxPx - minPx,
interactionSource = interactionSource,
modifier = press.then(drag),
)
}
}
private val SliderMinWidth = 100.dp // Completely arbitrary
@Composable
private fun SliderImpl(
enabled: Boolean,
positionFraction: Float,
tickFractions: List<Float>,
style: SliderStyle,
width: Float,
minHeight: Dp,
interactionSource: MutableInteractionSource,
modifier: Modifier,
) {
Box(
modifier.then(
Modifier
.widthIn(min = SliderMinWidth)
.heightIn(min = minHeight),
),
) {
val widthDp: Dp
with(LocalDensity.current) {
widthDp = width.toDp()
}
Track(
modifier = Modifier.fillMaxWidth(),
style = style,
enabled = enabled,
positionFractionEnd = positionFraction,
tickFractions = tickFractions,
)
val offset = (widthDp + style.metrics.thumbSize.width) * positionFraction
SliderThumb(offset, interactionSource, style, enabled)
}
}
@Composable
private fun Track(
modifier: Modifier,
style: SliderStyle,
enabled: Boolean,
positionFractionEnd: Float,
tickFractions: List<Float>,
) {
val trackStrokeWidthPx: Float
val thumbWidthPx: Float
val trackYPx: Float
val stepLineHeightPx: Float
val stepLineWidthPx: Float
val trackToMarkersGapPx: Float
with(LocalDensity.current) {
trackStrokeWidthPx = style.metrics.trackHeight.toPx()
thumbWidthPx = style.metrics.thumbSize.width.toPx()
trackYPx = style.metrics.thumbSize.width.toPx() / 2 + style.metrics.thumbBorderWidth.toPx()
stepLineHeightPx = style.metrics.stepLineHeight.toPx()
stepLineWidthPx = style.metrics.stepLineWidth.toPx()
trackToMarkersGapPx = style.metrics.trackToStepSpacing.toPx()
}
Canvas(modifier) {
val isRtl = layoutDirection == LayoutDirection.Rtl
val trackLeft = Offset(thumbWidthPx / 2, trackYPx)
val trackRight = Offset(size.width - thumbWidthPx / 2, trackYPx)
val trackStart = if (isRtl) trackRight else trackLeft
val trackEnd = if (isRtl) trackLeft else trackRight
drawLine(
color = if (enabled) style.colors.track else style.colors.trackDisabled,
start = trackStart,
end = trackEnd,
strokeWidth = trackStrokeWidthPx,
cap = StrokeCap.Round,
)
val activeTrackStart = Offset(trackStart.x, trackYPx)
val activeTrackEnd = Offset(
x = trackStart.x + (trackEnd.x - trackStart.x) * positionFractionEnd - thumbWidthPx / 2,
y = trackYPx,
)
drawLine(
color = if (enabled) style.colors.trackFilled else style.colors.trackFilledDisabled,
start = activeTrackStart,
end = activeTrackEnd,
strokeWidth = trackStrokeWidthPx,
cap = StrokeCap.Round,
)
val stepMarkerY = trackStrokeWidthPx + trackToMarkersGapPx
tickFractions.forEach { fraction ->
drawLine(
color = style.colors.stepMarker,
start = Offset(lerp(trackStart, trackEnd, fraction).x, stepMarkerY),
end = Offset(lerp(trackStart, trackEnd, fraction).x, stepMarkerY + stepLineHeightPx),
strokeWidth = stepLineWidthPx,
cap = StrokeCap.Round,
)
}
}
}
@Composable
private fun BoxScope.SliderThumb(
offset: Dp,
interactionSource: MutableInteractionSource,
style: SliderStyle,
enabled: Boolean,
modifier: Modifier = Modifier,
) {
Box(
Modifier
.padding(start = offset, top = style.metrics.thumbBorderWidth)
.align(Alignment.TopStart),
) {
var state by remember { mutableStateOf(SliderState.of(enabled)) }
remember(enabled) { state = state.copy(enabled = enabled) }
LaunchedEffect(interactionSource) {
interactionSource.interactions.collect { interaction ->
when (interaction) {
is PressInteraction.Press, is DragInteraction.Start ->
state = state.copy(pressed = true)
is PressInteraction.Release, is PressInteraction.Cancel,
is DragInteraction.Stop, is DragInteraction.Cancel,
->
state = state.copy(pressed = false)
is HoverInteraction.Enter -> state = state.copy(hovered = true)
is HoverInteraction.Exit -> state = state.copy(hovered = false)
is FocusInteraction.Focus -> state = state.copy(focused = true)
is FocusInteraction.Unfocus -> state = state.copy(focused = false)
}
}
}
val thumbSize = style.metrics.thumbSize
Spacer(
modifier
.size(thumbSize)
.hoverable(interactionSource, enabled)
.background(style.colors.thumbFillFor(state).value, style.thumbShape)
.border(
alignment = Stroke.Alignment.Outside,
width = style.metrics.thumbBorderWidth,
color = style.colors.thumbBorderFor(state).value,
shape = style.thumbShape,
)
.focusOutline(state, style.thumbShape),
)
}
}
private fun snapValueToTick(
current: Float,
tickFractions: List<Float>,
minPx: Float,
maxPx: Float,
): Float =
// target is a closest anchor to the `current`, if exists
tickFractions
.minByOrNull { abs(lerp(minPx, maxPx, it) - current) }
?.run { lerp(minPx, maxPx, this) }
?: current
private fun stepsToTickFractions(steps: Int): List<Float> =
if (steps == 0) emptyList() else List(steps + 2) { it.toFloat() / (steps + 1) }
// Scale x1 from a1..b1 range to a2..b2 range
private fun scale(a1: Float, b1: Float, x1: Float, a2: Float, b2: Float) =
lerp(a2, b2, calcFraction(a1, b1, x1))
// Calculate the 0..1 fraction that `pos` value represents between `a` and `b`
private fun calcFraction(a: Float, b: Float, pos: Float) =
(if (b - a == 0f) 0f else (pos - a) / (b - a)).coerceIn(0f, 1f)
@Composable
private fun CorrectValueSideEffect(
scaleToOffset: (Float) -> Float,
valueRange: ClosedFloatingPointRange<Float>,
trackRange: ClosedFloatingPointRange<Float>,
valueState: MutableState<Float>,
value: Float,
) {
SideEffect {
val error = (valueRange.endInclusive - valueRange.start) / 1000
val newOffset = scaleToOffset(value)
if (abs(newOffset - valueState.value) > error && valueState.value in trackRange) {
valueState.value = newOffset
}
}
}
private fun Modifier.sliderSemantics(
value: Float,
enabled: Boolean,
onValueChange: (Float) -> Unit,
onValueChangeFinished: (() -> Unit)? = null,
valueRange: ClosedFloatingPointRange<Float> = 0f..1f,
steps: Int = 0,
): Modifier {
val coerced = value.coerceIn(valueRange.start, valueRange.endInclusive)
return semantics {
if (!enabled) disabled()
setProgress(
action = { targetValue ->
var newValue = targetValue.coerceIn(valueRange.start, valueRange.endInclusive)
val originalVal = newValue
val resolvedValue = if (steps > 0) {
var distance: Float = newValue
for (i in 0..steps + 1) {
val stepValue = lerp(
valueRange.start,
valueRange.endInclusive,
i.toFloat() / (steps + 1),
)
if (abs(stepValue - originalVal) <= distance) {
distance = abs(stepValue - originalVal)
newValue = stepValue
}
}
newValue
} else {
newValue
}
// This is to keep it consistent with AbsSeekbar.java: return false if no
// change from current.
if (resolvedValue == coerced) {
false
} else {
onValueChange(resolvedValue)
onValueChangeFinished?.invoke()
true
}
},
)
}.progressSemantics(value, valueRange, steps)
}
private fun Modifier.sliderTapModifier(
draggableState: DraggableState,
interactionSource: MutableInteractionSource,
maxPx: Float,
isRtl: Boolean,
rawOffset: State<Float>,
gestureEndAction: State<(Float) -> Unit>,
pressOffset: MutableState<Float>,
enabled: Boolean,
) = composed(
factory = {
if (enabled) {
val scope = rememberCoroutineScope()
pointerInput(draggableState, interactionSource, maxPx, isRtl) {
detectTapGestures(
onPress = { pos ->
val to = if (isRtl) maxPx - pos.x else pos.x
pressOffset.value = to - rawOffset.value
try {
awaitRelease()
} catch (_: GestureCancellationException) {
pressOffset.value = 0f
}
},
onTap = {
scope.launch {
draggableState.drag(MutatePriority.UserInput) {
// just trigger animation, press offset will be applied
dragBy(0f)
}
gestureEndAction.value.invoke(0f)
}
},
)
}
} else {
this
}
},
inspectorInfo = debugInspectorInfo {
name = "sliderTapModifier"
properties["draggableState"] = draggableState
properties["interactionSource"] = interactionSource
properties["maxPx"] = maxPx
properties["isRtl"] = isRtl
properties["rawOffset"] = rawOffset
properties["gestureEndAction"] = gestureEndAction
properties["pressOffset"] = pressOffset
properties["enabled"] = enabled
},
)
private val SliderToTickAnimation = TweenSpec<Float>(durationMillis = 100)
private suspend fun animateToTarget(
draggableState: DraggableState,
current: Float,
target: Float,
velocity: Float,
) {
draggableState.drag {
var latestValue = current
Animatable(initialValue = current).animateTo(target, SliderToTickAnimation, velocity) {
dragBy(this.value - latestValue)
latestValue = this.value
}
}
}
// TODO: Edge case - losing focus on slider while key is pressed will end up with onValueChangeFinished not being invoked
@OptIn(ExperimentalComposeUiApi::class)
private fun Modifier.slideOnKeyEvents(
enabled: Boolean,
steps: Int,
valueRange: ClosedFloatingPointRange<Float>,
value: Float,
isRtl: Boolean,
onValueChangeState: State<(Float) -> Unit>,
onValueChangeFinishedState: State<(() -> Unit)?>,
): Modifier {
require(steps >= 0) { "steps should be >= 0" }
return this.onKeyEvent {
if (!enabled) return@onKeyEvent false
when (it.type) {
KeyEventType.KeyDown -> {
val rangeLength = abs(valueRange.endInclusive - valueRange.start)
// When steps == 0, it means that a user is not limited by a step length (delta) when using touch or mouse.
// But it is not possible to adjust the value continuously when using keyboard buttons -
// the delta has to be discrete. In this case, 1% of the valueRange seems to make sense.
val actualSteps = if (steps > 0) steps + 1 else 100
val delta = rangeLength / actualSteps
when {
it.isDirectionUp -> {
onValueChangeState.value((value + delta).coerceIn(valueRange))
true
}
it.isDirectionDown -> {
onValueChangeState.value((value - delta).coerceIn(valueRange))
true
}
it.isDirectionRight -> {
val sign = if (isRtl) -1 else 1
onValueChangeState.value((value + sign * delta).coerceIn(valueRange))
true
}
it.isDirectionLeft -> {
val sign = if (isRtl) -1 else 1
onValueChangeState.value((value - sign * delta).coerceIn(valueRange))
true
}
it.isHome -> {
onValueChangeState.value(valueRange.start)
true
}
it.isMoveEnd -> {
onValueChangeState.value(valueRange.endInclusive)
true
}
it.isPgUp -> {
val page = (actualSteps / 10).coerceIn(1, 10)
onValueChangeState.value((value - page * delta).coerceIn(valueRange))
true
}
it.isPgDn -> {
val page = (actualSteps / 10).coerceIn(1, 10)
onValueChangeState.value((value + page * delta).coerceIn(valueRange))
true
}
else -> false
}
}
KeyEventType.KeyUp -> {
@Suppress("ComplexCondition") // In original m2 code
if (it.isDirectionDown || it.isDirectionUp || it.isDirectionRight ||
it.isDirectionLeft || it.isHome || it.isMoveEnd || it.isPgUp || it.isPgDn
) {
onValueChangeFinishedState.value?.invoke()
true
} else {
false
}
}
else -> false
}
}
}
internal val KeyEvent.isDirectionUp: Boolean
get() = key.nativeKeyCode == java.awt.event.KeyEvent.VK_UP
internal val KeyEvent.isDirectionDown: Boolean
get() = key.nativeKeyCode == java.awt.event.KeyEvent.VK_DOWN
internal val KeyEvent.isDirectionRight: Boolean
get() = key.nativeKeyCode == java.awt.event.KeyEvent.VK_RIGHT
internal val KeyEvent.isDirectionLeft: Boolean
get() = key.nativeKeyCode == java.awt.event.KeyEvent.VK_LEFT
internal val KeyEvent.isHome: Boolean
get() = key.nativeKeyCode == java.awt.event.KeyEvent.VK_HOME
internal val KeyEvent.isMoveEnd: Boolean
get() = key.nativeKeyCode == java.awt.event.KeyEvent.VK_END
internal val KeyEvent.isPgUp: Boolean
get() = key.nativeKeyCode == java.awt.event.KeyEvent.VK_PAGE_UP
internal val KeyEvent.isPgDn: Boolean
get() = key.nativeKeyCode == java.awt.event.KeyEvent.VK_PAGE_DOWN
internal fun lerp(start: Float, stop: Float, fraction: Float): Float =
(1 - fraction) * start + fraction * stop
@Immutable
@JvmInline
public value class SliderState(public val state: ULong) : FocusableComponentState {
override val isActive: Boolean
get() = state and Active != 0UL
override val isEnabled: Boolean
get() = state and Enabled != 0UL
override val isFocused: Boolean
get() = state and Focused != 0UL
override val isHovered: Boolean
get() = state and Hovered != 0UL
override val isPressed: Boolean
get() = state and Pressed != 0UL
public fun copy(
enabled: Boolean = isEnabled,
focused: Boolean = isFocused,
pressed: Boolean = isPressed,
hovered: Boolean = isHovered,
active: Boolean = isActive,
): SliderState =
of(
enabled = enabled,
focused = focused,
pressed = pressed,
hovered = hovered,
active = active,
)
override fun toString(): String =
"${javaClass.simpleName}(isEnabled=$isEnabled, isFocused=$isFocused, isHovered=$isHovered, " +
"isPressed=$isPressed, isActive=$isActive)"
public companion object {
public fun of(
enabled: Boolean = true,
focused: Boolean = false,
pressed: Boolean = false,
hovered: Boolean = false,
active: Boolean = true,
): SliderState =
SliderState(
(if (enabled) Enabled else 0UL) or
(if (focused) Focused else 0UL) or
(if (hovered) Hovered else 0UL) or
(if (pressed) Pressed else 0UL) or
(if (active) Active else 0UL),
)
}
}
private class SliderDraggableState(
val onDelta: (Float) -> Unit,
) : DraggableState {
var isDragging by mutableStateOf(false)
private set
private val dragScope: DragScope = object : DragScope {
override fun dragBy(pixels: Float) {
onDelta(pixels)
}
}
private val scrollMutex = MutatorMutex()
override suspend fun drag(
dragPriority: MutatePriority,
block: suspend DragScope.() -> Unit,
) {
coroutineScope {
isDragging = true
scrollMutex.mutateWith(dragScope, dragPriority, block)
isDragging = false
}
}
override fun dispatchRawDelta(delta: Float) {
onDelta(delta)
}
}

View File

@@ -0,0 +1,109 @@
package org.jetbrains.jewel.ui.component.styling
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.ProvidableCompositionLocal
import androidx.compose.runtime.Stable
import androidx.compose.runtime.State
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.DpSize
import org.jetbrains.jewel.foundation.GenerateDataFunctions
import org.jetbrains.jewel.foundation.theme.JewelTheme
import org.jetbrains.jewel.ui.component.SliderState
@Stable
@GenerateDataFunctions
public class SliderStyle(
public val colors: SliderColors,
public val metrics: SliderMetrics,
public val thumbShape: Shape,
) {
public companion object
}
@Immutable
@GenerateDataFunctions
public class SliderColors(
public val track: Color,
public val trackFilled: Color,
public val trackDisabled: Color,
public val trackFilledDisabled: Color,
public val stepMarker: Color,
public val thumbFill: Color,
public val thumbFillDisabled: Color,
public val thumbFillFocused: Color,
public val thumbFillPressed: Color,
public val thumbFillHovered: Color,
public val thumbBorder: Color,
public val thumbBorderFocused: Color,
public val thumbBorderDisabled: Color,
public val thumbBorderPressed: Color,
public val thumbBorderHovered: Color,
) {
@Composable
public fun thumbFillFor(state: SliderState): State<Color> =
rememberUpdatedState(
state.chooseColor(
normal = thumbFill,
disabled = thumbFillDisabled,
focused = thumbFillFocused,
pressed = thumbFillPressed,
hovered = thumbFillHovered,
),
)
@Composable
public fun thumbBorderFor(state: SliderState): State<Color> =
rememberUpdatedState(
state.chooseColor(
normal = thumbBorder,
disabled = thumbBorderDisabled,
focused = thumbBorderFocused,
pressed = thumbBorderPressed,
hovered = thumbBorderHovered,
),
)
@Composable
private fun SliderState.chooseColor(
normal: Color,
disabled: Color,
pressed: Color,
hovered: Color,
focused: Color,
) =
when {
!isEnabled -> disabled
isFocused -> focused
isPressed && !JewelTheme.isSwingCompatMode -> pressed
isHovered && !JewelTheme.isSwingCompatMode -> hovered
else -> normal
}
public companion object
}
@Immutable
@GenerateDataFunctions
public class SliderMetrics(
public val trackHeight: Dp,
public val thumbSize: DpSize,
public val thumbBorderWidth: Dp,
public val stepLineHeight: Dp,
public val stepLineWidth: Dp,
public val trackToStepSpacing: Dp,
) {
public companion object
}
public val LocalSliderStyle: ProvidableCompositionLocal<SliderStyle> =
staticCompositionLocalOf {
error("No default SliderStyle provided. Have you forgotten the theme?")
}

View File

@@ -40,12 +40,14 @@ import org.jetbrains.jewel.ui.component.styling.LocalMenuStyle
import org.jetbrains.jewel.ui.component.styling.LocalOutlinedButtonStyle
import org.jetbrains.jewel.ui.component.styling.LocalRadioButtonStyle
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.LocalTooltipStyle
import org.jetbrains.jewel.ui.component.styling.MenuStyle
import org.jetbrains.jewel.ui.component.styling.RadioButtonStyle
import org.jetbrains.jewel.ui.component.styling.ScrollbarStyle
import org.jetbrains.jewel.ui.component.styling.SliderStyle
import org.jetbrains.jewel.ui.component.styling.TabStyle
import org.jetbrains.jewel.ui.component.styling.TextAreaStyle
import org.jetbrains.jewel.ui.component.styling.TextFieldStyle
@@ -165,6 +167,11 @@ public val JewelTheme.Companion.iconButtonStyle: IconButtonStyle
@ReadOnlyComposable
get() = LocalIconButtonStyle.current
public val JewelTheme.Companion.sliderStyle: SliderStyle
@Composable
@ReadOnlyComposable
get() = LocalSliderStyle.current
@Composable
public fun BaseJewelTheme(
theme: ThemeDefinition,