[JEWEL-1346] Force Auto Correct + Enable Documentation Rules

Cherry-picked from e2b25d41cd35c on master. 268 files; 254 applied
cleanly and 14 conflicted where the 0.41 cycle had since rewritten the
same declarations. The commit is almost entirely additive KDoc, so most
resolutions keep both sides; the exceptions are where this branch is
already ahead.

Taken from this branch, because the incoming text describes superseded
code:

* `MacPlatformServices`, `Popup`, `PathImageResourceLocation` —
  `[JEWEL-1388]`, `[JEWEL-1396]` and `[JEWEL-1370]` rewrote these. The
  incoming doc for `MacPlatformServicesDefaultImpl` still refers to
  `[UnsafeAccessing]`, which `[JEWEL-1388]` deleted, so importing it
  would leave a dangling KDoc link.
* `FocusableComponentState` — the incoming doc describes the old state
  priority; `[JEWEL-1193]` changed hover to take precedence over focus,
  and this branch's doc already matches that behaviour.
* `ThemeColorPalette` — `isIslands` is a constructor `val`, and every
  sibling entry in that block uses `@property`, so the incoming `@param`
  would be both wrong and inconsistent.
* `MarkdownTestTheme`, `ShowcaseIcons`, `JewelTheme` — signatures and
  declarations this branch gained from `[JEWEL-1322]`, `[JEWEL-1345]` and
  `[JEWEL-1150]`.

Kept from both sides, with ordering decided per hunk rather than per
file, since a KDoc has to sit immediately above what it documents:

* `MenuStyling` (4 hunks) and one hunk of `Menu` — the incoming KDoc and
  this branch's `@Deprecated` / `@Suppress` annotate the same following
  declaration, so the doc goes first.
* `Menu` (other hunk), `SimpleListItem`, `TooltipStyling`, `Typography`,
  `MarkdownStyling` — this branch's side is a complete deprecated
  declaration, several of them restored by the `[JEWEL-1323]` revert, and
  the incoming KDoc belongs to the declaration that follows it, so the
  declaration goes first.

Verified applicable to this branch rather than assumed: enabling the
documentation rules is only safe if the existing code already satisfies
them. `.editorconfig` and `jewel-linting.gradle.kts` are now identical to
master, and both gates pass here — `detekt detektMain detektTest` and
`lintKotlin` are green, and Bazel still compiles.

This also lands `scripts/annotate-detekt.main.kts` and the workflow's
detekt split, which the `checks` job needs: `check -x detekt` leaves
detekt to its own step so a failure there still reaches the annotation
step, which turns detekt's checkstyle reports into inline findings on a
PR's "Files changed" tab.


(cherry picked from commit 513866356b5904906dcf33830192bce225d7a413)

IJ-MR-220560

GitOrigin-RevId: 417028f8877d77b5d6aa61585081077a45f2a686
This commit is contained in:
Daniel Bertoldi
2026-09-07 22:29:10 +00:00
committed by intellij-monorepo-bot
parent ea32a85584
commit a4b53943c8
265 changed files with 4050 additions and 224 deletions
+17 -1
View File
@@ -43,7 +43,7 @@ jobs:
- name: Run :check task
# Run checks for all modules except the IDE plugin sample, as that is bound to have missing APIs issues
run: ./gradlew check --continue --no-daemon
run: ./gradlew check -x detekt --continue --no-daemon
- name: Annotate JUnit test failures
uses: mikepenz/action-junit-report@v6
@@ -61,9 +61,25 @@ jobs:
retention-days: 7
- name: Run detekt tasks
id: detekt
if: ${{ !cancelled() }}
# Run detekt checks for all modules except the IDE plugin sample, as that is bound to have missing APIs issues
run: ./gradlew detekt detektMain detektTest --continue --no-daemon
- name: Set up Kotlin ${{ env.KOTLIN_VERSION }}
id: kotlin
if: ${{ !cancelled() && steps.detekt.outcome != 'skipped' }}
uses: ./.github/actions/setup-kotlin
with:
version: ${{ env.KOTLIN_VERSION }}
- name: Annotate detekt findings
if: ${{ !cancelled() && steps.detekt.outcome != 'skipped' }}
# Turn detekt's checkstyle reports (main.xml from detektMain, test.xml from detektTest) into inline
# GitHub annotations on the PR's "Files changed" tab, plus a run summary. The failing detekt task is
# the gate; this is visibility. Works for fork PRs too (annotations, not API-driven comments).
run: ${{ steps.kotlin.outputs.bin-dir }}/kotlin ./scripts/annotate-detekt.main.kts
check_paths:
name: Check changed files
runs-on: ubuntu-latest
+1
View File
@@ -49,6 +49,7 @@ ktlint_standard_try-catch-finally-spacing = disabled
ktlint_standard_blank-line-between-when-conditions = disabled
ktlint_standard_when-entry-bracing = disabled
ktlint_standard_wrapping = disabled
ktlint_standard_spacing-between-declarations-with-comments=disabled
trim_trailing_whitespace = false
[gradlew.bat]
@@ -8,10 +8,11 @@ plugins {
detekt {
// TODO: JEWEL-1329 standalone analysis API initialises PSI documents as read-only, Detekt tries to open in writing mode.
// enable it once it has been fixed.
autoCorrect = false
// We are able to circumvent this using JewelBaseRule and JewelRuleSet for now.
autoCorrect = System.getenv("CI") == null
config.from(files(rootProject.file("detekt.yml")))
buildUponDefaultConfig = true
debug = providers.gradleProperty("detekt.debug").map { it.toBoolean() }.getOrElse(false)
}
dependencies {
@@ -3,9 +3,17 @@ package org.jetbrains.jewel.intui.window
import org.jetbrains.jewel.ui.icon.IconKey
import org.jetbrains.jewel.ui.icon.PathIconKey
/** Icon keys for the decorated window control buttons (minimize, maximize, restore, close). */
public object DecoratedWindowIconKeys {
/** The icon key for the minimize button. */
public val minimize: IconKey = PathIconKey("window/minimize.svg", this::class.java)
/** The icon key for the maximize button. */
public val maximize: IconKey = PathIconKey("window/maximize.svg", this::class.java)
/** The icon key for the restore button. */
public val restore: IconKey = PathIconKey("window/restore.svg", this::class.java)
/** The icon key for the close button. */
public val close: IconKey = PathIconKey("window/close.svg", this::class.java)
}
@@ -9,6 +9,15 @@ import org.jetbrains.jewel.window.styling.LocalDecoratedWindowStyle
import org.jetbrains.jewel.window.styling.LocalTitleBarStyle
import org.jetbrains.jewel.window.styling.TitleBarStyle
/**
* Provides [DecoratedWindowStyle] and [TitleBarStyle] into this [ComponentStyling], defaulting to the Int UI light or
* dark variants based on [JewelTheme.isDark].
*
* @param windowStyle The [DecoratedWindowStyle] to use. Defaults to [DecoratedWindowStyle.dark] or
* [DecoratedWindowStyle.light] based on the current theme.
* @param titleBarStyle The [TitleBarStyle] to use. Defaults to [TitleBarStyle.dark] or [TitleBarStyle.light] based on
* the current theme.
*/
public fun ComponentStyling.decoratedWindow(
windowStyle: DecoratedWindowStyle? = null,
titleBarStyle: TitleBarStyle? = null,
@@ -7,27 +7,56 @@ import org.jetbrains.jewel.window.styling.DecoratedWindowColors
import org.jetbrains.jewel.window.styling.DecoratedWindowMetrics
import org.jetbrains.jewel.window.styling.DecoratedWindowStyle
/**
* Creates an Int UI light [DecoratedWindowStyle].
*
* @param colors The [DecoratedWindowColors] to use. Defaults to [DecoratedWindowColors.light].
* @param metrics The [DecoratedWindowMetrics] to use. Defaults to [DecoratedWindowMetrics.defaults].
*/
public fun DecoratedWindowStyle.Companion.light(
colors: DecoratedWindowColors = DecoratedWindowColors.light(),
metrics: DecoratedWindowMetrics = DecoratedWindowMetrics.defaults(),
): DecoratedWindowStyle = DecoratedWindowStyle(colors, metrics)
/**
* Creates an Int UI dark [DecoratedWindowStyle].
*
* @param colors The [DecoratedWindowColors] to use. Defaults to [DecoratedWindowColors.dark].
* @param metrics The [DecoratedWindowMetrics] to use. Defaults to [DecoratedWindowMetrics.defaults].
*/
public fun DecoratedWindowStyle.Companion.dark(
colors: DecoratedWindowColors = DecoratedWindowColors.dark(),
metrics: DecoratedWindowMetrics = DecoratedWindowMetrics.defaults(),
): DecoratedWindowStyle = DecoratedWindowStyle(colors, metrics)
/**
* Creates Int UI light [DecoratedWindowColors] using the standard undecorated window border color.
*
* @param borderColor The active window border color. Defaults to `#5A5D6B`.
* @param inactiveBorderColor The inactive window border color. Defaults to [borderColor].
*/
public fun DecoratedWindowColors.Companion.light(
// from Window.undecorated.border
borderColor: Color = Color(0xFF5A5D6B),
inactiveBorderColor: Color = borderColor,
): DecoratedWindowColors = DecoratedWindowColors(borderColor, inactiveBorderColor)
/**
* Creates Int UI dark [DecoratedWindowColors] using the standard undecorated window border color.
*
* @param borderColor The active window border color. Defaults to `#5A5D63`.
* @param inactiveBorderColor The inactive window border color. Defaults to [borderColor].
*/
public fun DecoratedWindowColors.Companion.dark(
// from Window.undecorated.border
borderColor: Color = Color(0xFF5A5D63),
inactiveBorderColor: Color = borderColor,
): DecoratedWindowColors = DecoratedWindowColors(borderColor, inactiveBorderColor)
/**
* Creates default [DecoratedWindowMetrics] with a 1dp border width.
*
* @param borderWidth The width of the border drawn around the undecorated window on Linux.
*/
public fun DecoratedWindowMetrics.Companion.defaults(borderWidth: Dp = 1.dp): DecoratedWindowMetrics =
DecoratedWindowMetrics(borderWidth)
@@ -27,6 +27,13 @@ import org.jetbrains.jewel.window.styling.TitleBarIcons
import org.jetbrains.jewel.window.styling.TitleBarMetrics
import org.jetbrains.jewel.window.styling.TitleBarStyle
/**
* Creates an Int UI light [TitleBarStyle] with the standard IntelliJ dark-header appearance.
*
* @param colors The [TitleBarColors] to use. Defaults to [TitleBarColors.light].
* @param metrics The [TitleBarMetrics] to use. Defaults to [TitleBarMetrics.defaults].
* @param icons The [TitleBarIcons] to use. Defaults to [TitleBarIcons.defaults].
*/
@Composable
public fun TitleBarStyle.Companion.light(
colors: TitleBarColors = TitleBarColors.light(),
@@ -78,6 +85,13 @@ public fun TitleBarStyle.Companion.light(
),
)
/**
* Creates an Int UI [TitleBarStyle] with a light-colored header, matching the "New UI" appearance.
*
* @param colors The [TitleBarColors] to use. Defaults to [TitleBarColors.lightWithLightHeader].
* @param metrics The [TitleBarMetrics] to use. Defaults to [TitleBarMetrics.defaults].
* @param icons The [TitleBarIcons] to use. Defaults to [TitleBarIcons.defaults].
*/
@Composable
public fun TitleBarStyle.Companion.lightWithLightHeader(
colors: TitleBarColors = TitleBarColors.lightWithLightHeader(),
@@ -128,6 +142,13 @@ public fun TitleBarStyle.Companion.lightWithLightHeader(
),
)
/**
* Creates an Int UI dark [TitleBarStyle].
*
* @param colors The [TitleBarColors] to use. Defaults to [TitleBarColors.dark].
* @param metrics The [TitleBarMetrics] to use. Defaults to [TitleBarMetrics.defaults].
* @param icons The [TitleBarIcons] to use. Defaults to [TitleBarIcons.defaults].
*/
@Composable
public fun TitleBarStyle.Companion.dark(
colors: TitleBarColors = TitleBarColors.dark(),
@@ -200,6 +221,7 @@ private fun titleBarIconButtonStyle(hoveredBackground: Color, pressedBackground:
metrics,
)
/** Creates Int UI light [TitleBarColors] for the standard IntelliJ dark-header title bar. */
@Composable
public fun TitleBarColors.Companion.light(
backgroundColor: Color = IntUiLightTheme.colors.gray(2),
@@ -247,6 +269,7 @@ public fun TitleBarColors.Companion.light(
dropdownPressedBackground = dropdownPressedBackground,
)
/** Creates Int UI [TitleBarColors] for a light-colored title bar header, as used in the New UI. */
@Composable
public fun TitleBarColors.Companion.lightWithLightHeader(
backgroundColor: Color = IntUiLightTheme.colors.gray(13),
@@ -279,6 +302,7 @@ public fun TitleBarColors.Companion.lightWithLightHeader(
dropdownPressedBackground = dropdownPressedBackground,
)
/** Creates Int UI dark [TitleBarColors]. */
@Composable
public fun TitleBarColors.Companion.dark(
backgroundColor: Color = IntUiDarkTheme.colors.gray(2),
@@ -311,6 +335,14 @@ public fun TitleBarColors.Companion.dark(
dropdownPressedBackground = dropdownPressedBackground,
)
/**
* Creates default [TitleBarMetrics] with standard Int UI values.
*
* @param height The title bar height. Defaults to `40.dp`.
* @param gradientStartX The horizontal start position of the background gradient. Defaults to `-100.dp`.
* @param gradientEndX The horizontal end position of the background gradient. Defaults to `400.dp`.
* @param titlePaneButtonSize The size of window control buttons (minimize, maximize, close). Defaults to `40x40.dp`.
*/
public fun TitleBarMetrics.Companion.defaults(
height: Dp = 40.dp,
gradientStartX: Dp = (-100).dp,
@@ -318,6 +350,14 @@ public fun TitleBarMetrics.Companion.defaults(
titlePaneButtonSize: DpSize = DpSize(40.dp, 40.dp),
): TitleBarMetrics = TitleBarMetrics(height, gradientStartX, gradientEndX, titlePaneButtonSize)
/**
* Creates default [TitleBarIcons] using the standard [DecoratedWindowIconKeys] for window controls.
*
* @param minimizeButton The icon key for the minimize button.
* @param maximizeButton The icon key for the maximize button.
* @param restoreButton The icon key for the restore button.
* @param closeButton The icon key for the close button.
*/
public fun TitleBarIcons.Companion.defaults(
minimizeButton: IconKey = DecoratedWindowIconKeys.minimize,
maximizeButton: IconKey = DecoratedWindowIconKeys.maximize,
@@ -48,6 +48,28 @@ import org.jetbrains.jewel.intui.standalone.window.Window
import org.jetbrains.jewel.window.styling.DecoratedWindowStyle
import org.jetbrains.jewel.window.utils.DesktopPlatform
/**
* A Compose window with custom JetBrains Runtime (JBR) window decorations, including support for a custom [TitleBar].
* Requires the application to run on JetBrains Runtime; an error is thrown at runtime if JBR is not available.
*
* On Linux, the window is rendered undecorated with a 1dp border drawn by Compose to simulate a native frame.
*
* @param onCloseRequest Callback invoked when the user requests to close the window.
* @param state The [WindowState] controlling the window's size and placement.
* @param visible Whether the window is visible.
* @param title The title shown in the OS window frame and taskbar.
* @param icon The icon shown in the OS window frame and taskbar.
* @param resizable Whether the user can resize the window.
* @param enabled Whether the window is enabled for user interaction.
* @param focusable Whether the window can receive focus.
* @param alwaysOnTop Whether the window is always displayed on top of other windows.
* @param onPreviewKeyEvent Callback invoked for key events before they are dispatched to children. Return `true` to
* consume the event.
* @param onKeyEvent Callback invoked for key events after they are dispatched to children. Return `true` to consume the
* event.
* @param style The [DecoratedWindowStyle] controlling the window frame's visual appearance.
* @param content The composable content displayed inside the window, scoped to a [DecoratedWindowScope].
*/
@Suppress("ModifierMissing")
@Composable
public fun DecoratedWindow(
@@ -184,10 +206,13 @@ public fun DecoratedWindow(
}
}
/** Scope provided to content composables inside a [DecoratedWindow], exposing the [window] and its [state]. */
@Stable
public interface DecoratedWindowScope : FrameWindowScope {
/** The [ComposeWindow] backing this decorated window. */
override val window: ComposeWindow
/** The current visual state of the decorated window. */
public val state: DecoratedWindowState
}
@@ -230,21 +255,37 @@ private object DecoratedWindowMeasurePolicy : MeasurePolicy {
}
}
/** Encodes the visual state of a decorated window (active, fullscreen, minimized, maximized) as a bit mask. */
@Immutable
@JvmInline
public value class DecoratedWindowState(public val state: ULong) {
public value class DecoratedWindowState(
/** The raw bit mask encoding the current window state flags. */
public val state: ULong
) {
/** Whether the window is currently active (focused). */
public val isActive: Boolean
get() = state and Active != 0UL
/** Whether the window is in fullscreen mode. */
public val isFullscreen: Boolean
get() = state and Fullscreen != 0UL
/** Whether the window is minimized. */
public val isMinimized: Boolean
get() = state and Minimize != 0UL
/** Whether the window is maximized. */
public val isMaximized: Boolean
get() = state and Maximize != 0UL
/**
* Returns a copy of this [DecoratedWindowState] with the given fields replaced by their new values.
*
* @param fullscreen Whether the window is in fullscreen mode.
* @param minimized Whether the window is minimized.
* @param maximized Whether the window is maximized.
* @param active Whether the window is active (focused).
*/
public fun copy(
fullscreen: Boolean = isFullscreen,
minimized: Boolean = isMinimized,
@@ -254,12 +295,28 @@ public value class DecoratedWindowState(public val state: ULong) {
override fun toString(): String = "${javaClass.simpleName}(isFullscreen=$isFullscreen, isActive=$isActive)"
/** State bit constants and the [of] factory for constructing [DecoratedWindowState] values. */
public companion object {
/** Bit flag for the active (focused) state. */
public val Active: ULong = 1UL shl 0
/** Bit flag for the fullscreen state. */
public val Fullscreen: ULong = 1UL shl 1
/** Bit flag for the minimized state. */
public val Minimize: ULong = 1UL shl 2
/** Bit flag for the maximized state. */
public val Maximize: ULong = 1UL shl 3
/**
* Constructs a [DecoratedWindowState] from individual boolean flags.
*
* @param fullscreen Whether the window is in fullscreen mode.
* @param minimized Whether the window is minimized.
* @param maximized Whether the window is maximized.
* @param active Whether the window is active (focused).
*/
public fun of(
fullscreen: Boolean = false,
minimized: Boolean = false,
@@ -273,6 +330,12 @@ public value class DecoratedWindowState(public val state: ULong) {
(if (active) Active else 0UL)
)
/**
* Constructs a [DecoratedWindowState] by reading the current placement and activation state of the given
* [ComposeWindow].
*
* @param window The [ComposeWindow] to read state from.
*/
public fun of(window: ComposeWindow): DecoratedWindowState =
of(
fullscreen = window.placement == WindowPlacement.Fullscreen,
@@ -8,8 +8,10 @@ import org.jetbrains.jewel.window.styling.LocalDecoratedWindowStyle
import org.jetbrains.jewel.window.styling.LocalTitleBarStyle
import org.jetbrains.jewel.window.styling.TitleBarStyle
/** The default title bar style provided by the current theme. */
public val JewelTheme.Companion.defaultTitleBarStyle: TitleBarStyle
@Composable @ReadOnlyComposable get() = LocalTitleBarStyle.current
/** The default decorated window style provided by the current theme. */
public val JewelTheme.Companion.defaultDecoratedWindowStyle: DecoratedWindowStyle
@Composable @ReadOnlyComposable get() = LocalDecoratedWindowStyle.current
@@ -15,6 +15,13 @@ import org.jetbrains.jewel.intui.standalone.window.macos.LocalMacPlatformService
import org.jetbrains.jewel.window.styling.TitleBarStyle
import org.jetbrains.jewel.window.utils.WindowMouseEventEffect
/**
* Enables or disables the macOS "new fullscreen controls" (the three colored circles displayed in the upper-left corner
* of a window in fullscreen mode). When enabled, the background color of the controls is taken from
* [TitleBarColors.fullscreenControlButtonsBackground].
*
* @param newControls Whether to use the new fullscreen controls. Defaults to `true`.
*/
public fun Modifier.newFullscreenControls(newControls: Boolean = true): Modifier =
this then
NewFullscreenControlsElement(
@@ -60,6 +60,18 @@ internal const val TITLE_BAR_LAYOUT_ID = "__TITLE_BAR_CONTENT__"
internal const val TITLE_BAR_BORDER_LAYOUT_ID = "__TITLE_BAR_BORDER__"
/**
* Renders the title bar for a [DecoratedWindow], routing to the platform-specific implementation for macOS, Windows,
* and Linux. Content is laid out using [TitleBarScope.align] to position children at the start, center, or end of the
* bar.
*
* @param modifier The [Modifier] to apply to the title bar container.
* @param gradientStartColor An optional color used as the center point of a horizontal gradient blended with the
* background. Use [Color.Unspecified] for a solid background.
* @param style The [TitleBarStyle] controlling the bar's visual appearance.
* @param content The composable content rendered inside the title bar, provided with the current
* [DecoratedWindowState].
*/
@Composable
public fun DecoratedWindowScope.TitleBar(
modifier: Modifier = Modifier,
@@ -243,11 +255,18 @@ internal fun rememberTitleBarMeasurePolicy(
applyTitleBar: (Dp, DecoratedWindowState) -> PaddingValues,
): MeasurePolicy = remember(window, state, applyTitleBar) { TitleBarMeasurePolicy(window, state, applyTitleBar) }
/** Scope provided to content composables inside a title bar, exposing the window [title], [icon], and alignment. */
public interface TitleBarScope {
public val title: String
public val icon: Painter?
/**
* Aligns this title bar child element horizontally to [Start][Alignment.Start], [End][Alignment.End], or
* [CenterHorizontally][Alignment.CenterHorizontally].
*
* @param alignment The horizontal alignment to apply to this element.
*/
@Stable public fun Modifier.align(alignment: Alignment.Horizontal): Modifier
}
@@ -11,10 +11,13 @@ import androidx.compose.ui.unit.Dp
import org.jetbrains.jewel.foundation.GenerateDataFunctions
import org.jetbrains.jewel.window.DecoratedWindowState
/** Defines the overall visual style of a decorated window, combining its colors and metrics. */
@Immutable
@GenerateDataFunctions
public class DecoratedWindowStyle(
/** The colors used for the decorated window frame. */
public val colors: DecoratedWindowColors,
/** The layout metrics for the decorated window frame. */
public val metrics: DecoratedWindowMetrics,
) {
override fun equals(other: Any?): Boolean {
@@ -37,12 +40,25 @@ public class DecoratedWindowStyle(
override fun toString(): String = "DecoratedWindowStyle(colors=$colors, metrics=$metrics)"
/** Companion object for [DecoratedWindowStyle]. */
public companion object
}
/** Holds the border colors used for the decorated window frame in active and inactive states. */
@Immutable
@GenerateDataFunctions
public class DecoratedWindowColors(public val border: Color, public val borderInactive: Color) {
public class DecoratedWindowColors(
/** The border color when the window is active. */
public val border: Color,
/** The border color when the window is inactive. */
public val borderInactive: Color,
) {
/**
* Returns a [State] holding the border color appropriate for the given [state]: the inactive border color when the
* window is not active, or the active border color otherwise.
*
* @param state The current [DecoratedWindowState] of the window.
*/
@Composable
public fun borderFor(state: DecoratedWindowState): State<Color> =
rememberUpdatedState(
@@ -72,12 +88,17 @@ public class DecoratedWindowColors(public val border: Color, public val borderIn
override fun toString(): String = "DecoratedWindowColors(border=$border, borderInactive=$borderInactive)"
/** Companion object for [DecoratedWindowColors]. */
public companion object
}
/** Holds the layout metrics for the decorated window frame, such as border width. */
@Immutable
@GenerateDataFunctions
public class DecoratedWindowMetrics(public val borderWidth: Dp) {
public class DecoratedWindowMetrics(
/** The width of the decorated window border. */
public val borderWidth: Dp
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
@@ -91,9 +112,11 @@ public class DecoratedWindowMetrics(public val borderWidth: Dp) {
override fun toString(): String = "DecoratedWindowMetrics(borderWidth=$borderWidth)"
/** Companion object for [DecoratedWindowMetrics]. */
public companion object
}
/** CompositionLocal providing the current [DecoratedWindowStyle]. */
public val LocalDecoratedWindowStyle: ProvidableCompositionLocal<DecoratedWindowStyle> = staticCompositionLocalOf {
error("No DecoratedWindowStyle provided. Have you forgotten the theme?")
}
@@ -16,15 +16,23 @@ import org.jetbrains.jewel.ui.component.styling.IconButtonStyle
import org.jetbrains.jewel.ui.icon.IconKey
import org.jetbrains.jewel.window.DecoratedWindowState
/** Defines the overall visual style of the title bar, combining its colors, metrics, icons, and button styles. */
@Stable
@GenerateDataFunctions
public class TitleBarStyle(
/** The color tokens used by the title bar. */
public val colors: TitleBarColors,
/** The layout metrics for the title bar. */
public val metrics: TitleBarMetrics,
/** The icon keys for the title bar's window control buttons. */
public val icons: TitleBarIcons,
/** The style applied to dropdowns rendered inside the title bar. */
public val dropdownStyle: DropdownStyle,
/** The style applied to icon buttons rendered inside the title bar. */
public val iconButtonStyle: IconButtonStyle,
/** The style applied to window control pane buttons (minimize, maximize, restore). */
public val paneButtonStyle: IconButtonStyle,
/** The style applied to the window close pane button. */
public val paneCloseButtonStyle: IconButtonStyle,
) {
override fun equals(other: Any?): Boolean {
@@ -67,32 +75,47 @@ public class TitleBarStyle(
")"
}
/** Companion object for [TitleBarStyle]. */
public companion object
}
/** Holds all color tokens used by the title bar in its various interactive and focus states. */
@Immutable
@GenerateDataFunctions
public class TitleBarColors(
/** The background color when the window is active. */
public val background: Color,
/** The background color when the window is inactive. */
public val inactiveBackground: Color,
/** The foreground/content color of the title bar. */
public val content: Color,
/** The border color of the title bar. */
public val border: Color,
// The background color for newControlButtons(three circles in left top corner) in MacOS
// fullscreen mode
/** The background color for the macOS fullscreen control buttons (the three circles in the top-left corner). */
public val fullscreenControlButtonsBackground: Color,
// The hover and press background color for window control buttons(minimize, maximize) in Linux
/** The background color for window control buttons (minimize, maximize) on Linux when hovered. */
public val titlePaneButtonHoveredBackground: Color,
/** The background color for window control buttons (minimize, maximize) on Linux when pressed. */
public val titlePaneButtonPressedBackground: Color,
// The hover and press background color for window close button in Linux
/** The background color for the window close button on Linux when hovered. */
public val titlePaneCloseButtonHoveredBackground: Color,
/** The background color for the window close button on Linux when pressed. */
public val titlePaneCloseButtonPressedBackground: Color,
// The hover and press background color for IconButtons in title bar content
/** The background color for icon buttons in the title bar content area when hovered. */
public val iconButtonHoveredBackground: Color,
/** The background color for icon buttons in the title bar content area when pressed. */
public val iconButtonPressedBackground: Color,
// The hover and press background color for Dropdown in title bar content
/** The background color for dropdowns in the title bar content area when pressed. */
public val dropdownPressedBackground: Color,
/** The background color for dropdowns in the title bar content area when hovered. */
public val dropdownHoveredBackground: Color,
) {
/**
* Returns a [State] holding the background color appropriate for the given [state]: the inactive background when
* the window is not active, or the active background otherwise.
*
* @param state The current [DecoratedWindowState] of the window.
*/
@Composable
public fun backgroundFor(state: DecoratedWindowState): State<Color> =
rememberUpdatedState(
@@ -160,15 +183,21 @@ public class TitleBarColors(
")"
}
/** Companion object for [TitleBarColors]. */
public companion object
}
/** Holds the layout metrics for the title bar: height, gradient positions, and control button size. */
@Immutable
@GenerateDataFunctions
public class TitleBarMetrics(
/** The height of the title bar. */
public val height: Dp,
/** The horizontal start position of the title bar gradient. */
public val gradientStartX: Dp,
/** The horizontal end position of the title bar gradient. */
public val gradientEndX: Dp,
/** The size of the window control pane buttons (minimize, maximize, restore, close). */
public val titlePaneButtonSize: DpSize,
) {
override fun equals(other: Any?): Boolean {
@@ -202,15 +231,21 @@ public class TitleBarMetrics(
")"
}
/** Companion object for [TitleBarMetrics]. */
public companion object
}
/** Holds the icon keys for the title bar's window control buttons (minimize, maximize, restore, close). */
@Immutable
@GenerateDataFunctions
public class TitleBarIcons(
/** The icon key for the minimize window control button. */
public val minimizeButton: IconKey,
/** The icon key for the maximize window control button. */
public val maximizeButton: IconKey,
/** The icon key for the restore window control button. */
public val restoreButton: IconKey,
/** The icon key for the close window control button. */
public val closeButton: IconKey,
) {
override fun equals(other: Any?): Boolean {
@@ -244,9 +279,11 @@ public class TitleBarIcons(
")"
}
/** Companion object for [TitleBarIcons]. */
public companion object
}
/** CompositionLocal that provides the current [TitleBarStyle]. Must be provided by the active theme. */
public val LocalTitleBarStyle: ProvidableCompositionLocal<TitleBarStyle> = staticCompositionLocalOf {
error("No TitleBarStyle provided. Have you forgotten the theme?")
}
@@ -1,12 +1,22 @@
package org.jetbrains.jewel.window.utils
/** Identifies the desktop operating system the application is currently running on. */
public enum class DesktopPlatform {
/** The Linux operating system. */
Linux,
/** The Windows operating system. */
Windows,
/** The macOS operating system. */
MacOS,
/** An unrecognized or unsupported operating system. */
Unknown;
/** Provides the [Current] platform detected from system properties. */
public companion object {
/** The [DesktopPlatform] detected from the `os.name` system property at runtime. */
public val Current: DesktopPlatform by lazy {
val name = System.getProperty("os.name")
when {
@@ -2,15 +2,37 @@
// Apache 2.0 license.
package org.jetbrains.jewel.detekt
import com.intellij.core.CoreApplicationEnvironment
import com.intellij.openapi.application.ApplicationManager
import com.intellij.psi.impl.source.tree.TreeCopyHandler
import dev.detekt.api.RuleSet
import dev.detekt.api.RuleSetId
import dev.detekt.api.RuleSetProvider
import org.jetbrains.jewel.detekt.rules.EqualityMembersRule
import org.jetbrains.jewel.detekt.rules.MissingApiStatusAnnotationRule
/** Registers Jewel's custom Detekt rules under the `jewel` rule set ID. */
class JewelRuleSetProvider : RuleSetProvider {
override val ruleSetId: RuleSetId = RuleSetId("jewel")
init {
// Detekt's standalone Analysis API does not register treeCopyHandler (it was intentionally removed in
// https://github.com/detekt/detekt/commit/ba593207d90e97c96c890740a8a3cf3d0978aee2 as KtLint was phasing
// it out). However, our autocorrect rules use high-level PSI manipulation APIs (e.g. addDeclaration) that
// require cross-tree node copies, which internally look up this extension point. We register it here at the
// earliest point in the Detekt plugin lifecycle so that it is available before any analysis begins.
// The registration must happen here rather than in individual rules, as the RuleSetProvider is loaded via
// ServiceLoader before the Analysis API session is created.
val extensionArea = ApplicationManager.getApplication().extensionArea
if (!extensionArea.hasExtensionPoint(TreeCopyHandler.EP_NAME)) {
CoreApplicationEnvironment.registerExtensionPoint(
extensionArea,
TreeCopyHandler.EP_NAME,
TreeCopyHandler::class.java,
)
}
}
override fun instance(): RuleSet =
RuleSet(ruleSetId, rules = listOf(::EqualityMembersRule, ::MissingApiStatusAnnotationRule))
}
@@ -5,9 +5,9 @@ package org.jetbrains.jewel.detekt.rules
import com.intellij.psi.PsiWhiteSpace
import com.intellij.psi.impl.source.tree.LeafPsiElement
import dev.detekt.api.Config
import dev.detekt.api.Configuration
import dev.detekt.api.Entity
import dev.detekt.api.Finding
import dev.detekt.api.Rule
import dev.detekt.api.config
import dev.detekt.api.internal.AutoCorrectable
import org.jetbrains.kotlin.lexer.KtTokens
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtFunction
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.KtObjectDeclaration
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.psi.psiUtil.findDescendantOfType
@@ -31,9 +32,11 @@ private const val RULE_DESCRIPTION = "This rule detects missing or incomplete eq
* correctly implemented based on the class's properties. Formatting of the auto-corrected code is left to the IDE's
* formatter/ktfmt.
*/
@AutoCorrectable(since = "0.38.0")
class EqualityMembersRule(config: Config) : Rule(config, RULE_DESCRIPTION) {
@AutoCorrectable(since = "0.40.0")
class EqualityMembersRule(config: Config) : JewelBaseRule(config, RULE_DESCRIPTION) {
private val functionsToCheck: List<String> by config(defaultValue = listOf("equals", "hashCode", "toString"))
@Configuration("Only check classes annotated with these annotations")
private val annotated: List<String> by config(defaultValue = listOf("GenerateDataFunctions"))
override fun visitClass(klass: KtClass) {
@@ -147,7 +150,17 @@ class EqualityMembersRule(config: Config) : Rule(config, RULE_DESCRIPTION) {
// Clean up class code after the fixes
val factory = KtPsiFactory(klass.project)
val body = checkNotNull(klass.body)
if (body.lastChild is LeafPsiElement && (body.lastChild as LeafPsiElement).elementType == KtTokens.RBRACE) {
val companionObject =
klass.declarations.filterIsInstance<KtObjectDeclaration>().firstOrNull { it.isCompanion() }
if (companionObject != null) {
// Ensure a blank line separates the last generated function from the companion object
if (companionObject.prevSibling is KtFunction) {
body.addBefore(factory.createWhiteSpace("\n\n"), companionObject)
}
} else if (
body.lastChild is LeafPsiElement && (body.lastChild as LeafPsiElement).elementType == KtTokens.RBRACE
) {
when (val prevSibling = body.lastChild.prevSibling) {
is KtFunction -> {
// Missing newline before rbrace
@@ -212,9 +225,17 @@ class EqualityMembersRule(config: Config) : Rule(config, RULE_DESCRIPTION) {
private fun generateToStringFunction(klass: KtClass, props: Set<String>) {
generateFunction(klass) {
appendLine("override fun toString(): String {")
append(" return \"${klass.name}(")
append(props.joinToString(", ") { "$it=$$it" })
appendLine(")\"")
appendLine(" return \"${klass.name}(\" +")
val propsList = props.toList()
for ((index, prop) in propsList.withIndex()) {
val isLast = index == propsList.lastIndex
if (isLast) {
appendLine(" \"$prop=$$prop\" +")
} else {
appendLine(" \"$prop=$$prop, \" +")
}
}
appendLine(" \")\"")
appendLine("}")
}
}
@@ -223,10 +244,17 @@ class EqualityMembersRule(config: Config) : Rule(config, RULE_DESCRIPTION) {
val factory = KtPsiFactory(klass.project)
val newFunction = factory.createFunction(buildString(builder))
// 1. Add the function itself to the class body
val addedElement = klass.addDeclaration(newFunction)
// Insert before the companion object if present, otherwise append (addDeclaration creates
// the body block if the class currently has none).
val companionObject =
klass.declarations.filterIsInstance<KtObjectDeclaration>().firstOrNull { it.isCompanion() }
val addedElement: KtNamedFunction =
if (companionObject != null) {
checkNotNull(klass.body).addBefore(newFunction, companionObject) as KtNamedFunction
} else {
klass.addDeclaration(newFunction)
}
// 2. Add two newlines before the function we just added for nice formatting.
checkNotNull(klass.body).addBefore(factory.createWhiteSpace("\n\n"), addedElement)
}
}
@@ -0,0 +1,33 @@
package org.jetbrains.jewel.detekt.rules
import dev.detekt.api.Config
import dev.detekt.api.Rule
import dev.detekt.api.modifiedText
import java.net.URI
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtPsiFactory
/**
* Base class for Jewel Detekt rules. Handles working-file isolation for autocorrect: changes are applied to a writable
* copy of the PSI file, then written back to the original only if modifications were made.
*/
@Suppress("AbstractClassCanBeConcreteClass")
abstract class JewelBaseRule(config: Config, description: String, url: URI? = null) : Rule(config, description, url) {
private lateinit var workingFile: KtFile
override fun visit(root: KtFile) {
val startingText = root.modifiedText ?: root.text
workingFile =
if (autoCorrect) {
KtPsiFactory(root.project).createPhysicalFile(fileName = root.name, text = startingText)
} else {
root
}
super.visit(workingFile)
if (autoCorrect && workingFile.text != startingText) {
root.modifiedText = workingFile.text
}
}
}
@@ -4,9 +4,9 @@ package org.jetbrains.jewel.detekt.rules
import dev.detekt.api.Config
import dev.detekt.api.Entity
import dev.detekt.api.Finding
import dev.detekt.api.Rule
import dev.detekt.api.internal.AutoCorrectable
import org.jetbrains.kotlin.psi.KtAnnotated
import org.jetbrains.kotlin.psi.KtAnnotationEntry
import org.jetbrains.kotlin.psi.KtClassInitializer
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtDeclaration
@@ -32,7 +32,7 @@ private const val RULE_DESCRIPTION =
* Auto-correction will add the missing annotation, but formatting is left to the IDE's formatter/ktfmt.
*/
@AutoCorrectable(since = "0.38.0")
class MissingApiStatusAnnotationRule(config: Config) : Rule(config, RULE_DESCRIPTION) {
class MissingApiStatusAnnotationRule(config: Config) : JewelBaseRule(config, RULE_DESCRIPTION) {
private val annotationsMap =
mapOf("InternalJewelApi" to "ApiStatus.Internal", "ExperimentalJewelApi" to "ApiStatus.Experimental")
@@ -140,8 +140,27 @@ class MissingApiStatusAnnotationRule(config: Config) : Rule(config, RULE_DESCRIP
private fun KtDeclaration.addAnnotation(annotationName: String) {
val factory = KtPsiFactory(project)
val annotationEntry = factory.createAnnotationEntry("@$annotationName")
val added = addAnnotationEntry(annotationEntry)
modifierList?.addAfter(factory.createNewLine(1), added)
// When inserting a Jewel annotation, find the paired ApiStatus one and insert after it.
val pairedApiStatus = annotationsMap[annotationName]
val anchorEntry =
if (pairedApiStatus != null) {
annotationEntries.firstOrNull { entry ->
val name = entry.shortName.toString()
name == pairedApiStatus || name == pairedApiStatus.removePrefix("ApiStatus.")
}
} else {
null
}
if (anchorEntry != null) {
val modList = checkNotNull(modifierList)
val added = modList.addAfter(annotationEntry, anchorEntry) as KtAnnotationEntry
modList.addBefore(factory.createNewLine(1), added)
} else {
val added = addAnnotationEntry(annotationEntry)
modifierList?.addAfter(factory.createNewLine(1), added)
}
}
private fun KtFile.addImportIfNeeded(fqName: String) {
@@ -90,7 +90,9 @@ class EqualityMembersRuleSpec {
|}
|
|override fun toString(): String {
| return "DataFuncTest(a=$a)"
| return "DataFuncTest(" +
| "a=$a" +
| ")"
|}
|}
"""
@@ -139,7 +141,9 @@ class EqualityMembersRuleSpec {
|}
|
|override fun toString(): String {
| return "DataFuncTest(a=$a)"
| return "DataFuncTest(" +
| "a=$a" +
| ")"
|}
|}
"""
@@ -327,7 +331,10 @@ class EqualityMembersRuleSpec {
|}
|
|override fun toString(): String {
| return "DataFuncTest(a=$a, b=$b)"
| return "DataFuncTest(" +
| "a=$a, " +
| "b=$b" +
| ")"
|}
|}
"""
@@ -388,7 +395,10 @@ class EqualityMembersRuleSpec {
|}
|
|override fun toString(): String {
| return "DataFuncTest(a=$a, b=$b)"
| return "DataFuncTest(" +
| "a=$a, " +
| "b=$b" +
| ")"
|}
|}
"""
@@ -450,7 +460,10 @@ class EqualityMembersRuleSpec {
|}
|
|override fun toString(): String {
| return "DataFuncTest(a=$a, b=$b)"
| return "DataFuncTest(" +
| "a=$a, " +
| "b=$b" +
| ")"
|}
|}
"""
@@ -520,7 +533,10 @@ class EqualityMembersRuleSpec {
|}
|
|override fun toString(): String {
| return "DataFuncTest(a=$a, b=$b)"
| return "DataFuncTest(" +
| "a=$a, " +
| "b=$b" +
| ")"
|}
|}
"""
@@ -638,8 +638,8 @@ internal class MissingApiStatusAnnotationRuleSpec {
"""
|import org.jetbrains.annotations.ApiStatus
|import org.jetbrains.jewel.foundation.InternalJewelApi
|@InternalJewelApi
|@ApiStatus.Internal
|@InternalJewelApi
|class MyClass
"""
.trimMargin()
@@ -668,8 +668,8 @@ internal class MissingApiStatusAnnotationRuleSpec {
"""
|import org.jetbrains.annotations.ApiStatus
|import org.jetbrains.jewel.foundation.ExperimentalJewelApi
|@ExperimentalJewelApi
|@ApiStatus.Experimental
|@ExperimentalJewelApi
|class MyClass
"""
.trimMargin()
@@ -698,8 +698,8 @@ internal class MissingApiStatusAnnotationRuleSpec {
"""
|import org.jetbrains.annotations.ApiStatus
|import org.jetbrains.jewel.foundation.InternalJewelApi
|@InternalJewelApi
|@ApiStatus.Internal
|@InternalJewelApi
|fun myFunction() {}
"""
.trimMargin()
@@ -728,8 +728,8 @@ internal class MissingApiStatusAnnotationRuleSpec {
"""
|import org.jetbrains.annotations.ApiStatus
|import org.jetbrains.jewel.foundation.ExperimentalJewelApi
|@ExperimentalJewelApi
|@ApiStatus.Experimental
|@ExperimentalJewelApi
|fun myFunction() {}
"""
.trimMargin()
@@ -758,8 +758,8 @@ internal class MissingApiStatusAnnotationRuleSpec {
"""
|import org.jetbrains.annotations.ApiStatus
|import org.jetbrains.jewel.foundation.InternalJewelApi
|@InternalJewelApi
|@ApiStatus.Internal
|@InternalJewelApi
|val myVal = 0
"""
.trimMargin()
@@ -788,8 +788,8 @@ internal class MissingApiStatusAnnotationRuleSpec {
"""
|import org.jetbrains.annotations.ApiStatus
|import org.jetbrains.jewel.foundation.ExperimentalJewelApi
|@ExperimentalJewelApi
|@ApiStatus.Experimental
|@ExperimentalJewelApi
|val myVal = 0
"""
.trimMargin()
@@ -818,8 +818,8 @@ internal class MissingApiStatusAnnotationRuleSpec {
"""
|import org.jetbrains.annotations.ApiStatus
|import org.jetbrains.jewel.foundation.InternalJewelApi
|@InternalJewelApi
|@ApiStatus.Internal
|@InternalJewelApi
|typealias MyAlias = String
"""
.trimMargin()
@@ -848,8 +848,8 @@ internal class MissingApiStatusAnnotationRuleSpec {
"""
|import org.jetbrains.annotations.ApiStatus
|import org.jetbrains.jewel.foundation.ExperimentalJewelApi
|@ExperimentalJewelApi
|@ApiStatus.Experimental
|@ExperimentalJewelApi
|typealias MyAlias = String
"""
.trimMargin()
@@ -878,8 +878,8 @@ internal class MissingApiStatusAnnotationRuleSpec {
"""
|import org.jetbrains.annotations.ApiStatus
|import org.jetbrains.jewel.foundation.InternalJewelApi
|@InternalJewelApi
|@ApiStatus.Internal
|@InternalJewelApi
|object MyObject
"""
.trimMargin()
@@ -907,8 +907,8 @@ internal class MissingApiStatusAnnotationRuleSpec {
"""
|import org.jetbrains.annotations.ApiStatus
|import org.jetbrains.jewel.foundation.ExperimentalJewelApi
|class MyClass @ExperimentalJewelApi
|@ApiStatus.Experimental constructor()
|class MyClass @ApiStatus.Experimental
|@ExperimentalJewelApi constructor()
"""
.trimMargin()
)
@@ -939,8 +939,8 @@ internal class MissingApiStatusAnnotationRuleSpec {
|import org.jetbrains.annotations.ApiStatus
|import org.jetbrains.jewel.foundation.InternalJewelApi
|class MyClass {
| @InternalJewelApi
|@ApiStatus.Internal
| @ApiStatus.Internal
|@InternalJewelApi
| constructor()
|}
"""
@@ -973,8 +973,8 @@ internal class MissingApiStatusAnnotationRuleSpec {
|import org.jetbrains.annotations.ApiStatus
|import org.jetbrains.jewel.foundation.ExperimentalJewelApi
|class MyClass {
| @ExperimentalJewelApi
|@ApiStatus.Experimental
| @ApiStatus.Experimental
|@ExperimentalJewelApi
| init {}
|}
"""
@@ -1009,8 +1009,8 @@ internal class MissingApiStatusAnnotationRuleSpec {
|import org.jetbrains.jewel.foundation.InternalJewelApi
|class MyClass {
| val myVal: Int
| @InternalJewelApi
|@ApiStatus.Internal
| @ApiStatus.Internal
|@InternalJewelApi
| get() = 1
|}
"""
@@ -1045,8 +1045,8 @@ internal class MissingApiStatusAnnotationRuleSpec {
|import org.jetbrains.jewel.foundation.ExperimentalJewelApi
|class MyClass {
| var myVal: Int = 1
| @ExperimentalJewelApi
|@ApiStatus.Experimental
| @ApiStatus.Experimental
|@ExperimentalJewelApi
| set(value) {}
|}
"""
@@ -1075,8 +1075,8 @@ internal class MissingApiStatusAnnotationRuleSpec {
"""
|import org.jetbrains.annotations.ApiStatus
|import org.jetbrains.jewel.foundation.InternalJewelApi
|fun myFunction(@InternalJewelApi
|@ApiStatus.Internal param: Int) {}
|fun myFunction(@ApiStatus.Internal
|@InternalJewelApi param: Int) {}
"""
.trimMargin()
)
@@ -1104,8 +1104,8 @@ internal class MissingApiStatusAnnotationRuleSpec {
"""
|import org.jetbrains.annotations.ApiStatus
|import org.jetbrains.jewel.foundation.InternalJewelApi
|@InternalJewelApi
|@ApiStatus.Internal
|@InternalJewelApi
|interface MyInterface
"""
.trimMargin()
@@ -1134,8 +1134,8 @@ internal class MissingApiStatusAnnotationRuleSpec {
"""
|import org.jetbrains.annotations.ApiStatus
|import org.jetbrains.jewel.foundation.ExperimentalJewelApi
|@ExperimentalJewelApi
|@ApiStatus.Experimental
|@ExperimentalJewelApi
|enum class MyEnum
"""
.trimMargin()
@@ -1167,8 +1167,8 @@ internal class MissingApiStatusAnnotationRuleSpec {
|import org.jetbrains.annotations.ApiStatus
|import org.jetbrains.jewel.foundation.InternalJewelApi
|class MyClass {
| @InternalJewelApi
|@ApiStatus.Internal
| @ApiStatus.Internal
|@InternalJewelApi
| companion object
|}
"""
@@ -1201,8 +1201,8 @@ internal class MissingApiStatusAnnotationRuleSpec {
|import org.jetbrains.annotations.ApiStatus
|import org.jetbrains.jewel.foundation.ExperimentalJewelApi
|class MyClass(
| @ExperimentalJewelApi
|@ApiStatus.Experimental
| @ApiStatus.Experimental
|@ExperimentalJewelApi
| val myVal: Int
|)
"""
@@ -1239,10 +1239,10 @@ internal class MissingApiStatusAnnotationRuleSpec {
|import org.jetbrains.annotations.ApiStatus
|import org.jetbrains.jewel.foundation.InternalJewelApi
|import org.jetbrains.jewel.foundation.ExperimentalJewelApi
|@ExperimentalJewelApi
|@ApiStatus.Internal
|@InternalJewelApi
|@ApiStatus.Experimental
|@ExperimentalJewelApi
|class MismatchedAnnotation
"""
.trimMargin()
@@ -1278,9 +1278,9 @@ internal class MissingApiStatusAnnotationRuleSpec {
|import org.jetbrains.jewel.foundation.ExperimentalJewelApi
|import org.jetbrains.jewel.foundation.InternalJewelApi
|@ApiStatus.Experimental
|@InternalJewelApi
|@ExperimentalJewelApi
|@ApiStatus.Internal
|@InternalJewelApi
|class MismatchedAnnotation
"""
.trimMargin()
@@ -6,6 +6,7 @@ import com.intellij.openapi.application.ApplicationManager
import com.intellij.psi.impl.source.tree.TreeCopyHandler
import dev.detekt.api.Finding
import dev.detekt.api.Rule
import dev.detekt.api.modifiedText
import dev.detekt.test.FakeLanguageVersionSettings
import dev.detekt.test.utils.compileContentForTest
import org.assertj.core.api.Assertions.assertThat
@@ -28,7 +29,7 @@ internal fun Rule.lintAndFix(@Language("kotlin") code: String): Pair<List<Findin
val ktFile = compileContentForTest(code)
ensurePsiMutationSupported()
val findings = visitFile(ktFile, FakeLanguageVersionSettings())
return findings to ktFile.text
return findings to (ktFile.modifiedText ?: ktFile.text)
}
internal fun ObjectAssert<Finding>.hasMessage(message: String) =
@@ -1,7 +1,7 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.jewel.detekt
import dev.detekt.test.TestConfig
import dev.detekt.api.Config
import dev.detekt.test.lint
import org.assertj.core.api.Assertions.assertThat
import org.jetbrains.jewel.detekt.rules.EqualityMembersRule
@@ -13,7 +13,7 @@ import org.junit.jupiter.api.Test
class UtilsTest {
@Test
fun `isJewelSymbol should return true for exact org_jetbrains_jewel package`() {
val rule = EqualityMembersRule(TestConfig())
val rule = EqualityMembersRule(Config.empty)
val code =
"""
|package org.jetbrains.jewel
@@ -32,7 +32,7 @@ class UtilsTest {
@Test
fun `isJewelSymbol should return true for org_jetbrains_jewel subpackages`() {
val rule = EqualityMembersRule(TestConfig())
val rule = EqualityMembersRule(Config.empty)
val code =
"""
|package org.jetbrains.jewel.foundation
@@ -51,7 +51,7 @@ class UtilsTest {
@Test
fun `isJewelSymbol should return true for deeply nested org_jetbrains_jewel subpackages`() {
val rule = EqualityMembersRule(TestConfig())
val rule = EqualityMembersRule(Config.empty)
val code =
"""
|package org.jetbrains.jewel.ui.component
@@ -70,7 +70,7 @@ class UtilsTest {
@Test
fun `isJewelSymbol should return true for no package declaration`() {
val rule = EqualityMembersRule(TestConfig())
val rule = EqualityMembersRule(Config.empty)
val code =
"""
|annotation class GenerateDataFunctions
@@ -87,7 +87,7 @@ class UtilsTest {
@Test
fun `isJewelSymbol should return false for non-jewel packages`() {
val rule = EqualityMembersRule(TestConfig())
val rule = EqualityMembersRule(Config.empty)
val code =
"""
|package com.example.other
@@ -106,7 +106,7 @@ class UtilsTest {
@Test
fun `MissingApiStatusAnnotationRule should work with exact org_jetbrains_jewel package`() {
val rule = MissingApiStatusAnnotationRule(TestConfig())
val rule = MissingApiStatusAnnotationRule(Config.empty)
val code =
"""
|package org.jetbrains.jewel
@@ -125,7 +125,7 @@ class UtilsTest {
@Test
fun `MissingApiStatusAnnotationRule should work with Jewel subpackages`() {
val rule = MissingApiStatusAnnotationRule(TestConfig())
val rule = MissingApiStatusAnnotationRule(Config.empty)
val code =
"""
|package org.jetbrains.jewel.foundation
@@ -144,7 +144,7 @@ class UtilsTest {
@Test
fun `MissingApiStatusAnnotationRule should work with root package`() {
val rule = MissingApiStatusAnnotationRule(TestConfig())
val rule = MissingApiStatusAnnotationRule(Config.empty)
val code =
"""
|import org.jetbrains.jewel.foundation.InternalJewelApi
@@ -161,7 +161,7 @@ class UtilsTest {
@Test
fun `MissingApiStatusAnnotationRule should not run for non-jewel packages`() {
val rule = MissingApiStatusAnnotationRule(TestConfig())
val rule = MissingApiStatusAnnotationRule(Config.empty)
val code =
"""
|package com.example.other
+49 -3
View File
@@ -1,7 +1,8 @@
config:
validation: true
warningsAsErrors: false
# when writing own rules with new properties, exclude the property path e.g.: 'my_rule_set,.*>.*>[my_property]'
excludes: []
excludes: [ 'jewel>.*>.*' ]
processors:
active: true
@@ -23,7 +24,48 @@ console-reports:
- 'FileBasedFindingsReport'
comments:
active: false
active: true
# AbsentOrWrongFileLicense:
# active: false
# licenseTemplateFile: 'license.template'
# licenseTemplateIsRegex: false
# CommentOverPrivateFunction:
# active: false
# CommentOverPrivateProperty:
# active: false
# DeprecatedBlockTag:
# active: false
# EndOfSentenceFormat:
# active: false
# endOfSentenceFormat: '([.?!][ \t\n\r\f<])|([.?!:]$)'
# KDocReferencesNonPublicProperty:
# active: false
# excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**' ]
OutdatedDocumentation:
active: true
matchTypeParameters: true
matchDeclarationsOrder: true
allowParamOnConstructorProperties: true
UndocumentedPublicClass:
active: true
excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**', '**/generated/**' ]
searchInNestedClass: true
searchInInnerClass: true
searchInInnerObject: true
searchInInnerInterface: true
searchInProtectedClass: false
ignoreDefaultCompanionObject: false
ignoreAnnotated: [ 'Deprecated', 'InternalJewelApi' ]
UndocumentedPublicFunction:
active: true
excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**', '**/generated/**' ]
searchProtectedFunction: false
ignoreAnnotated: [ 'Deprecated', 'InternalJewelApi' ]
UndocumentedPublicProperty:
active: true
excludes: [ '**/test/**', '**/androidTest/**', '**/commonTest/**', '**/jvmTest/**', '**/androidUnitTest/**', '**/androidInstrumentedTest/**', '**/jsTest/**', '**/iosTest/**', '**/generated/**' ]
searchProtectedProperty: false
ignoreAnnotated: [ 'Deprecated', 'InternalJewelApi' ]
complexity:
active: true
@@ -93,7 +135,6 @@ style:
active: true
ExpressionBodySyntax:
active: true
autoCorrect: true
includeLineWrapping: false
ForbiddenComment:
active: true
@@ -175,10 +216,15 @@ naming:
active: false
ignoreAnnotated:
- Composable
jewel:
EqualityMembersRule:
active: true
autoCorrect: true
annotated:
- GenerateDataFunctions
MissingApiStatusAnnotationRule:
active: true
autoCorrect: true
Compose:
@@ -52,9 +52,11 @@ public class DisabledAppearanceValues(public val brightness: Int, public val con
override fun toString(): String = "GrayFilterValues(brightness=$brightness, contrast=$contrast, alpha=$alpha)"
/** Companion object for [DisabledAppearanceValues]. */
public companion object
}
/** The composition local that provides [DisabledAppearanceValues] to the composition tree. */
public val LocalDisabledAppearanceValues: ProvidableCompositionLocal<DisabledAppearanceValues> =
staticCompositionLocalOf {
error("No DisabledAppearanceValues provided. Have you forgotten the theme?")
@@ -69,6 +69,7 @@ public class GlobalColors(
"toolwindowBackground=$toolwindowBackground" +
")"
/** Companion object for [GlobalColors]. */
public companion object
}
@@ -138,6 +139,7 @@ public class TextColors(
"TextColors(normal=$normal, selected=$selected, disabled=$disabled, disabledSelected=$disabledSelected, " +
"info=$info, error=$error, warning=$warning)"
/** Companion object for [TextColors]. */
public companion object
}
@@ -173,6 +175,7 @@ public class BorderColors(public val normal: Color, public val focused: Color, p
override fun toString(): String = "BorderColors(normal=$normal, focused=$focused, disabled=$disabled)"
/** Companion object for [BorderColors]. */
public companion object
}
@@ -227,6 +230,7 @@ public class OutlineColors(
"error=$error" +
")"
/** Companion object for [OutlineColors]. */
public companion object
}
@@ -5,9 +5,15 @@ import androidx.compose.runtime.ProvidableCompositionLocal
import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.unit.Dp
/** Global layout metrics shared across all Jewel components, defining the default outline width and row height. */
@Immutable
@GenerateDataFunctions
public class GlobalMetrics(public val outlineWidth: Dp, public val rowHeight: Dp) {
public class GlobalMetrics(
/** The width of the focus outline drawn around focusable components. */
public val outlineWidth: Dp,
/** The default height of a single row in list-like components. */
public val rowHeight: Dp,
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
@@ -28,9 +34,11 @@ public class GlobalMetrics(public val outlineWidth: Dp, public val rowHeight: Dp
override fun toString(): String = "GlobalMetrics(outlineWidth=$outlineWidth, rowHeight=$rowHeight)"
/** Companion object for [GlobalMetrics]. */
public companion object
}
/** Composition local providing the current [GlobalMetrics] for the active theme. */
public val LocalGlobalMetrics: ProvidableCompositionLocal<GlobalMetrics> = staticCompositionLocalOf {
error("No GlobalMetrics provided. Have you forgotten the theme?")
}
@@ -7,20 +7,30 @@ import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.graphics.isUnspecified
import androidx.compose.ui.unit.Dp
/**
* Describes how a component's stroke (border) is drawn. Use [Stroke.None] for no stroke, [Stroke.Solid] for a
* single-color stroke, or [Stroke.Brush] for a gradient stroke.
*/
@Suppress("AbstractClassCanBeInterface") // Binary compatibility: sealed class cannot be changed to interface
public sealed class Stroke {
/** No stroke; the component has no visible border. */
@Immutable
public object None : Stroke() {
override fun toString(): String = "None"
}
/** A stroke drawn with a single solid [color]. */
@Immutable
@GenerateDataFunctions
public class Solid
internal constructor(
/** The width of the stroke. */
public val width: Dp,
/** The solid color of the stroke. */
public val color: Color,
/** Where the stroke is drawn relative to the component bounds. */
public val alignment: Alignment,
/** The amount by which to expand the stroke beyond the component bounds. */
public val expand: Dp,
) : Stroke() {
override fun equals(other: Any?): Boolean {
@@ -48,13 +58,18 @@ public sealed class Stroke {
override fun toString(): String = "Solid(width=$width, color=$color, alignment=$alignment, expand=$expand)"
}
/** A stroke drawn with a [Brush][androidx.compose.ui.graphics.Brush], allowing gradient effects. */
@Immutable
@GenerateDataFunctions
public class Brush
internal constructor(
/** The width of the stroke. */
public val width: Dp,
/** The brush used to paint the stroke. */
public val brush: androidx.compose.ui.graphics.Brush,
/** Where the stroke is drawn relative to the component bounds. */
public val alignment: Alignment,
/** The amount by which to expand the stroke beyond the component bounds. */
public val expand: Dp,
) : Stroke() {
override fun equals(other: Any?): Boolean {
@@ -82,13 +97,26 @@ public sealed class Stroke {
override fun toString(): String = "Brush(width=$width, brush=$brush, alignment=$alignment, expand=$expand)"
}
/** Controls where the stroke is drawn relative to the component's bounds. */
public enum class Alignment {
/** The stroke is drawn inside the component bounds. */
Inside,
/** The stroke is centered on the component bounds edge. */
Center,
/** The stroke is drawn outside the component bounds. */
Outside,
}
}
/**
* Creates a [Stroke] from a solid [color]. Returns [Stroke.None] if [width] is zero or [color] is
* [Color.Unspecified][androidx.compose.ui.graphics.Color.Unspecified].
*
* @param width The width of the stroke.
* @param color The solid color of the stroke.
* @param alignment Where the stroke is drawn relative to the component bounds.
* @param expand Optional amount by which to expand the stroke beyond the component bounds.
*/
public fun Stroke(width: Dp, color: Color, alignment: Stroke.Alignment, expand: Dp = Dp.Unspecified): Stroke {
if (width.value == 0f) return Stroke.None
if (color.isUnspecified) return Stroke.None
@@ -96,6 +124,15 @@ public fun Stroke(width: Dp, color: Color, alignment: Stroke.Alignment, expand:
return Stroke.Solid(width, color, alignment, expand)
}
/**
* Creates a [Stroke] from a [Brush]. Returns [Stroke.None] if [width] is zero or the brush is a
* [SolidColor][androidx.compose.ui.graphics.SolidColor] with an unspecified color.
*
* @param width The width of the stroke.
* @param brush The brush used to paint the stroke.
* @param alignment Where the stroke is drawn relative to the component bounds.
* @param expand Optional amount by which to expand the stroke beyond the component bounds.
*/
public fun Stroke(width: Dp, brush: Brush, alignment: Stroke.Alignment, expand: Dp = Dp.Unspecified): Stroke {
if (width.value == 0f) return Stroke.None
return when (brush) {
@@ -1,7 +1,10 @@
package org.jetbrains.jewel.foundation.actionSystem
/** A context used to supply data entries to the IntelliJ Platform action system from within a Compose component. */
public interface DataProviderContext {
/** Registers an eager data [value] for the given [key] in the action system context. */
public fun <TValue : Any> set(key: String, value: TValue?)
/** Registers a lazily-initialized value for the given [key]; [initializer] is invoked on first access. */
public fun <TValue : Any> lazy(key: String, initializer: () -> TValue?)
}
@@ -7,9 +7,13 @@ import androidx.compose.ui.node.TraversableNode
import org.jetbrains.annotations.ApiStatus
import org.jetbrains.jewel.foundation.InternalJewelApi
/**
* A [Modifier.Node] that tracks focus and exposes data to the IntelliJ Platform action system via a
* [DataProviderContext] lambda.
*/
@InternalJewelApi
@ApiStatus.Internal
public class DataProviderNode(@Suppress("DEPRECATION") public var dataProvider: DataProviderContext.() -> Unit) :
public class DataProviderNode(public var dataProvider: DataProviderContext.() -> Unit) :
Modifier.Node(), FocusEventModifierNode, TraversableNode {
public var hasFocus: Boolean = false
@@ -19,5 +23,6 @@ public class DataProviderNode(@Suppress("DEPRECATION") public var dataProvider:
override val traverseKey: TraverseKey = TraverseKey
/** The traversal key used to locate [DataProviderNode] instances in the Modifier node tree. */
public companion object TraverseKey
}
@@ -99,6 +99,11 @@ private val ALREADY_NORMALIZED_BUILTIN_TYPES =
)
@JvmInline
public value class MimeType(private val mimeType: String) {
/**
* Returns a human-readable display name for this MIME type (e.g., `"Kotlin"`, `"Java"`, `"XML"`).
*
* @see Known
*/
@Deprecated(
message =
"The MimeType class is deprecated in favor of using the code block info strings (e.g., \"kt\", " +
@@ -247,6 +252,11 @@ public value class MimeType(private val mimeType: String) {
const val VALUE_MANIFEST = "manifest"
}
/**
* Predefined [MimeType] constants for well-known programming languages and content types.
*
* @see MimeType
*/
@Deprecated(
message =
"The MimeType class is deprecated in favor of using the code block info strings (e.g., \"kt\", " +
@@ -8,6 +8,10 @@ import org.jetbrains.annotations.ApiStatus
import org.jetbrains.jewel.foundation.ExperimentalJewelApi
import org.jetbrains.jewel.foundation.code.MimeType
/**
* A functional interface for applying syntax highlighting to source code. Returns a [kotlinx.coroutines.flow.Flow] of
* styled [androidx.compose.ui.text.AnnotatedString]s that can update in response to theme or color scheme changes.
*/
@ApiStatus.Experimental
@ExperimentalJewelApi
public interface CodeHighlighter {
@@ -55,6 +59,7 @@ public interface CodeHighlighter {
public fun highlight(code: String, language: String = ""): Flow<AnnotatedString>
}
/** The composition local that provides the current [CodeHighlighter] instance. */
@ExperimentalJewelApi
@get:ApiStatus.Experimental
public val LocalCodeHighlighter: ProvidableCompositionLocal<CodeHighlighter> = staticCompositionLocalOf {
@@ -7,6 +7,7 @@ import org.jetbrains.annotations.ApiStatus
import org.jetbrains.jewel.foundation.ExperimentalJewelApi
import org.jetbrains.jewel.foundation.code.MimeType
/** A [CodeHighlighter] that applies no syntax highlighting, returning the code as a plain unstyled string. */
@ApiStatus.Experimental
@ExperimentalJewelApi
public object NoOpCodeHighlighter : CodeHighlighter {
@@ -11,13 +11,18 @@ import androidx.compose.ui.input.pointer.isCtrlPressed
import androidx.compose.ui.input.pointer.isMetaPressed
import androidx.compose.ui.input.pointer.isShiftPressed
/** Defines the key bindings for navigating and selecting items in a selectable lazy column. */
public interface SelectableColumnKeybindings {
/** Whether the contiguous selection modifier key (e.g., Shift) is pressed in a key event. */
public val KeyEvent.isContiguousSelectionKeyPressed: Boolean
/** Whether the contiguous selection modifier key (e.g., Shift) is pressed in a pointer event. */
public val PointerKeyboardModifiers.isContiguousSelectionKeyPressed: Boolean
/** Whether the multi-selection modifier key (e.g., Ctrl or Meta) is pressed in a key event. */
public val KeyEvent.isMultiSelectionKeyPressed: Boolean
/** Whether the multi-selection modifier key (e.g., Ctrl or Meta) is pressed in a pointer event. */
public val PointerKeyboardModifiers.isMultiSelectionKeyPressed: Boolean
/** Select First Node. */
@@ -63,7 +68,9 @@ public interface SelectableColumnKeybindings {
public val KeyEvent.isSelectAll: Boolean
}
/** Default [SelectableColumnKeybindings] for macOS, using `Meta` (⌘) as the multi-selection modifier. */
public open class DefaultMacOsSelectableColumnKeybindings : DefaultSelectableColumnKeybindings() {
/** The default singleton instance for macOS. */
public companion object : DefaultMacOsSelectableColumnKeybindings()
override val KeyEvent.isMultiSelectionKeyPressed: Boolean
@@ -73,7 +80,12 @@ public open class DefaultMacOsSelectableColumnKeybindings : DefaultSelectableCol
get() = isMetaPressed
}
/**
* Default [SelectableColumnKeybindings] for Windows/Linux, using `Ctrl` for multi-selection and standard arrow/page
* keys.
*/
public open class DefaultSelectableColumnKeybindings : SelectableColumnKeybindings {
/** The default singleton instance. */
public companion object : DefaultSelectableColumnKeybindings()
override val KeyEvent.isContiguousSelectionKeyPressed: Boolean
@@ -6,7 +6,9 @@ import org.jetbrains.annotations.ApiStatus
import org.jetbrains.jewel.foundation.InternalJewelApi
import org.jetbrains.jewel.foundation.lazy.SelectableLazyListKey.Selectable
/** Defines the keyboard navigation actions for a selectable lazy column. */
public interface SelectableColumnOnKeyEvent {
/** The keybindings that define keyboard navigation actions for the selectable column. */
public val keybindings: SelectableColumnKeybindings
/** Select First Node. */
@@ -72,6 +74,13 @@ public interface SelectableColumnOnKeyEvent {
onSelectPreviousItem(keys, state, initialIndex - 1 downTo 0)
}
/**
* Selects the previous selectable item found among [possibleIndexes], updating [state] accordingly.
*
* @param keys All keys in the list.
* @param state The current selection state to update.
* @param possibleIndexes The candidate indices to search through, in the order they should be checked.
*/
@InternalJewelApi
@ApiStatus.Internal
public fun onSelectPreviousItem(
@@ -109,6 +118,13 @@ public interface SelectableColumnOnKeyEvent {
onSelectNextItem(keys, state, initialIndex + 1..keys.lastIndex)
}
/**
* Selects the next selectable item found among [possibleIndexes], updating [state] accordingly.
*
* @param keys All keys in the list.
* @param state The current selection state to update.
* @param possibleIndexes The candidate indices to search through, in the order they should be checked.
*/
@InternalJewelApi
@ApiStatus.Internal
public fun onSelectNextItem(
@@ -194,7 +210,9 @@ public interface SelectableColumnOnKeyEvent {
}
}
/** Default [SelectableColumnOnKeyEvent] implementation backed by a configurable [SelectableColumnKeybindings]. */
public open class DefaultSelectableOnKeyEvent(override val keybindings: SelectableColumnKeybindings) :
SelectableColumnOnKeyEvent {
/** The default singleton instance using [DefaultSelectableColumnKeybindings]. */
public companion object : DefaultSelectableOnKeyEvent(DefaultSelectableColumnKeybindings)
}
@@ -152,6 +152,16 @@ internal class SelectableLazyListScopeContainer : SelectableLazyListScope {
}
}
/**
* Convenience extension that adds all elements of [items] to this [SelectableLazyListScope].
*
* @param T The type of items in the list.
* @param items The list of items to add.
* @param key A function producing a stable unique key for each item. Defaults to the item itself.
* @param contentType A function returning the content type of each item, used for composition reuse.
* @param selectable A function returning whether each item is selectable. Defaults to `true`.
* @param itemContent The composable content for each item.
*/
public fun <T : Any> SelectableLazyListScope.items(
items: List<T>,
key: (item: T) -> Any = { it },
@@ -168,6 +178,16 @@ public fun <T : Any> SelectableLazyListScope.items(
)
}
/**
* Convenience extension that adds all elements of [items] with their indices to this [SelectableLazyListScope].
*
* @param T The type of items in the list.
* @param items The list of items to add.
* @param key A function producing a stable unique key for each item by index and value.
* @param contentType A function returning the content type of each item by index and value.
* @param selectable A function returning whether each item is selectable by index and value.
* @param itemContent The composable content for each item, receiving both the index and the item.
*/
public fun <T : Any> SelectableLazyListScope.itemsIndexed(
items: List<T>,
key: (index: Int, item: T) -> Any = { _, item -> item },
@@ -184,6 +204,12 @@ public fun <T : Any> SelectableLazyListScope.itemsIndexed(
)
}
/**
* Creates a [SelectableLazyItemScope] for this [LazyItemScope], decorating it with selection and focus state.
*
* @param isSelected Whether this item is currently selected.
* @param isActive Whether this item's parent list is currently focused.
*/
@Composable
public fun LazyItemScope.SelectableLazyItemScope(
isSelected: Boolean = false,
@@ -15,14 +15,18 @@ import org.jetbrains.jewel.foundation.util.JewelLogger
private val logger = JewelLogger.getInstance(SelectableLazyListState::class.java)
/** The index range of currently visible items in this [LazyListState]. */
@Suppress("unused")
public val LazyListState.visibleItemsRange: IntRange
get() = firstVisibleItemIndex until firstVisibleItemIndex + layoutInfo.visibleItemsInfo.size
/** The index range of currently visible items in this [SelectableLazyListState]. */
public val SelectableLazyListState.visibleItemsRange: IntRange
get() = firstVisibleItemIndex until firstVisibleItemIndex + layoutInfo.visibleItemsInfo.size
/** Exposes mutable [selectedKeys] to composables and state holders managing a selectable list. */
public interface SelectableScope {
/** The set of keys currently selected in the list. */
public var selectedKeys: Set<Any>
}
@@ -63,8 +67,10 @@ public constructor(
/** Flag indicating whether the user is currently navigating via keyboard */
public var isKeyboardNavigating: Boolean by mutableStateOf(false)
/** The set of keys currently selected in the list. */
override var selectedKeys: Set<Any> by mutableStateOf(initialSelectedKeys)
/** The index of the last item that was made active, or null if no item has been activated yet. */
public var lastActiveItemIndex: Int? = null
/**
@@ -90,6 +96,7 @@ public constructor(
lastActiveItemIndex = itemIndex
}
/** Layout information about the currently visible items and overall list state. */
public val layoutInfo: LazyListLayoutInfo
get() = lazyListState.layoutInfo
@@ -113,6 +120,10 @@ public constructor(
get() = lazyListState.interactionSource
}
/**
* Type-safe state holder for single-selection lazy lists, enforcing [SelectionMode.Single] semantics. Delegates scroll
* and layout to an underlying [SelectableLazyListState].
*/
public class SingleSelectionLazyListState internal constructor(internal val delegate: SelectableLazyListState) :
ScrollableState by delegate, SelectableScope {
/**
@@ -138,12 +149,15 @@ public class SingleSelectionLazyListState internal constructor(internal val dele
)
)
/** The underlying [LazyListState] used for scroll and layout. */
public val lazyListState: LazyListState
get() = delegate.lazyListState
/** The selection mode, always [SelectionMode.Single] for this state. */
public val selectionMode: SelectionMode
get() = SelectionMode.Single
/** The set of keys currently selected; enforces at most one key. */
override var selectedKeys: Set<Any>
get() = delegate.selectedKeys
set(value) {
@@ -156,36 +170,56 @@ public class SingleSelectionLazyListState internal constructor(internal val dele
delegate.selectedKeys = if (value.isEmpty()) emptySet() else setOf(value.first())
}
/** Whether the user is currently navigating via keyboard. */
public var isKeyboardNavigating: Boolean
get() = delegate.isKeyboardNavigating
set(value) {
delegate.isKeyboardNavigating = value
}
/** The index of the last item that was made active, or null if no item has been activated yet. */
public var lastActiveItemIndex: Int?
get() = delegate.lastActiveItemIndex
set(value) {
delegate.lastActiveItemIndex = value
}
/**
* Scrolls to the item at [itemIndex], optionally animating and applying a [scrollOffset].
*
* @param itemIndex The index of the item to scroll to.
* @param animateScroll Whether to animate the scroll. Defaults to `false`.
* @param scrollOffset Offset from the start of the item. Defaults to `0`.
*/
public suspend fun scrollToItem(itemIndex: Int, animateScroll: Boolean = false, scrollOffset: Int = 0) {
delegate.scrollToItem(itemIndex, animateScroll, scrollOffset)
}
/** Layout information about the currently visible items and overall list state. */
public val layoutInfo: LazyListLayoutInfo
get() = delegate.layoutInfo
/** The index of the first item that is visible. */
public val firstVisibleItemIndex: Int
get() = delegate.firstVisibleItemIndex
/** The scroll offset of the first visible item. */
@Suppress("unused")
public val firstVisibleItemScrollOffset: Int
get() = delegate.firstVisibleItemScrollOffset
/**
* [InteractionSource] that will be used to dispatch drag events when this list is being dragged. If you want to
* know whether the fling (or animated scroll) is in progress, use [isScrollInProgress].
*/
public val interactionSource: InteractionSource
get() = delegate.interactionSource
}
/**
* Type-safe state holder for multi-selection lazy lists, enforcing [SelectionMode.Multiple] semantics. Delegates scroll
* and layout to an underlying [SelectableLazyListState].
*/
public class MultiSelectionLazyListState internal constructor(internal val delegate: SelectableLazyListState) :
ScrollableState by delegate, SelectableScope {
/**
@@ -211,44 +245,63 @@ public class MultiSelectionLazyListState internal constructor(internal val deleg
)
)
/** The underlying [LazyListState] used for scroll and layout. */
public val lazyListState: LazyListState
get() = delegate.lazyListState
/** The selection mode, always [SelectionMode.Multiple] for this state. */
public val selectionMode: SelectionMode
get() = SelectionMode.Multiple
/** The set of keys currently selected in the list. */
override var selectedKeys: Set<Any>
get() = delegate.selectedKeys
set(value) {
delegate.selectedKeys = value
}
/** Whether the user is currently navigating via keyboard. */
public var isKeyboardNavigating: Boolean
get() = delegate.isKeyboardNavigating
set(value) {
delegate.isKeyboardNavigating = value
}
/** The index of the last item that was made active, or null if no item has been activated yet. */
public var lastActiveItemIndex: Int?
get() = delegate.lastActiveItemIndex
set(value) {
delegate.lastActiveItemIndex = value
}
/**
* Scrolls to the item at [itemIndex], optionally animating and applying a [scrollOffset].
*
* @param itemIndex The index of the item to scroll to.
* @param animateScroll Whether to animate the scroll. Defaults to `false`.
* @param scrollOffset Offset from the start of the item. Defaults to `0`.
*/
public suspend fun scrollToItem(itemIndex: Int, animateScroll: Boolean = false, scrollOffset: Int = 0) {
delegate.scrollToItem(itemIndex, animateScroll, scrollOffset)
}
/** Layout information about the currently visible items and overall list state. */
public val layoutInfo: LazyListLayoutInfo
get() = delegate.layoutInfo
/** The index of the first item that is visible. */
public val firstVisibleItemIndex: Int
get() = delegate.firstVisibleItemIndex
/** The scroll offset of the first visible item. */
@Suppress("unused")
public val firstVisibleItemScrollOffset: Int
get() = delegate.firstVisibleItemScrollOffset
/**
* [InteractionSource] that will be used to dispatch drag events when this list is being dragged. If you want to
* know whether the fling (or animated scroll) is in progress, use [isScrollInProgress].
*/
public val interactionSource: InteractionSource
get() = delegate.interactionSource
}
@@ -292,8 +345,15 @@ public sealed class SelectableLazyListKey {
override fun hashCode(): Int = key.hashCode()
}
/** Extends [LazyItemScope] with [isSelected] and [isActive] flags for items inside a selectable lazy column. */
public interface SelectableLazyItemScope : LazyItemScope {
/** Whether this item is currently selected. */
public val isSelected: Boolean
/**
* Whether this item's parent list is currently focused. This reflects the list-wide focus state and is the same for
* every item in the list.
*/
public val isActive: Boolean
}
@@ -49,6 +49,7 @@ import org.jetbrains.jewel.foundation.state.SelectableComponentState
/**
* Renders a lazy tree view based on the provided tree data structure.
*
* @param T the type of data held by each tree element.
* @param tree The tree structure to be rendered.
* @param selectionMode The selection mode for the tree nodes.
* @param onElementClick Callback function triggered when a tree node is clicked.
@@ -127,6 +128,7 @@ public fun <T> BasicLazyTree(
/**
* Renders a lazy tree view based on the provided tree data structure.
*
* @param T the type of data held by each tree element.
* @param tree The tree structure to be rendered.
* @param elementBackgroundFocused The background color of a tree node when focused.
* @param elementBackgroundSelectedFocused The background color of a selected tree node when focused.
@@ -333,9 +335,16 @@ private fun Modifier.elementBackground(
shape = backgroundShape,
)
/**
* Encodes the visual state of a tree element as a bit mask, including enabled, focused, expanded, pressed, hovered,
* active, and selected flags.
*/
@Immutable
@JvmInline
public value class TreeElementState(public val state: ULong) : FocusableComponentState, SelectableComponentState {
public value class TreeElementState(
/** The raw bit mask encoding all state flags for this tree element. */
public val state: ULong
) : FocusableComponentState, SelectableComponentState {
@Stable
override val isActive: Boolean
get() = state and Active != 0UL
@@ -360,6 +369,7 @@ public value class TreeElementState(public val state: ULong) : FocusableComponen
override val isSelected: Boolean
get() = state and Selected != 0UL
/** Whether the node is expanded. */
@Stable
public val isExpanded: Boolean
get() = state and Expanded != 0UL
@@ -368,6 +378,17 @@ public value class TreeElementState(public val state: ULong) : FocusableComponen
"${javaClass.simpleName}(enabled=$isEnabled, focused=$isFocused, expanded=$isExpanded, " +
"pressed=$isPressed, hovered=$isHovered, active=$isActive, selected=$isSelected)"
/**
* Returns a copy of this [TreeElementState] with the given fields replaced by their new values.
*
* @param enabled Whether the element is enabled.
* @param focused Whether the element is focused.
* @param expanded Whether the element is expanded.
* @param pressed Whether the element is pressed.
* @param hovered Whether the element is hovered.
* @param active Whether the element's parent list is active (focused).
* @param selected Whether the element is selected.
*/
public fun copy(
enabled: Boolean = isEnabled,
focused: Boolean = isFocused,
@@ -387,11 +408,23 @@ public value class TreeElementState(public val state: ULong) : FocusableComponen
selected = selected,
)
/** State bit constants and the [of] factory for constructing [TreeElementState] values. */
public companion object {
private const val EXPANDED_BIT_OFFSET = CommonStateBitMask.FIRST_AVAILABLE_OFFSET
private val Expanded = 1UL shl EXPANDED_BIT_OFFSET
/**
* Constructs a [TreeElementState] from individual boolean flags.
*
* @param enabled Whether the element is enabled.
* @param focused Whether the element is focused.
* @param expanded Whether the node is expanded.
* @param hovered Whether the element is hovered.
* @param pressed Whether the element is pressed.
* @param active Whether the element's parent list is active (focused).
* @param selected Whether the element is selected.
*/
public fun of(
enabled: Boolean = true,
focused: Boolean = false,
@@ -4,15 +4,29 @@ import java.io.File
import java.nio.file.Path
import org.jetbrains.jewel.foundation.GenerateDataFunctions
/**
* Builds a [Tree] using a [TreeBuilder] DSL, then constructs and returns the resulting tree.
*
* @param T The type of data held by each tree element.
* @param builder A lambda with receiver [TreeBuilder] where root entries are declared.
*/
public fun <T> buildTree(builder: TreeBuilder<T>.() -> Unit): Tree<T> = TreeBuilder<T>().apply(builder).build()
/** A DSL builder for constructing a [Tree], used via [buildTree]. */
public class TreeBuilder<T> : TreeGeneratorScope<T> {
/** A sealed class representing either a [Leaf] or [Node] entry added to a [TreeBuilder]. */
@Suppress("AbstractClassCanBeInterface") // Binary compatibility: sealed class cannot be changed to interface
public sealed class Element<T> {
/** The stable identifier for this element, or null if none was provided. */
public abstract val id: Any?
/** A leaf entry in a [TreeBuilder], holding [data] with no children. */
@GenerateDataFunctions
public class Leaf<T>(public val data: T, override val id: Any?) : Element<T>() {
public class Leaf<T>(
/** The data held by this leaf. */
public val data: T,
override val id: Any?,
) : Element<T>() {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
@@ -34,10 +48,13 @@ public class TreeBuilder<T> : TreeGeneratorScope<T> {
override fun toString(): String = "Leaf(data=$data, id=$id)"
}
/** A node entry in a [TreeBuilder], holding [data] and a lambda that generates its children. */
@GenerateDataFunctions
public class Node<T>(
/** The data held by this node. */
public val data: T,
override val id: Any?,
/** The lambda invoked to populate this node's children when the node is expanded. */
public val childrenGenerator: ChildrenGeneratorScope<T>.() -> Unit,
) : Element<T>() {
override fun equals(other: Any?): Boolean {
@@ -78,6 +95,7 @@ public class TreeBuilder<T> : TreeGeneratorScope<T> {
heads.add(element)
}
/** Constructs and returns the [Tree] from all root entries added to this builder. */
public fun build(): Tree<T> {
val elements = mutableListOf<Tree.Element<T>>()
for (index in heads.indices) {
@@ -167,17 +185,30 @@ private fun <T> evaluatePrevious(element: Tree.Element<T>): Tree.Element<T> =
}
}
/** A DSL scope for adding [TreeBuilder.Element.Leaf] and [TreeBuilder.Element.Node] entries to a tree or subtree. */
public interface TreeGeneratorScope<T> {
/** Adds a node with [data], an optional stable [id], and a [childrenGenerator] that populates its subtree. */
public fun addNode(data: T, id: Any? = null, childrenGenerator: ChildrenGeneratorScope<T>.() -> Unit = {})
/** Adds a leaf entry with [data] and an optional stable [id]. */
public fun addLeaf(data: T, id: Any? = null)
/** Adds a pre-built [element] (either a [TreeBuilder.Element.Leaf] or [TreeBuilder.Element.Node]) directly. */
public fun add(element: TreeBuilder.Element<T>)
}
/** A [TreeGeneratorScope] used inside a node's children generator lambda, providing access to [parent] info. */
public class ChildrenGeneratorScope<T>(private val parentElement: Tree.Element.Node<T>) : TreeGeneratorScope<T> {
/** Holds identifying information about a node's parent: its data, depth in the tree, and child index. */
@GenerateDataFunctions
public class ParentInfo<T>(public val data: T, public val depth: Int, public val index: Int) {
public class ParentInfo<T>(
/** The data held by the parent node. */
public val data: T,
/** The depth of the parent node in the tree (0 = root level). */
public val depth: Int,
/** The child index of the parent node within its own parent's children. */
public val index: Int,
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
@@ -201,6 +232,7 @@ public class ChildrenGeneratorScope<T>(private val parentElement: Tree.Element.N
override fun toString(): String = "ParentInfo(data=$data, depth=$depth, index=$index)"
}
/** Information about the parent node of the current scope. */
public val parent: ParentInfo<T> by lazy {
ParentInfo(parentElement.data, parentElement.depth, parentElement.childIndex)
}
@@ -220,8 +252,22 @@ public class ChildrenGeneratorScope<T>(private val parentElement: Tree.Element.N
}
}
/**
* Converts this [Path] into a [Tree] of [File] nodes, recursively expanding directories.
*
* @param isOpen A predicate whose boolean result is used as the id of the root file/directory node. Note: it does not
* control the node's initial expansion state; nodes are always created collapsed and expanded lazily via
* [Tree.Element.Node.open].
*/
public fun Path.asTree(isOpen: (File) -> Boolean = { false }): Tree<File> = toFile().asTree(isOpen)
/**
* Converts this [File] into a [Tree] of [File] nodes, recursively expanding directories.
*
* @param isOpen A predicate whose boolean result is used as the id of the root file/directory node. Note: it does not
* control the node's initial expansion state; nodes are always created collapsed and expanded lazily via
* [Tree.Element.Node.open].
*/
public fun File.asTree(isOpen: (File) -> Boolean = { false }): Tree<File> = buildTree {
addNode(this@asTree, isOpen(this@asTree)) { generateFileNodes(isOpen) }
}
@@ -11,7 +11,9 @@ import org.jetbrains.jewel.foundation.lazy.DefaultSelectableColumnKeybindings
import org.jetbrains.jewel.foundation.lazy.SelectableColumnKeybindings
import org.jetbrains.skiko.hostOs
/** Default [TreeViewKeybindings]: left/right arrows collapse/expand nodes; F2 edits. */
public open class DefaultTreeViewKeybindings : DefaultSelectableColumnKeybindings(), TreeViewKeybindings {
/** The default singleton instance. */
public companion object : DefaultTreeViewKeybindings()
override val KeyEvent.isSelectParent: Boolean
@@ -32,10 +34,12 @@ public open class DefaultTreeViewKeybindings : DefaultSelectableColumnKeybinding
override val KeyEvent.isSelectPreviousSibling: Boolean
get() = false
/** Whether the event triggers an inline edit action (F2). */
override val KeyEvent.isEdit: Boolean
get() = key == Key.F2 && !isContiguousSelectionKeyPressed
}
/** Extends [SelectableColumnKeybindings] with tree-specific navigation: expand/collapse and sibling traversal. */
public interface TreeViewKeybindings : SelectableColumnKeybindings {
/** Select Parent Node. */
public val KeyEvent.isSelectParent: Boolean
@@ -56,6 +60,7 @@ public interface TreeViewKeybindings : SelectableColumnKeybindings {
public val KeyEvent.isSelectPreviousSibling: Boolean
}
/** Default click modifier handler that uses Ctrl on Windows/Linux and Meta (⌘) on macOS. */
@Suppress("unused")
public val DefaultWindowsTreeViewClickModifierHandler: TreeViewClickModifierHandler
get() = {
@@ -66,9 +71,12 @@ public val DefaultWindowsTreeViewClickModifierHandler: TreeViewClickModifierHand
}
}
/** Function type for determining whether a pointer event's modifier keys constitute a multi-selection click. */
public typealias TreeViewClickModifierHandler = PointerKeyboardModifiers.() -> Boolean
/** [DefaultTreeViewKeybindings] for macOS, overriding the multi-selection modifier to `Meta` (⌘). */
public open class DefaultMacOsTreeColumnKeybindings : DefaultTreeViewKeybindings() {
/** The default singleton instance for macOS. */
public companion object : DefaultMacOsTreeColumnKeybindings()
override val KeyEvent.isMultiSelectionKeyPressed: Boolean
@@ -3,6 +3,7 @@ package org.jetbrains.jewel.foundation.lazy.tree
import org.jetbrains.jewel.foundation.lazy.SelectableLazyListKey
import org.jetbrains.jewel.foundation.lazy.SelectableLazyListState
/** Default [TreeViewOnKeyEvent] that handles tree navigation: collapsing/expanding nodes and moving to parent/child. */
public open class DefaultTreeViewOnKeyEvent(
override val keybindings: TreeViewKeybindings,
private val treeState: TreeState,
@@ -22,10 +22,23 @@ import org.jetbrains.jewel.foundation.lazy.SelectableLazyListState
import org.jetbrains.jewel.foundation.lazy.SelectionMode
import org.jetbrains.skiko.hostOs
/** Combines keybindings and on-key-event actions for a selectable list or tree, dispatching keyboard events. */
public interface KeyActions {
/** The keybindings that define which key combinations trigger selection actions. */
public val keybindings: SelectableColumnKeybindings
/** The handler that performs selection actions in response to key events. */
public val actions: SelectableColumnOnKeyEvent
/**
* Returns a handler lambda for [event] that, when invoked on the [KeyEvent], applies the appropriate selection
* action and returns `true` if the event was consumed, or `false` to let it propagate.
*
* @param event The incoming key event.
* @param keys All selectable keys in the current list.
* @param state The mutable selection and scroll state.
* @param selectionMode The active selection mode.
*/
public fun handleOnKeyEvent(
event: KeyEvent,
keys: List<SelectableLazyListKey>,
@@ -34,7 +47,21 @@ public interface KeyActions {
): KeyEvent.() -> Boolean
}
/**
* Handles pointer (mouse) events for a selectable list or tree, including click-based selection and range extension.
*/
public interface PointerEventActions {
/**
* Handles a pointer press event, updating selection in [selectableLazyListState] for [key] based on modifier keys
* and [selectionMode].
*
* @param pointerEvent The raw pointer event containing modifier key state.
* @param keybindings The keybindings defining which modifier keys trigger multi/range select.
* @param selectableLazyListState The mutable selection state to update.
* @param selectionMode The active selection mode.
* @param allKeys All selectable keys in the list.
* @param key The key of the item that was pressed.
*/
public fun handlePointerEventPress(
pointerEvent: PointerEvent,
keybindings: SelectableColumnKeybindings,
@@ -44,6 +71,14 @@ public interface PointerEventActions {
key: Any,
)
/**
* Toggles the selection state of [key] in [selectableLazyListState], respecting [selectionMode].
*
* @param key The key to toggle.
* @param allKeys All selectable keys in the list.
* @param selectableLazyListState The mutable selection state to update.
* @param selectionMode The active selection mode.
*/
public fun toggleKeySelection(
key: Any,
allKeys: List<SelectableLazyListKey>,
@@ -51,6 +86,14 @@ public interface PointerEventActions {
selectionMode: SelectionMode,
)
/**
* Extends the current selection from the active item to [key], adding all items in between.
*
* @param key The target key to extend selection to.
* @param allKeys All selectable keys in the list.
* @param state The mutable selection state to update.
* @param selectionMode The active selection mode.
*/
public fun onExtendSelectionToKey(
key: Any,
allKeys: List<SelectableLazyListKey>,
@@ -59,6 +102,7 @@ public interface PointerEventActions {
)
}
/** Default [PointerEventActions] for selectable lazy columns, handling click, multi-select, and range-select. */
public open class DefaultSelectableLazyColumnEventAction : PointerEventActions {
override fun handlePointerEventPress(
pointerEvent: PointerEvent,
@@ -147,6 +191,7 @@ public open class DefaultSelectableLazyColumnEventAction : PointerEventActions {
}
}
/** [DefaultSelectableLazyColumnEventAction] for tree views, adding single/double-click detection for node expansion. */
public open class DefaultTreeViewPointerEventAction(private val treeState: TreeState) :
DefaultSelectableLazyColumnEventAction() {
override fun handlePointerEventPress(
@@ -188,6 +233,18 @@ public open class DefaultTreeViewPointerEventAction(private val treeState: TreeS
// for item click that lose focus and fail to match if a operation is a double-click
private var elementClickedTmpHolder: Any? = null
/**
* Detects whether [item] was single-clicked or double-clicked within [doubleClickTimeDelayMillis] and invokes the
* appropriate callback. For double-clicks on a [Tree.Element.Node], the node is also toggled.
*
* @param T The type of data in the tree.
* @param item The tree element that was clicked.
* @param scope The coroutine scope used to launch the double-click timeout.
* @param doubleClickTimeDelayMillis The window in milliseconds within which a second click counts as a
* double-click.
* @param onElementClick Callback invoked on a single click.
* @param onElementDoubleClick Callback invoked on a double click.
*/
@ApiStatus.Internal
@InternalJewelApi
public fun <T> notifyItemClicked(
@@ -216,6 +273,11 @@ public open class DefaultTreeViewPointerEventAction(private val treeState: TreeS
}
}
/**
* Creates a [DefaultTreeViewKeyActions] with platform-appropriate keybindings (macOS or Windows/Linux).
*
* @param treeState The [TreeState] used by key actions to expand/collapse nodes.
*/
public fun DefaultTreeViewKeyActions(treeState: TreeState): DefaultTreeViewKeyActions {
val keybindings =
when {
@@ -225,8 +287,13 @@ public fun DefaultTreeViewKeyActions(treeState: TreeState): DefaultTreeViewKeyAc
return DefaultTreeViewKeyActions(keybindings, DefaultTreeViewOnKeyEvent(keybindings, treeState))
}
/**
* [KeyActions] for tree views, adding expand/collapse key handling on top of [DefaultSelectableLazyColumnKeyActions].
*/
public class DefaultTreeViewKeyActions(
/** The tree-view-specific keybindings, including expand and collapse key mappings. */
override val keybindings: TreeViewKeybindings,
/** The handler that performs tree-view actions (expand, collapse, selection) in response to key events. */
override val actions: DefaultTreeViewOnKeyEvent,
) : DefaultSelectableLazyColumnKeyActions(keybindings, actions) {
override fun handleOnKeyEvent(
@@ -259,10 +326,17 @@ public class DefaultTreeViewKeyActions(
}
}
/**
* Default [KeyActions] for selectable lazy columns, dispatching key events via configurable [keybindings] and
* [actions].
*/
public open class DefaultSelectableLazyColumnKeyActions(
/** The keybindings that define which key combinations trigger selection actions. */
override val keybindings: SelectableColumnKeybindings,
/** The handler that performs selection actions in response to key events. */
override val actions: SelectableColumnOnKeyEvent = DefaultSelectableOnKeyEvent(keybindings),
) : KeyActions {
/** The default singleton instance using platform-appropriate keybindings (macOS or Windows/Linux). */
public companion object :
DefaultSelectableLazyColumnKeyActions(
when {
@@ -359,12 +433,18 @@ public open class DefaultSelectableLazyColumnKeyActions(
}
}
/**
* A no-op [KeyActions] whose [handleOnKeyEvent] always returns a handler that consumes nothing (false), so no key event
* is ever handled. For internal use when keyboard input handling must be disabled.
*/
@ApiStatus.Internal
@InternalJewelApi
public object NoopListKeyActions : KeyActions {
/** The keybindings used by this no-op implementation (default column keybindings). */
override val keybindings: SelectableColumnKeybindings
get() = DefaultSelectableColumnKeybindings
/** The on-key-event handler used by this no-op implementation. */
override val actions: SelectableColumnOnKeyEvent = DefaultSelectableOnKeyEvent(keybindings)
override fun handleOnKeyEvent(
@@ -2,13 +2,20 @@ package org.jetbrains.jewel.foundation.lazy.tree
import org.jetbrains.jewel.foundation.lazy.tree.Tree.Element.Node
/** Returns a shared empty [Tree] instance with no root elements. */
@Suppress("UNCHECKED_CAST") public fun <T> emptyTree(): Tree<T> = Tree.EMPTY as Tree<T>
/**
* A lazy tree data structure whose top-level entries are stored as a flat list of [roots]. Child nodes are generated on
* demand when a [Element.Node] is opened.
*/
public class Tree<T> internal constructor(public val roots: List<Element<T>>) {
/** Provides the [EMPTY] singleton for an empty tree with no root elements. */
public companion object {
internal val EMPTY = Tree(roots = emptyList<Element<Any?>>())
}
/** Returns `true` if this tree has no root elements. */
public fun isEmpty(): Boolean = roots.isEmpty()
private fun walk(breathFirst: Boolean) = sequence {
@@ -27,19 +34,39 @@ public class Tree<T> internal constructor(public val roots: List<Element<T>>) {
}
}
/** Returns a [Sequence] that traverses the tree in breadth-first order, opening nodes as it visits them. */
public fun walkBreadthFirst(): Sequence<Element<T>> = walk(true)
/** Returns a [Sequence] that traverses the tree in depth-first order, opening nodes as it visits them. */
public fun walkDepthFirst(): Sequence<Element<T>> = walk(false)
/**
* An element in the tree, holding [data] plus [depth], [childIndex], a [parent] pointer, and [next]/[previous]
* pointers into the tree's flattened linked list.
*/
public sealed interface Element<T> {
/** The data payload held by this element. */
public val data: T
/** The nesting depth of this element, where 0 means a root element. */
public val depth: Int
/** The parent element of this element, or `null` if it is a root element. */
public val parent: Element<T>?
/** The zero-based index of this element among its siblings. */
public val childIndex: Int
/** The next element in the flattened linked list, or `null` if this is the last element. */
public var next: Element<T>?
/** The previous element in the flattened linked list, or `null` if this is the first element. */
public var previous: Element<T>?
/** A stable identifier for this element, used to distinguish it from other elements in the tree. */
public val id: Any
/** Returns the ordered path from the root of the tree down to this element (inclusive). */
public fun path(): List<Element<T>> =
buildList {
var next: Element<T>? = this@Element
@@ -50,12 +77,15 @@ public class Tree<T> internal constructor(public val roots: List<Element<T>>) {
}
.reversed()
/** Returns an [Iterable] over elements preceding this one in the flattened linked list, in reverse order. */
public fun previousElementsIterable(): Iterable<Element<T>> = Iterable {
elementIterator(previous) { it.previous }
}
/** Returns an [Iterable] over elements following this one in the flattened linked list, in forward order. */
public fun nextElementsIterable(): Iterable<Element<T>> = Iterable { elementIterator(next) { it.next } }
/** A terminal element in the tree that holds [data] and has no children. */
public class Leaf<T>(
override val data: T,
override val depth: Int,
@@ -66,6 +96,9 @@ public class Tree<T> internal constructor(public val roots: List<Element<T>>) {
override val id: Any,
) : Element<T>
/**
* A branching element in the tree that holds [data] and can lazily generate [children] when [open] is called.
*/
public class Node<T>(
override val data: T,
override val depth: Int,
@@ -76,6 +109,7 @@ public class Tree<T> internal constructor(public val roots: List<Element<T>>) {
override var previous: Element<T>?,
override val id: Any,
) : Element<T> {
/** The lazily evaluated children of this node, or `null` if [open] has not been called yet. */
public var children: List<Element<T>>? = null
private set
@@ -103,11 +137,21 @@ public class Tree<T> internal constructor(public val roots: List<Element<T>>) {
}
}
/**
* Evaluates and links this node's children into the flat element linked list. If [reloadChildren] is
* `true`, the children generator is invoked again even if children were already evaluated.
*
* @param reloadChildren Whether to force re-evaluation of the children generator.
*/
public fun open(reloadChildren: Boolean = false) {
if (reloadChildren || children == null) evaluateChildren()
connectChildren()
}
/**
* Detaches this node's children from the flat element linked list and recursively closes all descendant
* nodes.
*/
public fun close() {
detachChildren()
children?.asSequence()?.filterIsInstance<Node<*>>()?.forEach { it.closeRecursively() }
@@ -13,19 +13,35 @@ import org.jetbrains.jewel.foundation.InternalJewelApi
import org.jetbrains.jewel.foundation.lazy.SelectableLazyListState
import org.jetbrains.jewel.foundation.lazy.SelectableScope
/**
* Creates and remembers a [TreeState] backed by [selectableLazyListState].
*
* @param lazyListState The [LazyListState] used for scroll and layout. Defaults to a new instance.
* @param selectableLazyListState The selectable list state backing the tree. Defaults to a new instance wrapping
* [lazyListState].
*/
@Composable
public fun rememberTreeState(
lazyListState: LazyListState = LazyListState(),
selectableLazyListState: SelectableLazyListState = SelectableLazyListState(lazyListState),
): TreeState = remember { TreeState(selectableLazyListState) }
/** Holds the runtime state of a tree view: the set of open node IDs and the underlying selectable list state. */
public class TreeState(delegate: SelectableLazyListState) : SelectableScope by delegate, ScrollableState by delegate {
internal val allNodes = mutableStateListOf<Pair<Any, Int>>()
/** The underlying selectable lazy list state backing the tree. */
@InternalJewelApi @ApiStatus.Internal public val lazyListState: SelectableLazyListState = delegate
/** The set of node IDs that are currently expanded (open) in the tree. */
public var openNodes: Set<Any> by mutableStateOf<Set<Any>>(emptySet())
/**
* Toggles the open/closed state of the node with [nodeId]: removes it from [openNodes] if present, or adds it
* otherwise.
*
* @param nodeId The unique identifier of the node to toggle.
*/
public fun toggleNode(nodeId: Any) {
if (nodeId in openNodes) {
openNodes -= nodeId
@@ -34,6 +50,11 @@ public class TreeState(delegate: SelectableLazyListState) : SelectableScope by d
}
}
/**
* Adds all [nodes] to [openNodes], expanding them all at once.
*
* @param nodes The list of node IDs to open.
*/
public fun openNodes(nodes: List<Any>) {
openNodes += nodes
}
@@ -4,6 +4,7 @@ import org.jetbrains.jewel.foundation.lazy.SelectableColumnOnKeyEvent
import org.jetbrains.jewel.foundation.lazy.SelectableLazyListKey
import org.jetbrains.jewel.foundation.lazy.SelectableLazyListState
/** Extends [SelectableColumnOnKeyEvent] with tree-specific handlers for navigating to parent and child nodes. */
public interface TreeViewOnKeyEvent : SelectableColumnOnKeyEvent {
/** Select Parent Node. */
public fun onSelectParent(keys: List<SelectableLazyListKey>, state: SelectableLazyListState)
@@ -254,4 +254,5 @@ private class ActivateChangedNode(var onChanged: (Boolean) -> Unit) :
}
}
/** The modifier local that provides the current activation state to child modifiers. */
public val ModifierLocalActivated: ProvidableModifierLocal<Boolean> = modifierLocalOf { false }
@@ -6,6 +6,11 @@ import androidx.compose.ui.input.pointer.PointerEventType
import androidx.compose.ui.input.pointer.pointerInput
import java.awt.event.MouseEvent
/**
* Invokes [onHover] with `true` when the pointer enters this composable and `false` when it exits.
*
* @param onHover Callback receiving `true` on enter and `false` on exit.
*/
public fun Modifier.onHover(onHover: (Boolean) -> Unit): Modifier =
pointerInput(onHover) {
awaitPointerEventScope {
@@ -19,6 +24,12 @@ public fun Modifier.onHover(onHover: (Boolean) -> Unit): Modifier =
}
}
/**
* Invokes [onMove] with the underlying [MouseEvent] (or `null` if unavailable) whenever the pointer moves over this
* composable.
*
* @param onMove Callback receiving the AWT [MouseEvent] on each pointer move event.
*/
public fun Modifier.onMove(onMove: (MouseEvent?) -> Unit): Modifier =
pointerInput(onMove) {
awaitPointerEventScope {
@@ -9,6 +9,7 @@ import org.jetbrains.jewel.foundation.search.SpeedSearchMatcher.MatchResult
import org.jetbrains.jewel.foundation.search.impl.ExactSubstringSpeedSearchMatcher
import org.jetbrains.jewel.foundation.search.impl.PatternSpeedSearchMatcher
/** A functional interface for matching text against a search pattern, returning matched character ranges. */
public fun interface SpeedSearchMatcher {
/**
* Returns a [MatchResult.Match] with a list of ranges from the where the pattern matches, or [MatchResult.NoMatch]
@@ -22,6 +23,7 @@ public fun interface SpeedSearchMatcher {
*/
public fun matches(text: CharSequence?): MatchResult = matches(text?.toString())
/** Factory methods for creating [SpeedSearchMatcher] instances: [exactSubstringMatcher] and [patternMatcher]. */
public companion object {
/**
* Returns a [SpeedSearchMatcher] that searches for the given [pattern] in the text.
@@ -85,9 +87,12 @@ public fun interface SpeedSearchMatcher {
)
}
/** The result of a [SpeedSearchMatcher.matches] call: either [NoMatch] or a [Match] with matched ranges. */
public sealed interface MatchResult {
/** Indicates that the text did not match the search pattern. */
public object NoMatch : MatchResult
/** Indicates a successful match, containing the list of matched [ranges] within the text. */
@GenerateDataFunctions
public class Match(public val ranges: List<IntRange>) : MatchResult {
override fun equals(other: Any?): Boolean {
@@ -104,6 +109,7 @@ public fun interface SpeedSearchMatcher {
override fun toString(): String = "Match(ranges=$ranges)"
}
/** Companion object for [MatchResult]. */
public companion object {
internal fun from(ranges: List<IntRange>?): MatchResult =
if (ranges.isNullOrEmpty()) NoMatch else Match(ranges)
@@ -196,7 +202,7 @@ public object EmptySpeedSearchMatcher : SpeedSearchMatcher {
* matcher.doesMatch("baz") // false
* ```
*
* @param text The text to check for matches. If null, returns false.
* @param matcher The [SpeedSearchMatcher] to use for matching.
* @return `true` if the text matches the pattern, `false` otherwise.
* @see SpeedSearchMatcher.matches for the underlying match result with ranges
*/
@@ -255,6 +261,7 @@ public fun <T> Iterable<T>.filter(
* // Returns: ["React"]
* ```
*
* @param T the type of items in the collection, constrained to [CharSequence].
* @param matcher The [SpeedSearchMatcher] to use for filtering.
* @return A list containing only the strings that match the search pattern.
* @see filter for filtering collections of other types
@@ -1,13 +1,28 @@
package org.jetbrains.jewel.foundation.state
/** Bit mask constants for the common interactive component states shared across all Jewel components. */
public object CommonStateBitMask {
/** Bit flag for the enabled state. */
public val Enabled: ULong = 1UL shl 0
/** Bit flag for the focused state. */
public val Focused: ULong = 1UL shl 1
/** Bit flag for the hovered state. */
public val Hovered: ULong = 1UL shl 2
/** Bit flag for the pressed state. */
public val Pressed: ULong = 1UL shl 3
/** Bit flag for the active state. */
public val Active: ULong = 1UL shl 4
/** Bit flag for the selected state. */
public val Selected: ULong = 1UL shl 5
/** Bit flag for the indeterminate state. */
public val Indeterminate: ULong = 1UL shl 6
/** The first bit offset available for component-specific state flags. */
public const val FIRST_AVAILABLE_OFFSET: Int = 7
}
@@ -3,7 +3,12 @@ package org.jetbrains.jewel.foundation.state
import androidx.compose.runtime.Composable
import org.jetbrains.jewel.foundation.theme.JewelTheme
/**
* An [InteractiveComponentState] that also tracks focus. Provides a composable `chooseValue` helper that resolves a
* state-dependent value based on the current enabled, pressed, hovered, focused, and active flags.
*/
public interface FocusableComponentState : InteractiveComponentState {
/** Whether the component currently has keyboard focus. */
public val isFocused: Boolean
/**
@@ -1,11 +1,19 @@
package org.jetbrains.jewel.foundation.state
/**
* Base interface for interactive component states, tracking whether a component is active, enabled, hovered, or
* pressed.
*/
public interface InteractiveComponentState {
/** Whether the component is active (e.g., its parent window has focus). */
public val isActive: Boolean
/** Whether the component is enabled and can receive user interaction. */
public val isEnabled: Boolean
/** Whether the pointer is currently hovering over the component. */
public val isHovered: Boolean
/** Whether the component is currently being pressed. */
public val isPressed: Boolean
}
@@ -1,5 +1,7 @@
package org.jetbrains.jewel.foundation.state
/** An [InteractiveComponentState] that also tracks whether the component is selected. */
public interface SelectableComponentState : InteractiveComponentState {
/** Whether the component is currently selected. */
public val isSelected: Boolean
}
@@ -4,16 +4,22 @@ import androidx.compose.ui.state.ToggleableState
import org.jetbrains.jewel.foundation.state.CommonStateBitMask.Indeterminate
import org.jetbrains.jewel.foundation.state.CommonStateBitMask.Selected
/** A component state that tracks a [ToggleableState] value (on, off, or indeterminate). */
public interface ToggleableComponentState {
/** The current toggleable state of the component (on, off, or indeterminate). */
public val toggleableState: ToggleableState
/** Whether the component is in the [ToggleableState.On] state. */
public val isSelected: Boolean
get() = toggleableState == ToggleableState.On
/** Whether the component is in either the [ToggleableState.On] or [ToggleableState.Indeterminate] state. */
public val isSelectedOrIndeterminate: Boolean
get() = toggleableState != ToggleableState.Off
/** Provides the [readToggleableState] helper for decoding a [ToggleableState] from a [ULong] bit mask. */
public companion object {
/** Decodes the [ToggleableState] from this [ULong] bit mask using the [Selected] and [Indeterminate] bits. */
public fun ULong.readToggleableState(): ToggleableState {
val selected = this and Selected != 0UL
val indeterminate = this and Indeterminate != 0UL
@@ -15,8 +15,11 @@ import org.jetbrains.jewel.foundation.LocalDisabledAppearanceValues
import org.jetbrains.jewel.foundation.LocalGlobalColors
import org.jetbrains.jewel.foundation.LocalGlobalMetrics
/** Entry point for accessing the current Jewel theme values from any composable via composition locals. */
public interface JewelTheme {
/** Provides composable-accessible properties for the current theme's colors, metrics, text styles, and flags. */
public companion object {
/** The name of the current theme. */
public val name: String
@Composable @ReadOnlyComposable get() = LocalThemeName.current
@@ -24,37 +27,58 @@ public interface JewelTheme {
public val instanceUuid: UUID
@Composable @ReadOnlyComposable get() = LocalThemeInstanceUuid.current
/** The global colors for the current theme. */
public val globalColors: GlobalColors
@Composable @ReadOnlyComposable get() = LocalGlobalColors.current
/** The global metrics for the current theme. */
public val globalMetrics: GlobalMetrics
@Composable @ReadOnlyComposable get() = LocalGlobalMetrics.current
/** The default text style for the current theme. */
public val defaultTextStyle: TextStyle
@Composable @ReadOnlyComposable get() = LocalTextStyle.current
/** The text style used in editor components. */
public val editorTextStyle: TextStyle
@Composable @ReadOnlyComposable get() = LocalEditorTextStyle.current
/** The text style used in console/terminal components. */
public val consoleTextStyle: TextStyle
@Composable @ReadOnlyComposable get() = LocalConsoleTextStyle.current
/** The default content (foreground) color for the current theme. */
public val contentColor: Color
@Composable @ReadOnlyComposable get() = LocalContentColor.current
/** Whether the current theme is a dark theme. */
public val isDark: Boolean
@Composable @ReadOnlyComposable get() = LocalIsDarkTheme.current
/** Whether Swing compatibility mode is enabled, which disables hover and press state changes. */
public val isSwingCompatMode: Boolean
@Composable @ReadOnlyComposable get() = LocalSwingCompatMode.current
}
}
/**
* Applies the given [theme] and [swingCompatMode] flag to the [content] composition tree.
*
* @param theme The [ThemeDefinition] describing colors, metrics, and text styles.
* @param swingCompatMode Whether to enable Swing compatibility mode (disables hover/press state changes).
* @param content The composable content to render under this theme.
*/
@Composable
public fun JewelTheme(theme: ThemeDefinition, swingCompatMode: Boolean, content: @Composable () -> Unit) {
CompositionLocalProvider(LocalSwingCompatMode provides swingCompatMode) { JewelTheme(theme, content) }
}
/**
* Applies the given [theme] to the [content] composition tree, providing all theme composition locals.
*
* @param theme The [ThemeDefinition] describing colors, metrics, and text styles.
* @param content The composable content to render under this theme.
*/
@Composable
public fun JewelTheme(theme: ThemeDefinition, content: @Composable () -> Unit) {
CompositionLocalProvider(
@@ -72,6 +96,7 @@ public fun JewelTheme(theme: ThemeDefinition, content: @Composable () -> Unit) {
)
}
/** Composition local providing the name of the current theme. */
public val LocalThemeName: ProvidableCompositionLocal<String> = staticCompositionLocalOf {
error("No ThemeName provided")
}
@@ -89,6 +114,7 @@ public val LocalThemeInstanceUuid: ProvidableCompositionLocal<UUID> = staticComp
error("No ThemeInstanceUuid provided. Have you forgotten the theme?")
}
/** Composition local providing the default content (foreground) color for the current theme. */
public val LocalContentColor: ProvidableCompositionLocal<Color> = staticCompositionLocalOf {
error("No ContentColor provided. Have you forgotten the theme?")
}
@@ -102,20 +128,25 @@ internal val LocalSwingCompatMode: ProvidableCompositionLocal<Boolean> = staticC
false
}
/** Composition local providing the color palette for the current theme. */
public val LocalColorPalette: ProvidableCompositionLocal<ThemeColorPalette> = staticCompositionLocalOf {
ThemeColorPalette.Empty
}
/** Composition local providing icon data (mappings and overrides) for the current theme. */
public val LocalIconData: ProvidableCompositionLocal<ThemeIconData> = staticCompositionLocalOf { ThemeIconData.Empty }
/** Composition local providing the default text style for the current theme. */
public val LocalTextStyle: ProvidableCompositionLocal<TextStyle> = staticCompositionLocalOf {
error("No TextStyle provided. Have you forgotten the theme?")
}
/** Composition local providing the text style used in editor components. */
public val LocalEditorTextStyle: ProvidableCompositionLocal<TextStyle> = staticCompositionLocalOf {
error("No EditorTextStyle provided. Have you forgotten the theme?")
}
/** Composition local providing the text style used in console/terminal components. */
public val LocalConsoleTextStyle: ProvidableCompositionLocal<TextStyle> = staticCompositionLocalOf {
error("No ConsoleTextStyle provided. Have you forgotten the theme?")
}
@@ -418,6 +418,7 @@ public class ThemeColorPalette(
")"
}
/** Provides the [Empty] instance representing a palette with no color entries. */
public companion object {
public val Empty: ThemeColorPalette =
ThemeColorPalette(
@@ -8,19 +8,34 @@ import org.jetbrains.jewel.foundation.GenerateDataFunctions
import org.jetbrains.jewel.foundation.GlobalColors
import org.jetbrains.jewel.foundation.GlobalMetrics
/**
* Defines all visual properties of a Jewel theme: its name, dark/light mode, global colors and metrics, text styles,
* content color, color palette, icon data, and disabled appearance values.
*/
@Immutable
@GenerateDataFunctions
public class ThemeDefinition(
/** The unique name identifying this theme. */
public val name: String,
/** Whether this theme is a dark theme. */
public val isDark: Boolean,
/** The global colors shared across all components in this theme. */
public val globalColors: GlobalColors,
/** The global metrics (sizes, spacings) shared across all components in this theme. */
public val globalMetrics: GlobalMetrics,
/** The default text style used for body content. */
public val defaultTextStyle: TextStyle,
/** The text style used for editor content. */
public val editorTextStyle: TextStyle,
/** The text style used for console/terminal content. */
public val consoleTextStyle: TextStyle,
/** The default foreground color for content rendered with this theme. */
public val contentColor: Color,
/** The color palette providing semantic and raw color mappings for this theme. */
public val colorPalette: ThemeColorPalette,
/** The icon data providing icon overrides and mappings for this theme. */
public val iconData: ThemeIconData,
/** The values controlling the appearance of disabled components. */
public val disabledAppearanceValues: DisabledAppearanceValues,
) {
@Deprecated("Use the primary constructor and provide DisabledAppearanceValues.")
@@ -2,10 +2,18 @@ package org.jetbrains.jewel.foundation.theme
import androidx.compose.runtime.Immutable
/** Describes the identity and palette of a Jewel theme: its name, dark/light flag, color palette, and icon data. */
@Immutable
public interface ThemeDescriptor {
/** The unique name identifying this theme. */
public val name: String
/** Whether this theme uses a dark color scheme. */
public val isDark: Boolean
/** The color palette associated with this theme. */
public val colors: ThemeColorPalette
/** The icon data associated with this theme. */
public val iconData: ThemeIconData
}
@@ -3,12 +3,21 @@ package org.jetbrains.jewel.foundation.theme
import androidx.compose.runtime.Immutable
import androidx.compose.ui.graphics.Color
/** Holds theme-specific icon path overrides and color palette mappings used to tint and remap SVG icons. */
@Immutable
public class ThemeIconData(
/** Maps original icon paths to replacement icon paths for this theme. */
public val iconOverrides: Map<String, String>,
/** Maps color hex strings to replacement color hex strings (or null to leave unchanged) for icon tinting. */
public val colorPalette: Map<String, String?>,
/** Maps color hex strings to replacement ARGB int values used for selected icon tinting. */
public val selectionColorPalette: Map<String, Int>,
) {
/**
* Converts [selectionColorPalette] into a typed [Map] from source [Color] (parsed from each hex-string key) to
* replacement [Color] (built from each ARGB int value). Entries whose key string cannot be parsed as a color are
* silently dropped.
*/
public fun selectionColorMapping(): Map<Color, Color> =
selectionColorPalette
.mapNotNull { (key, value) ->
@@ -18,6 +27,7 @@ public class ThemeIconData(
}
.toMap()
/** Provides the [Empty] instance representing a theme with no icon customizations. */
public companion object {
public val Empty: ThemeIconData =
ThemeIconData(iconOverrides = emptyMap(), colorPalette = emptyMap(), selectionColorPalette = emptyMap())
@@ -6,6 +6,7 @@ import java.util.logging.Level
import java.util.logging.Logger
import org.jetbrains.annotations.ApiStatus
/** Creates a [JewelLogger] instance scoped to the calling class [T]. */
public inline fun <reified T : Any> T.myLogger(): JewelLogger = JewelLogger.getInstance(T::class.java)
/** A wrapper which uses either IDE logging subsystem (if available) or java.util.logging. */
@@ -16,34 +17,49 @@ public abstract class JewelLogger {
fun getInstance(category: String?): JewelLogger
}
/** Logs [message] at TRACE level with no associated throwable. */
public fun trace(message: String?): Unit = trace(message, null)
/** Logs [t] at TRACE level, using the throwable's message as the log message. */
public fun trace(t: Throwable): Unit = trace(t.message, t)
/** Logs [message] at DEBUG level with no associated throwable. */
public fun debug(message: String?): Unit = debug(message, null)
/** Logs [t] at DEBUG level, using the throwable's message as the log message. */
public fun debug(t: Throwable): Unit = debug(t.message, t)
/** Logs [message] at INFO level with no associated throwable. */
public fun info(message: String?): Unit = info(message, null)
/** Logs [t] at INFO level, using the throwable's message as the log message. */
public fun info(t: Throwable): Unit = info(t.message, t)
/** Logs [message] at WARN level with no associated throwable. */
public fun warn(message: String?): Unit = warn(message, null)
/** Logs [t] at WARN level, using the throwable's message as the log message. */
public fun warn(t: Throwable): Unit = warn(t.message, t)
/** Logs [message] at ERROR level with no associated throwable. */
public fun error(message: String?): Unit = error(message, null)
/** Logs [t] at ERROR level, using the throwable's message as the log message. */
public fun error(t: Throwable): Unit = error(t.message, t)
/** Logs [message] with optional [t] at TRACE level. */
public abstract fun trace(message: String?, t: Throwable?)
/** Logs [message] with optional [t] at DEBUG level. */
public abstract fun debug(message: String?, t: Throwable?)
/** Logs [message] with optional [t] at INFO level. */
public abstract fun info(message: String?, t: Throwable?)
/** Logs [message] with optional [t] at WARN level. */
public abstract fun warn(message: String?, t: Throwable?)
/** Logs [message] with optional [t] at ERROR level. */
public abstract fun error(message: String?, t: Throwable?)
private class JavaFactory : Factory {
@@ -252,6 +268,7 @@ public abstract class JewelLogger {
@Throws(Exception::class) override fun getLogger(category: String?): Any = myGetLogger.invoke(null, category)
}
/** Provides [getInstance] factory methods for obtaining [JewelLogger] instances by category name or class. */
public companion object {
@get:Synchronized private val factory: Factory = createFactory()
@@ -267,8 +284,10 @@ public abstract class JewelLogger {
}
}
/** Returns a [JewelLogger] instance for the given [category] name. */
public fun getInstance(category: String): JewelLogger = factory.getInstance("#$category")
/** Returns a [JewelLogger] instance for the given [clazz], using the class name as the category. */
public fun getInstance(clazz: Class<*>): JewelLogger = getInstance("#${clazz.name}")
}
}
@@ -3,6 +3,7 @@ package org.jetbrains.jewel.bridge
import com.intellij.ide.ui.UITheme
import org.jetbrains.jewel.foundation.theme.ThemeIconData
/** Reads [ThemeIconData] from the currently active IntelliJ UI theme, including icon overrides and color palettes. */
@Suppress("UnstableApiUsage")
public fun ThemeIconData.Companion.readFromLaF(): ThemeIconData {
val uiTheme = currentUiThemeOrNull()
@@ -102,9 +102,16 @@ private constructor(
add(Dark(JewelTheme.isDark))
}
/** Provides the [invoke] factory that creates a [PalettePainterHintsProvider] from the current IDE UI theme. */
public companion object {
private val logger = thisLogger()
/**
* Creates a [PalettePainterHintsProvider] from the current IDE UI theme. Falls back to a basic
* [BridgePainterHintsProvider] if no theme is active.
*
* @param isDark Whether the current theme is dark.
*/
@Suppress("UnstableApiUsage") // We need to call @Internal APIs
public operator fun invoke(isDark: Boolean): PalettePainterHintsProvider {
val uiTheme = currentUiThemeOrNull() ?: return BridgePainterHintsProvider(isDark)
@@ -12,6 +12,10 @@ import androidx.compose.ui.semantics.getOrNull
import org.jetbrains.annotations.ApiStatus.Internal
import org.jetbrains.jewel.foundation.InternalJewelApi
/**
* Internal utilities for inspecting the Compose semantics tree, such as finding the focused node or identifying text
* fields.
*/
@Internal
@InternalJewelApi
public object ComposeSemanticsTreeUtils {
@@ -39,6 +43,10 @@ public object ComposeSemanticsTreeUtils {
null
}
/**
* Returns `true` if this [SemanticsNode] represents an editable text field (has editable text or a set-text
* action).
*/
public fun SemanticsNode.isEditableTextField(): Boolean {
// Check if the node has editable text or supports setting text
val editable = config.contains(SemanticsProperties.EditableText)
@@ -46,6 +54,10 @@ public object ComposeSemanticsTreeUtils {
return editable || hasSetTextAction
}
/**
* Returns the [CustomAccessibilityAction] with the given [label] from this node's semantics, or `null` if not
* found.
*/
public fun SemanticsNode.getCustomAction(label: String): CustomAccessibilityAction? =
config.getOrNull(SemanticsActions.CustomActions)?.firstOrNull { it.label == label }
}
@@ -1,9 +1,12 @@
package org.jetbrains.jewel.bridge
/** A sealed exception hierarchy for errors that occur when a required key is not found in the Swing LaF. */
public sealed class JewelBridgeException(override val message: String?) : RuntimeException(message) {
/** Thrown when a single expected Swing LaF key is not found. */
public class KeyNotFoundException(key: String, type: String) :
JewelBridgeException("Key '$key' not found in Swing LaF, was expecting a value of type $type")
/** Thrown when none of a set of expected Swing LaF keys are found. */
public class KeysNotFoundException(keys: List<String>, type: String) :
JewelBridgeException(
"Keys ${keys.joinToString(", ") { "'$it'" }} not found in Swing LaF, " +
@@ -8,11 +8,11 @@ import org.jetbrains.jewel.foundation.enableNewSwingCompositing
/**
* Adds a new tab to the tool window with Compose content.
*
* @param focusOnClickInside If `true`, the underlying [ComposePanel] will request focus when a mouse click occurs
* inside it, even if it does not hit a "focusable" element.
* @param tabDisplayName The title of the tab.
* @param isLockable Whether the tab can be locked.
* @param isCloseable Whether the tab can be closed.
* @param focusOnClickInside If `true`, the underlying [ComposePanel] will request focus when a mouse click occurs
* inside it, even if it does not hit a "focusable" element.
* @param content The Composable content of the tab.
*/
public fun ToolWindow.addComposeTab(
@@ -11,6 +11,10 @@ import org.jetbrains.annotations.VisibleForTesting
import org.jetbrains.jewel.foundation.InternalJewelApi
import org.jetbrains.jewel.foundation.actionSystem.DataProviderNode
/**
* A [Modifier.Node] that collects data from all [DataProviderNode] descendants with focus and exposes it to the
* IntelliJ Platform via [UiDataProvider.uiDataSnapshot].
*/
@VisibleForTesting
@ApiStatus.Internal
@InternalJewelApi
@@ -10,6 +10,10 @@ import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.launch
import org.jetbrains.jewel.foundation.code.highlighting.CodeHighlighter
/**
* A project-level IDE service that creates [CodeHighlighter] instances backed by the IDE's editor color scheme, and
* triggers re-highlighting when the color scheme changes.
*/
@Service(Service.Level.PROJECT)
public class CodeHighlighterFactory(private val project: Project, private val coroutineScope: CoroutineScope) {
private val reHighlightingRequests = MutableSharedFlow<Unit>(replay = 0)
@@ -23,9 +27,12 @@ public class CodeHighlighterFactory(private val project: Project, private val co
)
}
/** Creates a new [CodeHighlighter] backed by the IDE's current editor color scheme for this project. */
public fun createHighlighter(): CodeHighlighter = IntelliJCodeHighlighter(project, reHighlightingRequests)
/** Provides the [getInstance] factory for obtaining the [CodeHighlighterFactory] service for a given project. */
public companion object {
/** Returns the [CodeHighlighterFactory] service instance for the given [project]. */
public fun getInstance(project: Project): CodeHighlighterFactory = project.service()
}
}
@@ -4,6 +4,13 @@ import com.intellij.ui.icons.IconPathProvider
import org.jetbrains.jewel.ui.icon.IconKey
import org.jetbrains.jewel.ui.icon.IntelliJIconKey
/**
* Creates an [IntelliJIconKey] from a Swing [icon] that implements [IconPathProvider], extracting the old-UI and New-UI
* resource paths.
*
* @param icon The Swing icon to convert. Must be an [IconPathProvider] (e.g., icons from `AllIcons`).
* @param iconClass The class whose [ClassLoader] will be used to locate the icon resource.
*/
public fun IntelliJIconKey.Companion.fromPlatformIcon(
icon: javax.swing.Icon,
iconClass: Class<*> = icon::class.java,
@@ -7,6 +7,7 @@ import com.intellij.util.ui.JBUI
import org.jetbrains.jewel.bridge.safeValue
import org.jetbrains.jewel.foundation.GlobalMetrics
/** Reads [GlobalMetrics] from the current IntelliJ LaF, deriving outline width and row height from JBUI. */
public fun GlobalMetrics.Companion.readFromLaF(): GlobalMetrics =
GlobalMetrics(
outlineWidth = DarculaUIUtil.BW.unscaled.dp.safeValue(),
@@ -10,9 +10,13 @@ import org.jetbrains.jewel.foundation.theme.ThemeColorPalette
private val logger: Logger = Logger.getInstance("BridgeThemeColorPalette")
/** The border color used for Windows-style popups, or null if not defined in the current LaF. */
public val ThemeColorPalette.windowsPopupBorder: Color?
get() = lookup("windowsPopupBorder")
/**
* Reads [ThemeColorPalette] from the current IntelliJ LaF by extracting named color-palette entries from UIDefaults.
*/
public fun ThemeColorPalette.Companion.readFromLaF(): ThemeColorPalette {
val isIslands = IslandsState.isEnabled()
val gray = readPaletteColors("Gray", isIslands)
@@ -278,6 +278,7 @@ private fun readScrollbarVisibility() =
ScrollbarVisibility.AlwaysVisible.windowsAndLinux()
}
/** Creates the default [ScrollbarVisibility.WhenScrolling] for the current platform: macOS or Windows/Linux. */
public fun ScrollbarVisibility.WhenScrolling.Companion.default(): ScrollbarVisibility.WhenScrolling =
if (hostOs.isMacOS) {
ScrollbarVisibility.WhenScrolling.macOs()
@@ -285,6 +286,7 @@ public fun ScrollbarVisibility.WhenScrolling.Companion.default(): ScrollbarVisib
ScrollbarVisibility.WhenScrolling.windowsAndLinux()
}
/** Creates a [ScrollbarVisibility.WhenScrolling] configured with macOS-specific dimensions and animations. */
public fun ScrollbarVisibility.WhenScrolling.Companion.macOs(
trackThickness: Dp = 11.dp,
trackThicknessExpanded: Dp = 14.dp,
@@ -306,6 +308,7 @@ public fun ScrollbarVisibility.WhenScrolling.Companion.macOs(
lingerDuration = lingerDuration,
)
/** Creates a [ScrollbarVisibility.WhenScrolling] configured with Windows/Linux-specific dimensions and animations. */
public fun ScrollbarVisibility.WhenScrolling.Companion.windowsAndLinux(
trackThickness: Dp = 11.dp,
trackThicknessExpanded: Dp = 14.dp,
@@ -327,6 +330,7 @@ public fun ScrollbarVisibility.WhenScrolling.Companion.windowsAndLinux(
lingerDuration = lingerDuration,
)
/** Creates the default [ScrollbarVisibility.AlwaysVisible] for the current platform: macOS or Windows/Linux. */
public fun ScrollbarVisibility.AlwaysVisible.Companion.default(): ScrollbarVisibility.AlwaysVisible =
if (hostOs.isMacOS) {
ScrollbarVisibility.AlwaysVisible.macOs()
@@ -334,6 +338,7 @@ public fun ScrollbarVisibility.AlwaysVisible.Companion.default(): ScrollbarVisib
ScrollbarVisibility.AlwaysVisible.windowsAndLinux()
}
/** Creates a [ScrollbarVisibility.AlwaysVisible] configured with macOS-specific dimensions and colors. */
public fun ScrollbarVisibility.AlwaysVisible.Companion.macOs(
trackThickness: Dp = 14.dp,
trackPadding: PaddingValues = PaddingValues(2.dp),
@@ -351,6 +356,7 @@ public fun ScrollbarVisibility.AlwaysVisible.Companion.macOs(
scrollbarBackgroundColorDark = scrollbarBackgroundColorDark,
)
/** Creates a [ScrollbarVisibility.AlwaysVisible] configured with Windows/Linux-specific dimensions. */
public fun ScrollbarVisibility.AlwaysVisible.Companion.windowsAndLinux(
trackThickness: Dp = 10.dp,
trackPadding: PaddingValues = PaddingValues(0.5.dp),
@@ -19,6 +19,7 @@ internal fun readSliderStyle(dark: Boolean): SliderStyle {
return SliderStyle(colors, SliderMetrics.defaults(), CircleShape)
}
/** Creates Int UI light [SliderColors] by reading values from the IntelliJ color palette, with hardcoded fallbacks. */
public fun SliderColors.Companion.light(
track: Color = retrieveColorOrUnspecified("ColorPalette.Gray10").takeOrElse { Color(0xFFD3D5DB) },
trackFilled: Color = retrieveColorOrUnspecified("ColorPalette.Blue6").takeOrElse { Color(0xFF588CF3) },
@@ -54,6 +55,7 @@ public fun SliderColors.Companion.light(
thumbBorderHovered,
)
/** Creates Int UI dark [SliderColors] by reading values from the IntelliJ color palette, with hardcoded fallbacks. */
public fun SliderColors.Companion.dark(
track: Color = retrieveColorOrUnspecified("ColorPalette.Gray4").takeOrElse { Color(0xFF43454A) },
trackFilled: Color = retrieveColorOrUnspecified("ColorPalette.Blue7").takeOrElse { Color(0xFF467FF2) },
@@ -89,6 +91,7 @@ public fun SliderColors.Companion.dark(
thumbBorderHovered,
)
/** Creates default [SliderMetrics] with standard Int UI sizing values. */
public fun SliderMetrics.Companion.defaults(
trackHeight: Dp = 4.dp,
thumbSize: DpSize = DpSize(14.dp, 14.dp),
@@ -14,6 +14,7 @@ import org.jetbrains.jewel.ui.component.styling.SplitButtonStyle
private val dividerPadding: Int
get() = if (isNewUiTheme()) 4 else 1
/** Reads the [SplitButtonStyle] for the outlined variant from the current IntelliJ JBUI theme values. */
public fun readOutlinedSplitButtonStyle(): SplitButtonStyle =
SplitButtonStyle(
button = readOutlinedButtonStyle(),
@@ -26,6 +27,7 @@ public fun readOutlinedSplitButtonStyle(): SplitButtonStyle =
metrics = SplitButtonMetrics(dividerMetrics = readDividerStyle().metrics, dividerPadding = dividerPadding.dp),
)
/** Reads the [SplitButtonStyle] for the default (filled) variant from the current IntelliJ JBUI theme values. */
public fun readDefaultSplitButtonStyle(): SplitButtonStyle =
SplitButtonStyle(
button = readDefaultButtonStyle(),
@@ -279,6 +279,7 @@ private val image = ImageUtil.createImage(1, 1, TYPE_INT_ARGB)
* Computes the "base" line height with the same logic used by
* [com.intellij.openapi.editor.impl.view.EditorView.initMetricsIfNeeded].
*
* @param font The font for which to compute the line height.
* @param treatAsUnscaled When true, the font metrics are treated as "unscaled" (i.e., they do not need compensation for
* the IDE scale). This is useful e.g., for editor scheme fonts, which are not scaled, contrary to LaF fonts.
*/
@@ -33,6 +33,13 @@ import org.jetbrains.jewel.ui.util.LocalMessageResourceResolverProvider
private val bridgeThemeReader by lazy { SwingBridgeReader() }
/**
* Entry-point composable for using Jewel inside an IntelliJ Platform plugin. Reads the current IntelliJ theme via
* [SwingBridgeReader] and applies it as a [BaseJewelTheme] with Swing compatibility mode enabled and the appropriate
* platform bridge providers wired up.
*
* @param content The composable content to render under the bridged theme.
*/
@ApiStatus.Experimental
@ExperimentalJewelApi
@Composable
@@ -39,5 +39,6 @@ private val InterFontFamily =
Font(resource = "/fonts/inter/Inter-BlackItalic.ttf", weight = FontWeight.Black, style = FontStyle.Italic),
)
/** The Inter font family, bundled with Jewel for use in standalone (non-IDE) applications. */
public val FontFamily.Companion.Inter: FontFamily
get() = InterFontFamily
@@ -63,5 +63,6 @@ private val JetBrainsMonoFontFamily =
),
)
/** The JetBrains Mono font family, bundled with Jewel. */
public val FontFamily.Companion.JetBrainsMono: FontFamily
get() = JetBrainsMonoFontFamily
@@ -100,6 +100,7 @@ public class StandalonePainterHintsProvider(theme: ThemeDefinition) :
add(Dark(JewelTheme.isDark))
}
/** Companion object for [StandalonePainterHintsProvider]. */
public companion object {
// Extracted from com.intellij.ide.ui.UITheme#colorPalette
private val intellijColorPalette =
@@ -44,6 +44,7 @@ public interface ScrollbarHelper {
*/
public val scrollbarVisibilityStyle: ScrollbarVisibility
/** Delegates to the macOS-specific [StandaloneScrollbarHelper] on macOS, or a no-op dummy on other platforms. */
public companion object : ScrollbarHelper by if (hostOs == OS.MacOS) scrollbarService else DummyScrollbarHelper
}
@@ -49,9 +49,11 @@ public open class DynamicBundle(bundleClass: Class<*>, private val pathToBundle:
private val cache = ConcurrentHashMap<String, ResourceBundle>()
/** Returns the localized message for [key], substituting any [params] into the format pattern. */
public fun getMessage(key: @NonNls String, vararg params: Any?): @Nls String =
@Suppress("HardCodedStringLiteral") getResourceBundle().messageOrDefault(key, params = params)
/** Returns a lazy [Supplier] that retrieves the localized message for [key] with optional [params] on demand. */
public fun getLazyMessage(key: @NonNls String, vararg params: Any?): Supplier<@Nls String> = Supplier {
getMessage(key, params = params)
}
@@ -82,6 +84,7 @@ public open class DynamicBundle(bundleClass: Class<*>, private val pathToBundle:
}
}
/** Companion object for [DynamicBundle]. */
public companion object {
@Suppress("HardCodedStringLiteral")
internal fun postprocessValue(
@@ -13,6 +13,10 @@ import org.jetbrains.jewel.ui.component.ContextMenuItemOptionAction.PasteMenuIte
import org.jetbrains.jewel.ui.component.ContextMenuItemOptionAction.SelectAllMenuItemOptionAction
import org.jetbrains.skiko.hostOs
/**
* Standalone implementation of [MenuItemShortcutProvider] that maps context menu actions to platform-appropriate key
* strokes.
*/
@ApiStatus.Internal
@InternalJewelApi
public object StandaloneShortcutProvider : MenuItemShortcutProvider {
@@ -14,10 +14,13 @@ import org.jetbrains.jewel.ui.component.styling.DefaultBannerStyles
import org.jetbrains.jewel.ui.component.styling.InlineBannerStyle
import org.jetbrains.jewel.ui.component.styling.InlineBannerStyles
/** Provides access to the [IntUiDefaultBannerStylesFactory] via the [DefaultBannerStyles] companion. */
public val DefaultBannerStyles.Companion.Default: IntUiDefaultBannerStylesFactory
get() = IntUiDefaultBannerStylesFactory
/** Factory object for creating Int UI [DefaultBannerStyles] instances. */
public object IntUiDefaultBannerStylesFactory {
/** Creates an Int UI light [DefaultBannerStyles] with the provided parameters. */
public fun light(
information: DefaultBannerStyle = DefaultBannerStyle.Information.light(),
success: DefaultBannerStyle = DefaultBannerStyle.Success.light(),
@@ -26,6 +29,7 @@ public object IntUiDefaultBannerStylesFactory {
): DefaultBannerStyles =
DefaultBannerStyles(information = information, success = success, warning = warning, error = error)
/** Creates an Int UI dark [DefaultBannerStyles] with the provided parameters. */
public fun dark(
information: DefaultBannerStyle = DefaultBannerStyle.Information.dark(),
success: DefaultBannerStyle = DefaultBannerStyle.Success.dark(),
@@ -35,127 +39,148 @@ public object IntUiDefaultBannerStylesFactory {
DefaultBannerStyles(information = information, success = success, warning = warning, error = error)
}
// region Information Banner
/** Provides access to the [IntUiDefaultInformationBannerStyleFactory] via the [DefaultBannerStyle] companion. */
public val DefaultBannerStyle.Companion.Information: IntUiDefaultInformationBannerStyleFactory
get() = IntUiDefaultInformationBannerStyleFactory
/** Factory object for creating Int UI information-variant [DefaultBannerStyle] instances. */
public object IntUiDefaultInformationBannerStyleFactory {
/** Creates an Int UI light information [DefaultBannerStyle] with the provided parameters. */
public fun light(
colors: BannerColors = BannerColors.Information.light(),
metrics: BannerMetrics = BannerMetrics.default(),
): DefaultBannerStyle = DefaultBannerStyle(colors = colors, metrics = metrics)
/** Creates an Int UI dark information [DefaultBannerStyle] with the provided parameters. */
public fun dark(
colors: BannerColors = BannerColors.Information.dark(),
metrics: BannerMetrics = BannerMetrics.default(),
): DefaultBannerStyle = DefaultBannerStyle(colors = colors, metrics = metrics)
}
/** Provides access to the [IntUiInformationBannerColorFactory] via the [BannerColors] companion. */
public val BannerColors.Companion.Information: IntUiInformationBannerColorFactory
get() = IntUiInformationBannerColorFactory
/** Factory object for creating Int UI information-variant [BannerColors] instances. */
public object IntUiInformationBannerColorFactory {
/** Creates an Int UI light information [BannerColors] with the provided parameters. */
public fun light(
background: Color = IntUiLightTheme.colors.blue(13),
border: Color = IntUiLightTheme.colors.blue(10),
): BannerColors = BannerColors(background = background, border = border)
/** Creates an Int UI dark information [BannerColors] with the provided parameters. */
public fun dark(
background: Color = IntUiDarkTheme.colors.blue(1),
border: Color = IntUiDarkTheme.colors.blue(3),
): BannerColors = BannerColors(background = background, border = border)
}
// endregion
// region Success Banner
/** Provides access to the [IntUiDefaultSuccessBannerStyleFactory] via the [DefaultBannerStyle] companion. */
public val DefaultBannerStyle.Companion.Success: IntUiDefaultSuccessBannerStyleFactory
get() = IntUiDefaultSuccessBannerStyleFactory
/** Factory object for creating Int UI success-variant [DefaultBannerStyle] instances. */
public object IntUiDefaultSuccessBannerStyleFactory {
/** Creates an Int UI light success [DefaultBannerStyle] with the provided parameters. */
public fun light(
colors: BannerColors = BannerColors.Success.light(),
metrics: BannerMetrics = BannerMetrics.default(),
): DefaultBannerStyle = DefaultBannerStyle(colors = colors, metrics = metrics)
/** Creates an Int UI dark success [DefaultBannerStyle] with the provided parameters. */
public fun dark(
colors: BannerColors = BannerColors.Success.dark(),
metrics: BannerMetrics = BannerMetrics.default(),
): DefaultBannerStyle = DefaultBannerStyle(colors = colors, metrics = metrics)
}
/** Factory object for creating Int UI success-variant [BannerColors] instances. */
public object IntUiSuccessBannerColorFactory {
/** Creates an Int UI light success [BannerColors] with the provided parameters. */
public fun light(
background: Color = IntUiLightTheme.colors.green(11),
border: Color = IntUiLightTheme.colors.green(9),
): BannerColors = BannerColors(background = background, border = border)
/** Creates an Int UI dark success [BannerColors] with the provided parameters. */
public fun dark(
background: Color = IntUiDarkTheme.colors.green(1),
border: Color = IntUiDarkTheme.colors.green(3),
): BannerColors = BannerColors(background = background, border = border)
}
// endregion
// region Warning Banner
/** Provides access to the [IntUiDefaultWarningBannerStyleFactory] via the [DefaultBannerStyle] companion. */
public val DefaultBannerStyle.Companion.Warning: IntUiDefaultWarningBannerStyleFactory
get() = IntUiDefaultWarningBannerStyleFactory
/** Factory object for creating Int UI warning-variant [DefaultBannerStyle] instances. */
public object IntUiDefaultWarningBannerStyleFactory {
/** Creates an Int UI light warning [DefaultBannerStyle] with the provided parameters. */
public fun light(
colors: BannerColors = BannerColors.Warning.light(),
metrics: BannerMetrics = BannerMetrics.default(),
): DefaultBannerStyle = DefaultBannerStyle(colors = colors, metrics = metrics)
/** Creates an Int UI dark warning [DefaultBannerStyle] with the provided parameters. */
public fun dark(
colors: BannerColors = BannerColors.Warning.dark(),
metrics: BannerMetrics = BannerMetrics.default(),
): DefaultBannerStyle = DefaultBannerStyle(colors = colors, metrics = metrics)
}
/** Provides access to the [IntUiWarningBannerColorFactory] via the [BannerColors] companion. */
public val BannerColors.Companion.Warning: IntUiWarningBannerColorFactory
get() = IntUiWarningBannerColorFactory
/** Factory object for creating Int UI warning-variant [BannerColors] instances. */
public object IntUiWarningBannerColorFactory {
/** Creates an Int UI light warning [BannerColors] with the provided parameters. */
public fun light(
background: Color = IntUiLightTheme.colors.yellow(10),
border: Color = IntUiLightTheme.colors.yellow(6),
): BannerColors = BannerColors(background = background, border = border)
/** Creates an Int UI dark warning [BannerColors] with the provided parameters. */
public fun dark(
background: Color = IntUiDarkTheme.colors.yellow(1),
border: Color = IntUiDarkTheme.colors.yellow(2),
): BannerColors = BannerColors(background = background, border = border)
}
// endregion
// region Error Banner
/** Provides access to the [IntUiDefaultErrorBannerStyleFactory] via the [DefaultBannerStyle] companion. */
public val DefaultBannerStyle.Companion.Error: IntUiDefaultErrorBannerStyleFactory
get() = IntUiDefaultErrorBannerStyleFactory
/** Factory object for creating Int UI error-variant [DefaultBannerStyle] instances. */
public object IntUiDefaultErrorBannerStyleFactory {
/** Creates an Int UI light error [DefaultBannerStyle] with the provided parameters. */
public fun light(
colors: BannerColors = BannerColors.Error.light(),
metrics: BannerMetrics = BannerMetrics.default(),
): DefaultBannerStyle = DefaultBannerStyle(colors = colors, metrics = metrics)
/** Creates an Int UI dark error [DefaultBannerStyle] with the provided parameters. */
public fun dark(
colors: BannerColors = BannerColors.Error.dark(),
metrics: BannerMetrics = BannerMetrics.default(),
): DefaultBannerStyle = DefaultBannerStyle(colors = colors, metrics = metrics)
}
/** Provides access to the [IntUiErrorBannerColorFactory] via the [BannerColors] companion. */
public val BannerColors.Companion.Error: IntUiErrorBannerColorFactory
get() = IntUiErrorBannerColorFactory
/** Factory object for creating Int UI error-variant [BannerColors] instances. */
public object IntUiErrorBannerColorFactory {
/** Creates an Int UI light error [BannerColors] with the provided parameters. */
public fun light(
background: Color = IntUiLightTheme.colors.red(12),
border: Color = IntUiLightTheme.colors.red(9),
): BannerColors = BannerColors(background = background, border = border)
/** Creates an Int UI dark error [BannerColors] with the provided parameters. */
public fun dark(
background: Color = IntUiDarkTheme.colors.red(1),
border: Color = IntUiDarkTheme.colors.red(3),
@@ -164,10 +189,13 @@ public object IntUiErrorBannerColorFactory {
// endregion
/** Provides access to the [IntUiInlineBannerStylesFactory] via the [InlineBannerStyles] companion. */
public val InlineBannerStyles.Companion.Default: IntUiInlineBannerStylesFactory
get() = IntUiInlineBannerStylesFactory
/** Factory object for creating Int UI [InlineBannerStyles] instances. */
public object IntUiInlineBannerStylesFactory {
/** Creates an Int UI light [InlineBannerStyles] with the provided parameters. */
public fun light(
information: InlineBannerStyle = InlineBannerStyle.Information.light(),
success: InlineBannerStyle = InlineBannerStyle.Success.light(),
@@ -176,6 +204,7 @@ public object IntUiInlineBannerStylesFactory {
): InlineBannerStyles =
InlineBannerStyles(information = information, success = success, warning = warning, error = error)
/** Creates an Int UI dark [InlineBannerStyles] with the provided parameters. */
public fun dark(
information: InlineBannerStyle = InlineBannerStyle.Information.dark(),
success: InlineBannerStyle = InlineBannerStyle.Success.dark(),
@@ -185,6 +214,7 @@ public object IntUiInlineBannerStylesFactory {
InlineBannerStyles(information = information, success = success, warning = warning, error = error)
}
/** Creates an Int UI default [BannerMetrics] with the provided parameters. */
@Deprecated(
"Use the `default()` function with `cornerSize` and `paddingValues`",
replaceWith = ReplaceWith("default(borderWidth, cornerSize = TODO(), paddingValues = TODO())"),
@@ -192,79 +222,87 @@ public object IntUiInlineBannerStylesFactory {
public fun BannerMetrics.Companion.default(borderWidth: Dp = 1.dp): BannerMetrics =
BannerMetrics(borderWidth, CornerSize(8.dp), PaddingValues(12.dp))
/** Creates an Int UI default [BannerMetrics] with the provided parameters. */
public fun BannerMetrics.Companion.default(
borderWidth: Dp = 1.dp,
cornerSize: CornerSize = CornerSize(8.dp),
paddingValues: PaddingValues = PaddingValues(12.dp),
): BannerMetrics = BannerMetrics(borderWidth, cornerSize, paddingValues)
// region Inline Information Banner
/** Provides access to the [IntUiInlineInformationBannerStyleFactory] via the [InlineBannerStyle] companion. */
public val InlineBannerStyle.Companion.Information: IntUiInlineInformationBannerStyleFactory
get() = IntUiInlineInformationBannerStyleFactory
/** Factory object for creating Int UI information-variant [InlineBannerStyle] instances. */
public object IntUiInlineInformationBannerStyleFactory {
/** Creates an Int UI light information [InlineBannerStyle] with the provided parameters. */
public fun light(
colors: BannerColors = BannerColors.Information.light(),
metrics: BannerMetrics = BannerMetrics.default(),
): InlineBannerStyle = InlineBannerStyle(colors = colors, metrics = metrics)
/** Creates an Int UI dark information [InlineBannerStyle] with the provided parameters. */
public fun dark(
colors: BannerColors = BannerColors.Information.dark(),
metrics: BannerMetrics = BannerMetrics.default(),
): InlineBannerStyle = InlineBannerStyle(colors = colors, metrics = metrics)
}
// endregion
// region Inline Success Banner
/** Provides access to the [IntUiInlineSuccessBannerStyleFactory] via the [InlineBannerStyle] companion. */
public val InlineBannerStyle.Companion.Success: IntUiInlineSuccessBannerStyleFactory
get() = IntUiInlineSuccessBannerStyleFactory
/** Factory object for creating Int UI success-variant [InlineBannerStyle] instances. */
public object IntUiInlineSuccessBannerStyleFactory {
/** Creates an Int UI light success [InlineBannerStyle] with the provided parameters. */
public fun light(
colors: BannerColors = BannerColors.Success.light(),
metrics: BannerMetrics = BannerMetrics.default(),
): InlineBannerStyle = InlineBannerStyle(colors = colors, metrics = metrics)
/** Creates an Int UI dark success [InlineBannerStyle] with the provided parameters. */
public fun dark(
colors: BannerColors = BannerColors.Success.dark(),
metrics: BannerMetrics = BannerMetrics.default(),
): InlineBannerStyle = InlineBannerStyle(colors = colors, metrics = metrics)
}
/** Provides access to the [IntUiSuccessBannerColorFactory] via the [BannerColors] companion. */
public val BannerColors.Companion.Success: IntUiSuccessBannerColorFactory
get() = IntUiSuccessBannerColorFactory
// endregion
// region Inline Warning Banner
/** Provides access to the [IntUiInlineWarningBannerStyleFactory] via the [InlineBannerStyle] companion. */
public val InlineBannerStyle.Companion.Warning: IntUiInlineWarningBannerStyleFactory
get() = IntUiInlineWarningBannerStyleFactory
/** Factory object for creating Int UI warning-variant [InlineBannerStyle] instances. */
public object IntUiInlineWarningBannerStyleFactory {
/** Creates an Int UI light warning [InlineBannerStyle] with the provided parameters. */
public fun light(
colors: BannerColors = BannerColors.Warning.light(),
metrics: BannerMetrics = BannerMetrics.default(),
): InlineBannerStyle = InlineBannerStyle(colors = colors, metrics = metrics)
/** Creates an Int UI dark warning [InlineBannerStyle] with the provided parameters. */
public fun dark(
colors: BannerColors = BannerColors.Warning.dark(),
metrics: BannerMetrics = BannerMetrics.default(),
): InlineBannerStyle = InlineBannerStyle(colors = colors, metrics = metrics)
}
// endregion
// region Inline Error Banner
/** Provides access to the [IntUiInlineErrorBannerStyleFactory] via the [InlineBannerStyle] companion. */
public val InlineBannerStyle.Companion.Error: IntUiInlineErrorBannerStyleFactory
get() = IntUiInlineErrorBannerStyleFactory
/** Factory object for creating Int UI error-variant [InlineBannerStyle] instances. */
public object IntUiInlineErrorBannerStyleFactory {
/** Creates an Int UI light error [InlineBannerStyle] with the provided parameters. */
public fun light(
colors: BannerColors = BannerColors.Error.light(),
metrics: BannerMetrics = BannerMetrics.default(),
): InlineBannerStyle = InlineBannerStyle(colors = colors, metrics = metrics)
/** Creates an Int UI dark error [InlineBannerStyle] with the provided parameters. */
public fun dark(
colors: BannerColors = BannerColors.Error.dark(),
metrics: BannerMetrics = BannerMetrics.default(),
@@ -14,6 +14,7 @@ import org.jetbrains.jewel.ui.component.styling.BadgeMetrics
import org.jetbrains.jewel.ui.component.styling.BadgeStyle
import org.jetbrains.jewel.ui.component.styling.BadgeStyles
/** Creates an Int UI light [BadgeStyles] with the provided parameters. */
public fun BadgeStyles.Companion.light(
blue: BadgeStyle = BadgeStyle.Blue.light(),
blueSecondary: BadgeStyle = BadgeStyle.BlueSecondary.light(),
@@ -31,6 +32,7 @@ public fun BadgeStyles.Companion.light(
graySecondary = graySecondary,
)
/** Creates an Int UI dark [BadgeStyles] with the provided parameters. */
public fun BadgeStyles.Companion.dark(
blue: BadgeStyle = BadgeStyle.Blue.dark(),
blueSecondary: BadgeStyle = BadgeStyle.BlueSecondary.dark(),
@@ -48,24 +50,30 @@ public fun BadgeStyles.Companion.dark(
graySecondary = graySecondary,
)
/** Provides access to the Int UI blue [BadgeStyle] factory. */
public val BadgeStyle.Companion.Blue: IntUiBlueBadgeStyleFactory
get() = IntUiBlueBadgeStyleFactory
/** Factory object for creating Int UI blue [BadgeStyle] instances. */
public object IntUiBlueBadgeStyleFactory {
/** Creates an Int UI light blue [BadgeStyle] with the provided parameters. */
public fun light(
colors: BadgeColors = BadgeColors.Blue.light(),
metrics: BadgeMetrics = BadgeMetrics.default(),
): BadgeStyle = BadgeStyle(colors = colors, metrics = metrics)
/** Creates an Int UI dark blue [BadgeStyle] with the provided parameters. */
public fun dark(
colors: BadgeColors = BadgeColors.Blue.dark(),
metrics: BadgeMetrics = BadgeMetrics.default(),
): BadgeStyle = BadgeStyle(colors = colors, metrics = metrics)
}
/** Provides access to the Int UI blue [BadgeColors] factory. */
public val BadgeColors.Companion.Blue: IntUiBlueBadgeColorsFactory
get() = IntUiBlueBadgeColorsFactory
/** Factory object for creating Int UI blue [BadgeColors] instances. */
public object IntUiBlueBadgeColorsFactory {
private val lightBackground = IntUiLightTheme.colors.blueOrNull(4) ?: Color(0xFF3574F0)
private val lightContent = IntUiLightTheme.colors.grayOrNull(14) ?: Color(0xFFFFFFFF)
@@ -75,6 +83,7 @@ public object IntUiBlueBadgeColorsFactory {
private val darkContent = IntUiDarkTheme.colors.grayOrNull(1) ?: Color(0xFF1E1F22)
private val darkDisabled = IntUiDisabledBadgeColorsFactory.dark()
/** Creates an Int UI light blue [BadgeColors] with the provided parameters. */
public fun light(
background: Brush = SolidColor(lightBackground),
backgroundDisabled: Brush = SolidColor(lightDisabled.background),
@@ -100,6 +109,7 @@ public object IntUiBlueBadgeColorsFactory {
contentHovered = contentHovered,
)
/** Creates an Int UI dark blue [BadgeColors] with the provided parameters. */
public fun dark(
background: Brush = SolidColor(darkBackground),
backgroundDisabled: Brush = SolidColor(darkDisabled.background),
@@ -126,24 +136,30 @@ public object IntUiBlueBadgeColorsFactory {
)
}
/** Provides access to the Int UI blue-secondary [BadgeStyle] factory. */
public val BadgeStyle.Companion.BlueSecondary: IntUiBlueSecondaryBadgeStyleFactory
get() = IntUiBlueSecondaryBadgeStyleFactory
/** Factory object for creating Int UI blue-secondary [BadgeStyle] instances. */
public object IntUiBlueSecondaryBadgeStyleFactory {
/** Creates an Int UI light blue-secondary [BadgeStyle] with the provided parameters. */
public fun light(
colors: BadgeColors = BadgeColors.BlueSecondary.light(),
metrics: BadgeMetrics = BadgeMetrics.default(),
): BadgeStyle = BadgeStyle(colors = colors, metrics = metrics)
/** Creates an Int UI dark blue-secondary [BadgeStyle] with the provided parameters. */
public fun dark(
colors: BadgeColors = BadgeColors.BlueSecondary.dark(),
metrics: BadgeMetrics = BadgeMetrics.default(),
): BadgeStyle = BadgeStyle(colors = colors, metrics = metrics)
}
/** Provides access to the Int UI blue-secondary [BadgeColors] factory. */
public val BadgeColors.Companion.BlueSecondary: IntUiBlueSecondaryBadgeColorsFactory
get() = IntUiBlueSecondaryBadgeColorsFactory
/** Factory object for creating Int UI blue-secondary [BadgeColors] instances. */
public object IntUiBlueSecondaryBadgeColorsFactory {
private val lightBackground = Color(0x293574F0)
private val lightContent = IntUiLightTheme.colors.blueOrNull(1) ?: Color(0xFF2E55A3)
@@ -153,6 +169,7 @@ public object IntUiBlueSecondaryBadgeColorsFactory {
private val darkContent = IntUiDarkTheme.colors.blueOrNull(12) ?: Color(0xFFB5CEFF)
private val darkDisabled = IntUiDisabledBadgeColorsFactory.dark()
/** Creates an Int UI light blue-secondary [BadgeColors] with the provided parameters. */
public fun light(
background: Brush = SolidColor(lightBackground),
backgroundDisabled: Brush = SolidColor(lightDisabled.background),
@@ -178,6 +195,7 @@ public object IntUiBlueSecondaryBadgeColorsFactory {
contentHovered = contentHovered,
)
/** Creates an Int UI dark blue-secondary [BadgeColors] with the provided parameters. */
public fun dark(
background: Brush = SolidColor(darkBackground),
backgroundDisabled: Brush = SolidColor(darkDisabled.background),
@@ -204,24 +222,30 @@ public object IntUiBlueSecondaryBadgeColorsFactory {
)
}
/** Provides access to the Int UI purple-secondary [BadgeStyle] factory. */
public val BadgeStyle.Companion.PurpleSecondary: IntUiPurpleSecondaryBadgeStyleFactory
get() = IntUiPurpleSecondaryBadgeStyleFactory
/** Factory object for creating Int UI purple-secondary [BadgeStyle] instances. */
public object IntUiPurpleSecondaryBadgeStyleFactory {
/** Creates an Int UI light purple-secondary [BadgeStyle] with the provided parameters. */
public fun light(
colors: BadgeColors = BadgeColors.PurpleSecondary.light(),
metrics: BadgeMetrics = BadgeMetrics.default(),
): BadgeStyle = BadgeStyle(colors = colors, metrics = metrics)
/** Creates an Int UI dark purple-secondary [BadgeStyle] with the provided parameters. */
public fun dark(
colors: BadgeColors = BadgeColors.PurpleSecondary.dark(),
metrics: BadgeMetrics = BadgeMetrics.default(),
): BadgeStyle = BadgeStyle(colors = colors, metrics = metrics)
}
/** Provides access to the Int UI purple-secondary [BadgeColors] factory. */
public val BadgeColors.Companion.PurpleSecondary: IntUiPurpleSecondaryBadgeColorsFactory
get() = IntUiPurpleSecondaryBadgeColorsFactory
/** Factory object for creating Int UI purple-secondary [BadgeColors] instances. */
public object IntUiPurpleSecondaryBadgeColorsFactory {
private val lightBackground = Color(0x29834DF0)
private val lightContent = IntUiLightTheme.colors.purpleOrNull(1) ?: Color(0xFF55339C)
@@ -231,6 +255,7 @@ public object IntUiPurpleSecondaryBadgeColorsFactory {
private val darkContent = IntUiDarkTheme.colors.purpleOrNull(12) ?: Color(0xFFE4CEFF)
private val darkDisabled = IntUiDisabledBadgeColorsFactory.dark()
/** Creates an Int UI light purple-secondary [BadgeColors] with the provided parameters. */
public fun light(
background: Brush = SolidColor(lightBackground),
backgroundDisabled: Brush = SolidColor(lightDisabled.background),
@@ -256,6 +281,7 @@ public object IntUiPurpleSecondaryBadgeColorsFactory {
contentHovered = contentHovered,
)
/** Creates an Int UI dark purple-secondary [BadgeColors] with the provided parameters. */
public fun dark(
background: Brush = SolidColor(darkBackground),
backgroundDisabled: Brush = SolidColor(darkDisabled.background),
@@ -282,24 +308,30 @@ public object IntUiPurpleSecondaryBadgeColorsFactory {
)
}
/** Provides access to the Int UI green [BadgeStyle] factory. */
public val BadgeStyle.Companion.Green: IntUiGreenBadgeStyleFactory
get() = IntUiGreenBadgeStyleFactory
/** Factory object for creating Int UI green [BadgeStyle] instances. */
public object IntUiGreenBadgeStyleFactory {
/** Creates an Int UI light green [BadgeStyle] with the provided parameters. */
public fun light(
colors: BadgeColors = BadgeColors.Green.light(),
metrics: BadgeMetrics = BadgeMetrics.default(),
): BadgeStyle = BadgeStyle(colors = colors, metrics = metrics)
/** Creates an Int UI dark green [BadgeStyle] with the provided parameters. */
public fun dark(
colors: BadgeColors = BadgeColors.Green.dark(),
metrics: BadgeMetrics = BadgeMetrics.default(),
): BadgeStyle = BadgeStyle(colors = colors, metrics = metrics)
}
/** Provides access to the Int UI green [BadgeColors] factory. */
public val BadgeColors.Companion.Green: IntUiGreenBadgeColorsFactory
get() = IntUiGreenBadgeColorsFactory
/** Factory object for creating Int UI green [BadgeColors] instances. */
public object IntUiGreenBadgeColorsFactory {
private val lightBackground = IntUiLightTheme.colors.greenOrNull(4) ?: Color(0xFF208A3C)
private val lightContent = IntUiLightTheme.colors.grayOrNull(14) ?: Color(0xFFFFFFFF)
@@ -309,6 +341,7 @@ public object IntUiGreenBadgeColorsFactory {
private val darkContent = IntUiDarkTheme.colors.grayOrNull(1) ?: Color(0xFF1E1F22)
private val darkDisabled = IntUiDisabledBadgeColorsFactory.dark()
/** Creates an Int UI light green [BadgeColors] with the provided parameters. */
public fun light(
background: Brush = SolidColor(lightBackground),
backgroundDisabled: Brush = SolidColor(lightDisabled.background),
@@ -334,6 +367,7 @@ public object IntUiGreenBadgeColorsFactory {
contentHovered = contentHovered,
)
/** Creates an Int UI dark green [BadgeColors] with the provided parameters. */
public fun dark(
background: Brush = SolidColor(darkBackground),
backgroundDisabled: Brush = SolidColor(darkDisabled.background),
@@ -360,24 +394,30 @@ public object IntUiGreenBadgeColorsFactory {
)
}
/** Provides access to the Int UI green-secondary [BadgeStyle] factory. */
public val BadgeStyle.Companion.GreenSecondary: IntUiGreenSecondaryBadgeStyleFactory
get() = IntUiGreenSecondaryBadgeStyleFactory
/** Factory object for creating Int UI green-secondary [BadgeStyle] instances. */
public object IntUiGreenSecondaryBadgeStyleFactory {
/** Creates an Int UI light green-secondary [BadgeStyle] with the provided parameters. */
public fun light(
colors: BadgeColors = BadgeColors.GreenSecondary.light(),
metrics: BadgeMetrics = BadgeMetrics.default(),
): BadgeStyle = BadgeStyle(colors = colors, metrics = metrics)
/** Creates an Int UI dark green-secondary [BadgeStyle] with the provided parameters. */
public fun dark(
colors: BadgeColors = BadgeColors.GreenSecondary.dark(),
metrics: BadgeMetrics = BadgeMetrics.default(),
): BadgeStyle = BadgeStyle(colors = colors, metrics = metrics)
}
/** Provides access to the Int UI green-secondary [BadgeColors] factory. */
public val BadgeColors.Companion.GreenSecondary: IntUiGreenSecondaryBadgeColorsFactory
get() = IntUiGreenSecondaryBadgeColorsFactory
/** Factory object for creating Int UI green-secondary [BadgeColors] instances. */
public object IntUiGreenSecondaryBadgeColorsFactory {
private val lightBackground = Color(0x29208A3C)
private val lightContent = IntUiLightTheme.colors.greenOrNull(1) ?: Color(0xFF1E6B33)
@@ -387,6 +427,7 @@ public object IntUiGreenSecondaryBadgeColorsFactory {
private val darkContent = IntUiDarkTheme.colors.greenOrNull(12) ?: Color(0xFFD4FAD7)
private val darkDisabled = IntUiDisabledBadgeColorsFactory.dark()
/** Creates an Int UI light green-secondary [BadgeColors] with the provided parameters. */
public fun light(
background: Brush = SolidColor(lightBackground),
backgroundDisabled: Brush = SolidColor(lightDisabled.background),
@@ -412,6 +453,7 @@ public object IntUiGreenSecondaryBadgeColorsFactory {
contentHovered = contentHovered,
)
/** Creates an Int UI dark green-secondary [BadgeColors] with the provided parameters. */
public fun dark(
background: Brush = SolidColor(darkBackground),
backgroundDisabled: Brush = SolidColor(darkDisabled.background),
@@ -438,24 +480,30 @@ public object IntUiGreenSecondaryBadgeColorsFactory {
)
}
/** Provides access to the Int UI gray-secondary [BadgeStyle] factory. */
public val BadgeStyle.Companion.GraySecondary: IntUiGraySecondaryBadgeStyleFactory
get() = IntUiGraySecondaryBadgeStyleFactory
/** Factory object for creating Int UI gray-secondary [BadgeStyle] instances. */
public object IntUiGraySecondaryBadgeStyleFactory {
/** Creates an Int UI light gray-secondary [BadgeStyle] with the provided parameters. */
public fun light(
colors: BadgeColors = BadgeColors.GraySecondary.light(),
metrics: BadgeMetrics = BadgeMetrics.default(),
): BadgeStyle = BadgeStyle(colors = colors, metrics = metrics)
/** Creates an Int UI dark gray-secondary [BadgeStyle] with the provided parameters. */
public fun dark(
colors: BadgeColors = BadgeColors.GraySecondary.dark(),
metrics: BadgeMetrics = BadgeMetrics.default(),
): BadgeStyle = BadgeStyle(colors = colors, metrics = metrics)
}
/** Provides access to the Int UI gray-secondary [BadgeColors] factory. */
public val BadgeColors.Companion.GraySecondary: IntUiGraySecondaryBadgeColorsFactory
get() = IntUiGraySecondaryBadgeColorsFactory
/** Factory object for creating Int UI gray-secondary [BadgeColors] instances. */
public object IntUiGraySecondaryBadgeColorsFactory {
private val lightBackground = Color(0x1F6C707E)
private val lightContent = IntUiLightTheme.colors.grayOrNull(6) ?: Color(0xFF6C707E)
@@ -465,6 +513,7 @@ public object IntUiGraySecondaryBadgeColorsFactory {
private val darkContent = IntUiDarkTheme.colors.grayOrNull(10) ?: Color(0xFFB4B8BF)
private val darkDisabled = IntUiDisabledBadgeColorsFactory.dark()
/** Creates an Int UI light gray-secondary [BadgeColors] with the provided parameters. */
public fun light(
background: Brush = SolidColor(lightBackground.copy(alpha = .12f)),
backgroundDisabled: Brush = SolidColor(lightDisabled.background),
@@ -490,6 +539,7 @@ public object IntUiGraySecondaryBadgeColorsFactory {
contentHovered = contentHovered,
)
/** Creates an Int UI dark gray-secondary [BadgeColors] with the provided parameters. */
public fun dark(
background: Brush = SolidColor(darkBackground.copy(alpha = .20f)),
backgroundDisabled: Brush = SolidColor(darkDisabled.background),
@@ -516,6 +566,7 @@ public object IntUiGraySecondaryBadgeColorsFactory {
)
}
/** Creates an Int UI default [BadgeMetrics] with the provided parameters. */
public fun BadgeMetrics.Companion.default(
cornerSize: CornerSize = CornerSize(100),
padding: PaddingValues = PaddingValues(horizontal = 6.dp),
@@ -15,16 +15,20 @@ import org.jetbrains.jewel.ui.component.styling.ButtonColors
import org.jetbrains.jewel.ui.component.styling.ButtonMetrics
import org.jetbrains.jewel.ui.component.styling.ButtonStyle
/** Factory for creating Int UI default [ButtonStyle] instances. */
public val ButtonStyle.Companion.Default: IntUiDefaultButtonStyleFactory
get() = IntUiDefaultButtonStyleFactory
/** Factory object that creates Int UI default [ButtonStyle] instances for light and dark themes. */
public object IntUiDefaultButtonStyleFactory {
/** Creates an Int UI light default [ButtonStyle] with the provided parameters. */
public fun light(
colors: ButtonColors = ButtonColors.Default.light(),
metrics: ButtonMetrics = ButtonMetrics.default(),
focusOutlineAlignment: Stroke.Alignment = Stroke.Alignment.Center,
): ButtonStyle = ButtonStyle(colors, metrics, focusOutlineAlignment)
/** Creates an Int UI dark default [ButtonStyle] with the provided parameters. */
public fun dark(
colors: ButtonColors = ButtonColors.Default.dark(),
metrics: ButtonMetrics = ButtonMetrics.default(),
@@ -32,16 +36,20 @@ public object IntUiDefaultButtonStyleFactory {
): ButtonStyle = ButtonStyle(colors, metrics, focusOutlineAlignment)
}
/** Factory for creating Int UI outlined [ButtonStyle] instances. */
public val ButtonStyle.Companion.Outlined: IntUiOutlinedButtonStyleFactory
get() = IntUiOutlinedButtonStyleFactory
/** Factory object that creates Int UI outlined [ButtonStyle] instances for light and dark themes. */
public object IntUiOutlinedButtonStyleFactory {
/** Creates an Int UI light outlined [ButtonStyle] with the provided parameters. */
public fun light(
colors: ButtonColors = ButtonColors.Outlined.light(),
metrics: ButtonMetrics = ButtonMetrics.outlined(),
focusOutlineAlignment: Stroke.Alignment = Stroke.Alignment.Center,
): ButtonStyle = ButtonStyle(colors, metrics, focusOutlineAlignment)
/** Creates an Int UI dark outlined [ButtonStyle] with the provided parameters. */
public fun dark(
colors: ButtonColors = ButtonColors.Outlined.dark(),
metrics: ButtonMetrics = ButtonMetrics.outlined(),
@@ -49,10 +57,13 @@ public object IntUiOutlinedButtonStyleFactory {
): ButtonStyle = ButtonStyle(colors, metrics, focusOutlineAlignment)
}
/** Factory for creating Int UI default [ButtonColors] instances. */
public val ButtonColors.Companion.Default: IntUiDefaultButtonColorFactory
get() = IntUiDefaultButtonColorFactory
/** Factory object that creates Int UI default [ButtonColors] instances for light and dark themes. */
public object IntUiDefaultButtonColorFactory {
/** Creates an Int UI light default [ButtonColors] with the provided parameters. */
public fun light(
background: Brush = SolidColor(IntUiLightTheme.colors.blue(4)),
backgroundDisabled: Brush = SolidColor(Color.Unspecified),
@@ -88,6 +99,7 @@ public object IntUiDefaultButtonColorFactory {
borderHovered = borderHovered,
)
/** Creates an Int UI dark default [ButtonColors] with the provided parameters. */
public fun dark(
background: Brush = SolidColor(IntUiDarkTheme.colors.blue(6)),
backgroundDisabled: Brush = SolidColor(Color.Unspecified),
@@ -124,10 +136,13 @@ public object IntUiDefaultButtonColorFactory {
)
}
/** Factory for creating Int UI outlined [ButtonColors] instances. */
public val ButtonColors.Companion.Outlined: IntUiOutlinedButtonColorFactory
get() = IntUiOutlinedButtonColorFactory
/** Factory object that creates Int UI outlined [ButtonColors] instances for light and dark themes. */
public object IntUiOutlinedButtonColorFactory {
/** Creates an Int UI light outlined [ButtonColors] with the provided parameters. */
public fun light(
background: Brush = SolidColor(IntUiLightTheme.colors.gray(14)),
backgroundDisabled: Brush = SolidColor(Color.Unspecified),
@@ -163,6 +178,7 @@ public object IntUiOutlinedButtonColorFactory {
borderHovered = borderHovered,
)
/** Creates an Int UI dark outlined [ButtonColors] with the provided parameters. */
public fun dark(
background: Brush = SolidColor(Color.Transparent),
backgroundDisabled: Brush = SolidColor(Color.Unspecified),
@@ -199,6 +215,7 @@ public object IntUiOutlinedButtonColorFactory {
)
}
/** Creates an Int UI default [ButtonMetrics] with the provided parameters. */
public fun ButtonMetrics.Companion.default(
cornerSize: CornerSize = CornerSize(4.dp),
padding: PaddingValues = PaddingValues(horizontal = 12.dp, vertical = 6.dp),
@@ -207,6 +224,7 @@ public fun ButtonMetrics.Companion.default(
focusOutlineExpand: Dp = 1.5.dp,
): ButtonMetrics = ButtonMetrics(cornerSize, padding, minSize, borderWidth, focusOutlineExpand)
/** Creates an Int UI outlined [ButtonMetrics] with the provided parameters. */
public fun ButtonMetrics.Companion.outlined(
cornerSize: CornerSize = CornerSize(4.dp),
padding: PaddingValues = PaddingValues(horizontal = 12.dp, vertical = 6.dp),
@@ -215,24 +233,31 @@ public fun ButtonMetrics.Companion.outlined(
focusOutlineExpand: Dp = Dp.Unspecified,
): ButtonMetrics = ButtonMetrics(cornerSize, padding, minSize, borderWidth, focusOutlineExpand)
/** Factory for creating Int UI slim [ButtonStyle] instances. */
public val ButtonStyle.Companion.Slim: IntUiSlimButtonStyleFactory
get() = IntUiSlimButtonStyleFactory
/** Factory object that provides access to slim default and outlined [ButtonStyle] factories. */
public object IntUiSlimButtonStyleFactory {
/** Factory for creating Int UI slim default [ButtonStyle] instances. */
public val Default: IntUiSlimDefaultButtonStyleFactory
get() = IntUiSlimDefaultButtonStyleFactory
/** Factory for creating Int UI slim outlined [ButtonStyle] instances. */
public val Outlined: IntUiSlimOutlinedButtonStyleFactory
get() = IntUiSlimOutlinedButtonStyleFactory
}
/** Factory object that creates Int UI slim default [ButtonStyle] instances for light and dark themes. */
public object IntUiSlimDefaultButtonStyleFactory {
/** Creates an Int UI light slim default [ButtonStyle] with the provided parameters. */
public fun light(
colors: ButtonColors = ButtonColors.Default.light(),
metrics: ButtonMetrics = ButtonMetrics.Slim.default(),
focusOutlineAlignment: Stroke.Alignment = Stroke.Alignment.Center,
): ButtonStyle = ButtonStyle(colors, metrics, focusOutlineAlignment)
/** Creates an Int UI dark slim default [ButtonStyle] with the provided parameters. */
public fun dark(
colors: ButtonColors = ButtonColors.Default.dark(),
metrics: ButtonMetrics = ButtonMetrics.Slim.default(),
@@ -240,13 +265,16 @@ public object IntUiSlimDefaultButtonStyleFactory {
): ButtonStyle = ButtonStyle(colors, metrics, focusOutlineAlignment)
}
/** Factory object that creates Int UI slim outlined [ButtonStyle] instances for light and dark themes. */
public object IntUiSlimOutlinedButtonStyleFactory {
/** Creates an Int UI light slim outlined [ButtonStyle] with the provided parameters. */
public fun light(
colors: ButtonColors = ButtonColors.Outlined.light(),
metrics: ButtonMetrics = ButtonMetrics.Slim.outlined(),
focusOutlineAlignment: Stroke.Alignment = Stroke.Alignment.Center,
): ButtonStyle = ButtonStyle(colors, metrics, focusOutlineAlignment)
/** Creates an Int UI dark slim outlined [ButtonStyle] with the provided parameters. */
public fun dark(
colors: ButtonColors = ButtonColors.Outlined.dark(),
metrics: ButtonMetrics = ButtonMetrics.Slim.outlined(),
@@ -254,10 +282,13 @@ public object IntUiSlimOutlinedButtonStyleFactory {
): ButtonStyle = ButtonStyle(colors, metrics, focusOutlineAlignment)
}
/** Factory for creating Int UI slim [ButtonMetrics] instances. */
public val ButtonMetrics.Companion.Slim: IntUiSlimButtonMetricsFactory
get() = IntUiSlimButtonMetricsFactory
/** Factory object that creates Int UI slim [ButtonMetrics] instances. */
public object IntUiSlimButtonMetricsFactory {
/** Creates an Int UI slim default [ButtonMetrics] with the provided parameters. */
public fun default(
cornerSize: CornerSize = CornerSize(4.dp),
padding: PaddingValues = PaddingValues(horizontal = 12.dp, vertical = 2.dp),
@@ -266,6 +297,7 @@ public object IntUiSlimButtonMetricsFactory {
focusOutlineExpand: Dp = 1.5.dp,
): ButtonMetrics = ButtonMetrics(cornerSize, padding, minSize, borderWidth, focusOutlineExpand)
/** Creates an Int UI slim outlined [ButtonMetrics] with the provided parameters. */
public fun outlined(
cornerSize: CornerSize = CornerSize(4.dp),
padding: PaddingValues = PaddingValues(horizontal = 12.dp, vertical = 2.dp),
@@ -14,30 +14,35 @@ import org.jetbrains.jewel.ui.component.styling.CheckboxStyle
import org.jetbrains.jewel.ui.icon.IconKey
import org.jetbrains.jewel.ui.icon.PathIconKey
/** Creates an Int UI light [CheckboxStyle] with the provided parameters. */
public fun CheckboxStyle.Companion.light(
colors: CheckboxColors = CheckboxColors.light(),
metrics: CheckboxMetrics = CheckboxMetrics.defaults(),
icons: CheckboxIcons = CheckboxIcons.light(),
): CheckboxStyle = CheckboxStyle(colors, metrics, icons)
/** Creates an Int UI dark [CheckboxStyle] with the provided parameters. */
public fun CheckboxStyle.Companion.dark(
colors: CheckboxColors = CheckboxColors.dark(),
metrics: CheckboxMetrics = CheckboxMetrics.defaults(),
icons: CheckboxIcons = CheckboxIcons.dark(),
): CheckboxStyle = CheckboxStyle(colors, metrics, icons)
/** Creates an Int UI light [CheckboxColors] with the provided parameters. */
public fun CheckboxColors.Companion.light(
content: Color = Color.Unspecified,
contentDisabled: Color = IntUiLightTheme.colors.gray(8),
contentSelected: Color = content,
): CheckboxColors = CheckboxColors(content, contentDisabled, contentSelected)
/** Creates an Int UI dark [CheckboxColors] with the provided parameters. */
public fun CheckboxColors.Companion.dark(
content: Color = Color.Unspecified,
contentDisabled: Color = IntUiDarkTheme.colors.gray(7),
contentSelected: Color = content,
): CheckboxColors = CheckboxColors(content, contentDisabled, contentSelected)
/** Creates an Int UI default [CheckboxMetrics] with the provided parameters. */
public fun CheckboxMetrics.Companion.defaults(
checkboxSize: DpSize = DpSize(24.dp, 24.dp),
outlineCornerSize: CornerSize = CornerSize(3.dp),
@@ -63,11 +68,13 @@ public fun CheckboxMetrics.Companion.defaults(
iconContentGap = iconContentGap,
)
/** Creates an Int UI light [CheckboxIcons] with the provided parameters. */
public fun CheckboxIcons.Companion.light(
checkbox: IconKey =
PathIconKey(path = "com/intellij/ide/ui/laf/icons/intellij/checkBox.svg", iconClass = CheckboxIcons::class.java)
): CheckboxIcons = CheckboxIcons(checkbox)
/** Creates an Int UI dark [CheckboxIcons] with the provided parameters. */
public fun CheckboxIcons.Companion.dark(
checkbox: IconKey =
PathIconKey(path = "com/intellij/ide/ui/laf/icons/darcula/checkBox.svg", iconClass = CheckboxIcons::class.java)
@@ -14,16 +14,19 @@ import org.jetbrains.jewel.ui.component.styling.ChipColors
import org.jetbrains.jewel.ui.component.styling.ChipMetrics
import org.jetbrains.jewel.ui.component.styling.ChipStyle
/** Creates an Int UI light [ChipStyle] with the provided parameters. */
public fun ChipStyle.Companion.light(
colors: ChipColors = ChipColors.light(),
metrics: ChipMetrics = ChipMetrics.defaults(),
): ChipStyle = ChipStyle(colors, metrics)
/** Creates an Int UI dark [ChipStyle] with the provided parameters. */
public fun ChipStyle.Companion.dark(
colors: ChipColors = ChipColors.dark(),
metrics: ChipMetrics = ChipMetrics.defaults(),
): ChipStyle = ChipStyle(colors, metrics)
/** Creates an Int UI light [ChipColors] with the provided parameters. */
public fun ChipColors.Companion.light(
background: Brush = SolidColor(IntUiLightTheme.colors.gray(14)),
backgroundDisabled: Brush = SolidColor(IntUiLightTheme.colors.gray(12)),
@@ -89,6 +92,7 @@ public fun ChipColors.Companion.light(
borderSelectedHovered = borderSelectedHovered,
)
/** Creates an Int UI dark [ChipColors] with the provided parameters. */
public fun ChipColors.Companion.dark(
background: Brush = SolidColor(IntUiDarkTheme.colors.gray(2)),
backgroundDisabled: Brush = SolidColor(IntUiDarkTheme.colors.gray(4)),
@@ -154,6 +158,7 @@ public fun ChipColors.Companion.dark(
borderSelectedHovered = borderSelectedHovered,
)
/** Creates an Int UI default [ChipMetrics] with the provided parameters. */
@Deprecated("Use the version with 'minSize' instead", level = DeprecationLevel.HIDDEN)
public fun ChipMetrics.Companion.defaults(
cornerSize: CornerSize = CornerSize(100),
@@ -162,6 +167,7 @@ public fun ChipMetrics.Companion.defaults(
borderWidthSelected: Dp = 2.dp,
): ChipMetrics = ChipMetrics(cornerSize, padding, borderWidth, borderWidthSelected, DpSize(72.dp, 28.dp))
/** Creates an Int UI default [ChipMetrics] with the provided parameters. */
public fun ChipMetrics.Companion.defaults(
cornerSize: CornerSize = CornerSize(100),
padding: PaddingValues = PaddingValues(horizontal = 12.dp, vertical = 8.dp),
@@ -7,11 +7,13 @@ import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds
import org.jetbrains.jewel.ui.component.styling.CircularProgressStyle
/** Creates an Int UI dark [CircularProgressStyle] with the provided parameters. */
public fun CircularProgressStyle.Companion.dark(
frameTime: Duration = 125.milliseconds,
color: Color = Color(0xFF6F737A),
): CircularProgressStyle = CircularProgressStyle(frameTime, color)
/** Creates an Int UI light [CircularProgressStyle] with the provided parameters. */
public fun CircularProgressStyle.Companion.light(
frameTime: Duration = 125.milliseconds,
color: Color = Color(0xFFA8ADBD),
@@ -16,16 +16,20 @@ import org.jetbrains.jewel.ui.component.styling.ComboBoxStyle
import org.jetbrains.jewel.ui.icon.IconKey
import org.jetbrains.jewel.ui.icons.AllIconsKeys
/** Provides access to [IntUiDefaultComboBoxStyleFactory] for creating default-style [ComboBoxStyle] instances. */
public val ComboBoxStyle.Companion.Default: IntUiDefaultComboBoxStyleFactory
get() = IntUiDefaultComboBoxStyleFactory
/** Factory object for creating Int UI default [ComboBoxStyle] instances. */
public object IntUiDefaultComboBoxStyleFactory {
/** Creates an Int UI light default [ComboBoxStyle] with the provided parameters. */
public fun light(
colors: ComboBoxColors = ComboBoxColors.Default.light(),
metrics: ComboBoxMetrics = ComboBoxMetrics.defaultWithRowCount(maxPopupRowCount = 10),
icons: ComboBoxIcons = ComboBoxIcons.defaults(),
): ComboBoxStyle = ComboBoxStyle(colors, metrics, icons)
/** Creates an Int UI dark default [ComboBoxStyle] with the provided parameters. */
public fun dark(
colors: ComboBoxColors = ComboBoxColors.Default.dark(),
metrics: ComboBoxMetrics = ComboBoxMetrics.defaultWithRowCount(maxPopupRowCount = 10),
@@ -33,16 +37,20 @@ public object IntUiDefaultComboBoxStyleFactory {
): ComboBoxStyle = ComboBoxStyle(colors, metrics, icons)
}
/** Provides access to [IntUiUndecoratedComboBoxStyleFactory] for creating undecorated [ComboBoxStyle] instances. */
public val ComboBoxStyle.Companion.Undecorated: IntUiUndecoratedComboBoxStyleFactory
get() = IntUiUndecoratedComboBoxStyleFactory
/** Factory object for creating Int UI undecorated [ComboBoxStyle] instances. */
public object IntUiUndecoratedComboBoxStyleFactory {
/** Creates an Int UI light undecorated [ComboBoxStyle] with the provided parameters. */
public fun light(
colors: ComboBoxColors = ComboBoxColors.Undecorated.light(),
metrics: ComboBoxMetrics = ComboBoxMetrics.undecoratedWithRowCount(maxPopupRowCount = 10),
icons: ComboBoxIcons = ComboBoxIcons.defaults(),
): ComboBoxStyle = ComboBoxStyle(colors, metrics, icons)
/** Creates an Int UI dark undecorated [ComboBoxStyle] with the provided parameters. */
public fun dark(
colors: ComboBoxColors = ComboBoxColors.Undecorated.dark(),
metrics: ComboBoxMetrics = ComboBoxMetrics.undecoratedWithRowCount(maxPopupRowCount = 10),
@@ -50,10 +58,13 @@ public object IntUiUndecoratedComboBoxStyleFactory {
): ComboBoxStyle = ComboBoxStyle(colors, metrics, icons)
}
/** Provides access to [IntUiDefaultComboBoxColorsFactory] for creating default-style [ComboBoxColors] instances. */
public val ComboBoxColors.Companion.Default: IntUiDefaultComboBoxColorsFactory
get() = IntUiDefaultComboBoxColorsFactory
/** Factory object for creating Int UI default [ComboBoxColors] instances. */
public object IntUiDefaultComboBoxColorsFactory {
/** Creates an Int UI light default [ComboBoxColors] with the provided parameters. */
public fun light(
background: Color = IntUiLightTheme.colors.gray(14),
backgroundDisabled: Color = IntUiLightTheme.colors.gray(13),
@@ -91,6 +102,7 @@ public object IntUiDefaultComboBoxColorsFactory {
borderHovered = borderHovered,
)
/** Creates an Int UI dark default [ComboBoxColors] with the provided parameters. */
public fun dark(
background: Color = IntUiDarkTheme.colors.gray(2),
backgroundDisabled: Color = background,
@@ -129,10 +141,13 @@ public object IntUiDefaultComboBoxColorsFactory {
)
}
/** Provides access to [IntUiUndecoratedComboBoxColorsFactory] for creating undecorated [ComboBoxColors] instances. */
public val ComboBoxColors.Companion.Undecorated: IntUiUndecoratedComboBoxColorsFactory
get() = IntUiUndecoratedComboBoxColorsFactory
/** Factory object for creating Int UI undecorated [ComboBoxColors] instances. */
public object IntUiUndecoratedComboBoxColorsFactory {
/** Creates an Int UI light undecorated [ComboBoxColors] with the provided parameters. */
public fun light(
background: Color = Color.Transparent,
backgroundDisabled: Color = background,
@@ -165,6 +180,7 @@ public object IntUiUndecoratedComboBoxColorsFactory {
borderHovered = Color.Transparent,
)
/** Creates an Int UI dark undecorated [ComboBoxColors] with the provided parameters. */
public fun dark(
background: Color = Color.Transparent,
backgroundDisabled: Color = background,
@@ -198,6 +214,7 @@ public object IntUiUndecoratedComboBoxColorsFactory {
)
}
/** Creates an Int UI default [ComboBoxMetrics] constrained by a maximum popup row count. */
public fun ComboBoxMetrics.Companion.defaultWithRowCount(
arrowAreaSize: DpSize = DpSize(28.dp, 28.dp),
minSize: DpSize = DpSize(77.dp, 28.dp),
@@ -218,6 +235,7 @@ public fun ComboBoxMetrics.Companion.defaultWithRowCount(
maxPopupRowCount,
)
/** Creates an Int UI default [ComboBoxMetrics] constrained by a maximum popup height. */
public fun ComboBoxMetrics.Companion.default(
arrowAreaSize: DpSize = DpSize(28.dp, 28.dp),
minSize: DpSize = DpSize(77.dp, 28.dp),
@@ -238,6 +256,7 @@ public fun ComboBoxMetrics.Companion.default(
8, // For backwards compatibility
)
/** Creates an Int UI undecorated [ComboBoxMetrics] constrained by a maximum popup row count. */
public fun ComboBoxMetrics.Companion.undecoratedWithRowCount(
arrowAreaSize: DpSize = DpSize(28.dp, 28.dp),
minSize: DpSize = DpSize(77.dp, 28.dp),
@@ -258,6 +277,7 @@ public fun ComboBoxMetrics.Companion.undecoratedWithRowCount(
maxPopupRowCount,
)
/** Creates an Int UI undecorated [ComboBoxMetrics] constrained by a maximum popup height. */
public fun ComboBoxMetrics.Companion.undecorated(
arrowAreaSize: DpSize = DpSize(28.dp, 28.dp),
minSize: DpSize = DpSize(77.dp, 28.dp),
@@ -278,5 +298,6 @@ public fun ComboBoxMetrics.Companion.undecorated(
8,
)
/** Creates a default [ComboBoxIcons] with the provided parameters. */
public fun ComboBoxIcons.Companion.defaults(chevronDown: IconKey = AllIconsKeys.General.ChevronDown): ComboBoxIcons =
ComboBoxIcons(chevronDown)
@@ -6,11 +6,13 @@ import org.jetbrains.jewel.intui.core.theme.IntUiLightTheme
import org.jetbrains.jewel.ui.component.styling.DividerMetrics
import org.jetbrains.jewel.ui.component.styling.DividerStyle
/** Creates an Int UI light [DividerStyle] with the provided parameters. */
public fun DividerStyle.Companion.light(
color: Color = IntUiLightTheme.colors.gray(12),
metrics: DividerMetrics = DividerMetrics.defaults(),
): DividerStyle = DividerStyle(color, metrics)
/** Creates an Int UI dark [DividerStyle] with the provided parameters. */
public fun DividerStyle.Companion.dark(
color: Color = IntUiDarkTheme.colors.gray(1),
metrics: DividerMetrics = DividerMetrics.defaults(),
@@ -16,10 +16,13 @@ import org.jetbrains.jewel.ui.component.styling.MenuStyle
import org.jetbrains.jewel.ui.icon.IconKey
import org.jetbrains.jewel.ui.icons.AllIconsKeys
/** Provides access to the factory for creating Int UI default [DropdownStyle] instances. */
public val DropdownStyle.Companion.Default: IntUiDefaultDropdownStyleFactory
get() = IntUiDefaultDropdownStyleFactory
/** Factory for creating Int UI default [DropdownStyle] instances. */
public object IntUiDefaultDropdownStyleFactory {
/** Creates an Int UI light default [DropdownStyle] with the provided parameters. */
public fun light(
colors: DropdownColors = DropdownColors.Default.light(),
metrics: DropdownMetrics = DropdownMetrics.default(),
@@ -27,6 +30,7 @@ public object IntUiDefaultDropdownStyleFactory {
menuStyle: MenuStyle = MenuStyle.light(),
): DropdownStyle = DropdownStyle(colors, metrics, icons, menuStyle)
/** Creates an Int UI dark default [DropdownStyle] with the provided parameters. */
public fun dark(
colors: DropdownColors = DropdownColors.Default.dark(),
metrics: DropdownMetrics = DropdownMetrics.default(),
@@ -35,10 +39,13 @@ public object IntUiDefaultDropdownStyleFactory {
): DropdownStyle = DropdownStyle(colors, metrics, icons, menuStyle)
}
/** Provides access to the factory for creating Int UI undecorated [DropdownStyle] instances. */
public val DropdownStyle.Companion.Undecorated: IntUiUndecoratedDropdownStyleFactory
get() = IntUiUndecoratedDropdownStyleFactory
/** Factory for creating Int UI undecorated [DropdownStyle] instances. */
public object IntUiUndecoratedDropdownStyleFactory {
/** Creates an Int UI light undecorated [DropdownStyle] with the provided parameters. */
public fun light(
colors: DropdownColors = DropdownColors.Undecorated.light(),
metrics: DropdownMetrics = DropdownMetrics.undecorated(),
@@ -46,6 +53,7 @@ public object IntUiUndecoratedDropdownStyleFactory {
menuStyle: MenuStyle = MenuStyle.light(),
): DropdownStyle = DropdownStyle(colors, metrics, icons, menuStyle)
/** Creates an Int UI dark undecorated [DropdownStyle] with the provided parameters. */
public fun dark(
colors: DropdownColors = DropdownColors.Undecorated.dark(),
metrics: DropdownMetrics = DropdownMetrics.undecorated(),
@@ -54,10 +62,13 @@ public object IntUiUndecoratedDropdownStyleFactory {
): DropdownStyle = DropdownStyle(colors, metrics, icons, menuStyle)
}
/** Provides access to the factory for creating Int UI default [DropdownColors] instances. */
public val DropdownColors.Companion.Default: IntUiDefaultDropdownColorsFactory
get() = IntUiDefaultDropdownColorsFactory
/** Factory for creating Int UI default [DropdownColors] instances. */
public object IntUiDefaultDropdownColorsFactory {
/** Creates an Int UI light default [DropdownColors] with the provided parameters. */
public fun light(
background: Color = IntUiLightTheme.colors.gray(14),
backgroundDisabled: Color = IntUiLightTheme.colors.gray(13),
@@ -103,6 +114,7 @@ public object IntUiDefaultDropdownColorsFactory {
iconTintHovered = iconTintHovered,
)
/** Creates an Int UI dark default [DropdownColors] with the provided parameters. */
public fun dark(
background: Color = IntUiDarkTheme.colors.gray(2),
backgroundDisabled: Color = background,
@@ -149,10 +161,13 @@ public object IntUiDefaultDropdownColorsFactory {
)
}
/** Provides access to the factory for creating Int UI undecorated [DropdownColors] instances. */
public val DropdownColors.Companion.Undecorated: IntUiUndecoratedDropdownColorsFactory
get() = IntUiUndecoratedDropdownColorsFactory
/** Factory for creating Int UI undecorated [DropdownColors] instances. */
public object IntUiUndecoratedDropdownColorsFactory {
/** Creates an Int UI light undecorated [DropdownColors] with the provided parameters. */
public fun light(
background: Color = Color.Transparent,
backgroundDisabled: Color = background,
@@ -193,6 +208,7 @@ public object IntUiUndecoratedDropdownColorsFactory {
iconTintHovered = iconTintHovered,
)
/** Creates an Int UI dark undecorated [DropdownColors] with the provided parameters. */
public fun dark(
background: Color = Color.Transparent,
backgroundDisabled: Color = background,
@@ -234,6 +250,7 @@ public object IntUiUndecoratedDropdownColorsFactory {
)
}
/** Creates an Int UI default [DropdownMetrics] with the provided parameters. */
public fun DropdownMetrics.Companion.default(
arrowMinSize: DpSize = DpSize((23 + 3).dp, 24.dp),
minSize: DpSize = DpSize((49 + 23 + 6).dp, 24.dp),
@@ -242,6 +259,7 @@ public fun DropdownMetrics.Companion.default(
borderWidth: Dp = 1.dp,
): DropdownMetrics = DropdownMetrics(arrowMinSize, minSize, cornerSize, contentPadding, borderWidth)
/** Creates an Int UI undecorated [DropdownMetrics] with the provided parameters. */
public fun DropdownMetrics.Companion.undecorated(
arrowMinSize: DpSize = DpSize((23 + 3).dp, 24.dp),
minSize: DpSize = DpSize((49 + 23 + 6).dp, 24.dp),
@@ -250,5 +268,6 @@ public fun DropdownMetrics.Companion.undecorated(
borderWidth: Dp = 0.dp,
): DropdownMetrics = DropdownMetrics(arrowMinSize, minSize, cornerSize, contentPadding, borderWidth)
/** Creates an Int UI default [DropdownIcons] with the provided parameters. */
public fun DropdownIcons.Companion.defaults(chevronDown: IconKey = AllIconsKeys.General.ChevronDown): DropdownIcons =
DropdownIcons(chevronDown)
@@ -9,21 +9,26 @@ import org.jetbrains.jewel.ui.component.styling.GroupHeaderColors
import org.jetbrains.jewel.ui.component.styling.GroupHeaderMetrics
import org.jetbrains.jewel.ui.component.styling.GroupHeaderStyle
/** Creates an Int UI light [GroupHeaderStyle] with the provided parameters. */
public fun GroupHeaderStyle.Companion.light(
colors: GroupHeaderColors = GroupHeaderColors.light(),
metrics: GroupHeaderMetrics = GroupHeaderMetrics.defaults(),
): GroupHeaderStyle = GroupHeaderStyle(colors, metrics)
/** Creates an Int UI dark [GroupHeaderStyle] with the provided parameters. */
public fun GroupHeaderStyle.Companion.dark(
colors: GroupHeaderColors = GroupHeaderColors.dark(),
metrics: GroupHeaderMetrics = GroupHeaderMetrics.defaults(),
): GroupHeaderStyle = GroupHeaderStyle(colors, metrics)
/** Creates an Int UI light [GroupHeaderColors] with the provided parameters. */
public fun GroupHeaderColors.Companion.light(divider: Color = IntUiLightTheme.colors.gray(12)): GroupHeaderColors =
GroupHeaderColors(divider)
/** Creates an Int UI dark [GroupHeaderColors] with the provided parameters. */
public fun GroupHeaderColors.Companion.dark(divider: Color = IntUiDarkTheme.colors.gray(3)): GroupHeaderColors =
GroupHeaderColors(divider)
/** Creates an Int UI default [GroupHeaderMetrics] with the provided parameters. */
public fun GroupHeaderMetrics.Companion.defaults(dividerThickness: Dp = 1.dp, indent: Dp = 8.dp): GroupHeaderMetrics =
GroupHeaderMetrics(dividerThickness, indent)
@@ -12,18 +12,21 @@ import org.jetbrains.jewel.ui.component.styling.HorizontalProgressBarColors
import org.jetbrains.jewel.ui.component.styling.HorizontalProgressBarMetrics
import org.jetbrains.jewel.ui.component.styling.HorizontalProgressBarStyle
/** Creates an Int UI light [HorizontalProgressBarStyle] with the provided parameters. */
public fun HorizontalProgressBarStyle.Companion.light(
colors: HorizontalProgressBarColors = HorizontalProgressBarColors.light(),
metrics: HorizontalProgressBarMetrics = HorizontalProgressBarMetrics.defaults(),
indeterminateCycleDuration: Duration = 800.milliseconds,
): HorizontalProgressBarStyle = HorizontalProgressBarStyle(colors, metrics, indeterminateCycleDuration)
/** Creates an Int UI dark [HorizontalProgressBarStyle] with the provided parameters. */
public fun HorizontalProgressBarStyle.Companion.dark(
colors: HorizontalProgressBarColors = HorizontalProgressBarColors.dark(),
metrics: HorizontalProgressBarMetrics = HorizontalProgressBarMetrics.defaults(),
indeterminateCycleDuration: Duration = 800.milliseconds,
): HorizontalProgressBarStyle = HorizontalProgressBarStyle(colors, metrics, indeterminateCycleDuration)
/** Creates an Int UI light [HorizontalProgressBarColors] with the provided parameters. */
public fun HorizontalProgressBarColors.Companion.light(
track: Color = IntUiLightTheme.colors.gray(11),
progress: Color = IntUiLightTheme.colors.blue(4),
@@ -37,6 +40,7 @@ public fun HorizontalProgressBarColors.Companion.light(
indeterminateHighlight = indeterminateHighlight,
)
/** Creates an Int UI dark [HorizontalProgressBarColors] with the provided parameters. */
public fun HorizontalProgressBarColors.Companion.dark(
track: Color = IntUiDarkTheme.colors.gray(4),
progress: Color = IntUiDarkTheme.colors.blue(7),
@@ -50,6 +54,7 @@ public fun HorizontalProgressBarColors.Companion.dark(
indeterminateHighlight = indeterminateHighlight,
)
/** Creates an Int UI default [HorizontalProgressBarMetrics] with the provided parameters. */
public fun HorizontalProgressBarMetrics.Companion.defaults(
cornerSize: CornerSize = CornerSize(100),
minHeight: Dp = 4.dp,
@@ -14,16 +14,19 @@ import org.jetbrains.jewel.ui.component.styling.IconButtonColors
import org.jetbrains.jewel.ui.component.styling.IconButtonMetrics
import org.jetbrains.jewel.ui.component.styling.IconButtonStyle
/** Creates an Int UI light [IconButtonStyle] with the provided parameters. */
public fun IconButtonStyle.Companion.light(
colors: IconButtonColors = IconButtonColors.light(),
metrics: IconButtonMetrics = IconButtonMetrics.defaults(),
): IconButtonStyle = IconButtonStyle(colors, metrics)
/** Creates an Int UI dark [IconButtonStyle] with the provided parameters. */
public fun IconButtonStyle.Companion.dark(
colors: IconButtonColors = IconButtonColors.dark(),
metrics: IconButtonMetrics = IconButtonMetrics.defaults(),
): IconButtonStyle = IconButtonStyle(colors, metrics)
/** Creates an Int UI light [IconButtonStyle] with a fully transparent background. */
@ApiStatus.Experimental
@ExperimentalJewelApi
public fun IconButtonStyle.Companion.lightTransparentBackground(
@@ -31,6 +34,7 @@ public fun IconButtonStyle.Companion.lightTransparentBackground(
metrics: IconButtonMetrics = IconButtonMetrics.defaults(),
): IconButtonStyle = IconButtonStyle(colors, metrics)
/** Creates an Int UI dark [IconButtonStyle] with a fully transparent background. */
@ApiStatus.Experimental
@ExperimentalJewelApi
public fun IconButtonStyle.Companion.darkTransparentBackground(
@@ -38,6 +42,7 @@ public fun IconButtonStyle.Companion.darkTransparentBackground(
metrics: IconButtonMetrics = IconButtonMetrics.defaults(),
): IconButtonStyle = IconButtonStyle(colors, metrics)
/** Creates an Int UI light [IconButtonColors] with the provided parameters. */
public fun IconButtonColors.Companion.light(
foregroundSelectedActivated: Color = IntUiLightTheme.colors.gray(14),
background: Color = Color.Unspecified,
@@ -73,6 +78,7 @@ public fun IconButtonColors.Companion.light(
borderHovered = borderHovered,
)
/** Creates an Int UI light [IconButtonColors] with a fully transparent background. */
@ApiStatus.Experimental
@ExperimentalJewelApi
public fun IconButtonColors.Companion.lightTransparentBackground(
@@ -96,6 +102,7 @@ public fun IconButtonColors.Companion.lightTransparentBackground(
borderHovered = Color.Transparent,
)
/** Creates an Int UI dark [IconButtonColors] with the provided parameters. */
public fun IconButtonColors.Companion.dark(
foregroundSelectedActivated: Color = IntUiDarkTheme.colors.gray(14),
background: Color = Color.Unspecified,
@@ -131,6 +138,7 @@ public fun IconButtonColors.Companion.dark(
borderHovered = borderHovered,
)
/** Creates an Int UI dark [IconButtonColors] with a fully transparent background. */
@ApiStatus.Experimental
@ExperimentalJewelApi
public fun IconButtonColors.Companion.darkTransparentBackground(
@@ -154,6 +162,7 @@ public fun IconButtonColors.Companion.darkTransparentBackground(
borderHovered = Color.Transparent,
)
/** Creates an Int UI default [IconButtonMetrics] with the provided parameters. */
public fun IconButtonMetrics.Companion.defaults(
cornerSize: CornerSize = CornerSize(4.dp),
borderWidth: Dp = 1.dp,
@@ -19,7 +19,9 @@ import org.jetbrains.jewel.ui.icons.AllIconsKeys
private val SimpleListItemStyle.Companion.LazyTree: IntUiDefaultSimpleListItemLazyTreeStyleFactory
get() = IntUiDefaultSimpleListItemLazyTreeStyleFactory
/** Factory object for creating Int UI [SimpleListItemColors] instances for lazy tree nodes. */
public object IntUiDefaultSimpleListItemLazyTreeStyleFactory {
/** Creates an Int UI light [SimpleListItemColors] for lazy tree nodes with the provided parameters. */
public fun light(
content: Color = Color.Unspecified,
contentActive: Color = content,
@@ -41,6 +43,7 @@ public object IntUiDefaultSimpleListItemLazyTreeStyleFactory {
contentSelectedActive = contentSelectedActive,
)
/** Creates an Int UI dark [SimpleListItemColors] for lazy tree nodes with the provided parameters. */
public fun dark(
content: Color = Color.Unspecified,
contentActive: Color = content,
@@ -63,18 +66,21 @@ public object IntUiDefaultSimpleListItemLazyTreeStyleFactory {
)
}
/** Creates an Int UI light [LazyTreeStyle] with the provided parameters. */
public fun LazyTreeStyle.Companion.light(
colors: SimpleListItemColors = SimpleListItemStyle.LazyTree.light(),
metrics: LazyTreeMetrics = LazyTreeMetrics.defaults(),
icons: LazyTreeIcons = LazyTreeIcons.defaults(),
): LazyTreeStyle = LazyTreeStyle(colors, metrics, icons)
/** Creates an Int UI dark [LazyTreeStyle] with the provided parameters. */
public fun LazyTreeStyle.Companion.dark(
colors: SimpleListItemColors = SimpleListItemStyle.LazyTree.dark(),
metrics: LazyTreeMetrics = LazyTreeMetrics.defaults(),
icons: LazyTreeIcons = LazyTreeIcons.defaults(),
): LazyTreeStyle = LazyTreeStyle(colors, metrics, icons)
/** Creates an Int UI default [LazyTreeMetrics] with the provided parameters. */
public fun LazyTreeMetrics.Companion.defaults(
indentSize: Dp = 7.dp + 16.dp,
elementBackgroundCornerSize: CornerSize = CornerSize(2.dp),
@@ -97,6 +103,7 @@ public fun LazyTreeMetrics.Companion.defaults(
),
)
/** Creates an Int UI default [LazyTreeIcons] with the provided parameters. */
public fun LazyTreeIcons.Companion.defaults(
chevronCollapsed: IconKey = AllIconsKeys.General.ChevronRight,
chevronExpanded: IconKey = AllIconsKeys.General.ChevronDown,
@@ -15,6 +15,7 @@ import org.jetbrains.jewel.ui.component.styling.LinkUnderlineBehavior
import org.jetbrains.jewel.ui.icon.IconKey
import org.jetbrains.jewel.ui.icons.AllIconsKeys
/** Creates an Int UI light [LinkStyle] with the provided parameters. */
public fun LinkStyle.Companion.light(
colors: LinkColors = LinkColors.light(),
metrics: LinkMetrics = LinkMetrics.defaults(),
@@ -22,6 +23,7 @@ public fun LinkStyle.Companion.light(
underlineBehavior: LinkUnderlineBehavior = LinkUnderlineBehavior.ShowOnHover,
): LinkStyle = LinkStyle(colors, metrics, icons, underlineBehavior)
/** Creates an Int UI dark [LinkStyle] with the provided parameters. */
public fun LinkStyle.Companion.dark(
colors: LinkColors = LinkColors.dark(),
metrics: LinkMetrics = LinkMetrics.defaults(),
@@ -29,6 +31,7 @@ public fun LinkStyle.Companion.dark(
underlineBehavior: LinkUnderlineBehavior = LinkUnderlineBehavior.ShowOnHover,
): LinkStyle = LinkStyle(colors, metrics, icons, underlineBehavior)
/** Creates an Int UI light [LinkColors] with the provided parameters. */
public fun LinkColors.Companion.light(
content: Color = IntUiLightTheme.colors.blue(2),
contentDisabled: Color = IntUiLightTheme.colors.gray(8),
@@ -46,6 +49,7 @@ public fun LinkColors.Companion.light(
contentVisited = contentVisited,
)
/** Creates an Int UI dark [LinkColors] with the provided parameters. */
public fun LinkColors.Companion.dark(
content: Color = IntUiDarkTheme.colors.blue(9),
contentDisabled: Color = IntUiDarkTheme.colors.gray(7),
@@ -63,12 +67,14 @@ public fun LinkColors.Companion.dark(
contentVisited = contentVisited,
)
/** Creates an Int UI default [LinkMetrics] with the provided parameters. */
public fun LinkMetrics.Companion.defaults(
focusHaloCornerSize: CornerSize = CornerSize(2.dp),
textIconGap: Dp = 0.dp,
iconSize: DpSize = DpSize(16.dp, 16.dp),
): LinkMetrics = LinkMetrics(focusHaloCornerSize, textIconGap, iconSize)
/** Creates an Int UI default [LinkIcons] with the provided parameters. */
public fun LinkIcons.Companion.defaults(
dropdownChevron: IconKey = AllIconsKeys.General.ChevronDown,
externalLink: IconKey = AllIconsKeys.Ide.External_link_arrow,
@@ -18,18 +18,21 @@ import org.jetbrains.jewel.ui.component.styling.SubmenuMetrics
import org.jetbrains.jewel.ui.icon.IconKey
import org.jetbrains.jewel.ui.icons.AllIconsKeys
/** Creates an Int UI light [MenuStyle] with the provided parameters. */
public fun MenuStyle.Companion.light(
colors: MenuColors = MenuColors.light(),
metrics: MenuMetrics = MenuMetrics.defaults(),
icons: MenuIcons = MenuIcons.defaults(),
): MenuStyle = MenuStyle(isDark = false, colors, metrics, icons)
/** Creates an Int UI dark [MenuStyle] with the provided parameters. */
public fun MenuStyle.Companion.dark(
colors: MenuColors = MenuColors.dark(),
metrics: MenuMetrics = MenuMetrics.defaults(),
icons: MenuIcons = MenuIcons.defaults(),
): MenuStyle = MenuStyle(isDark = true, colors, metrics, icons)
/** Creates an Int UI light [MenuColors] with the provided parameters. */
public fun MenuColors.Companion.light(
background: Color = IntUiLightTheme.colors.gray(14),
border: Color = IntUiLightTheme.colors.gray(9),
@@ -37,6 +40,7 @@ public fun MenuColors.Companion.light(
itemColors: MenuItemColors = MenuItemColors.light(),
): MenuColors = MenuColors(background = background, border = border, shadow = shadow, itemColors = itemColors)
/** Creates an Int UI dark [MenuColors] with the provided parameters. */
public fun MenuColors.Companion.dark(
background: Color = IntUiDarkTheme.colors.gray(2),
border: Color = IntUiDarkTheme.colors.gray(3),
@@ -44,6 +48,7 @@ public fun MenuColors.Companion.dark(
itemColors: MenuItemColors = MenuItemColors.dark(),
): MenuColors = MenuColors(background = background, border = border, shadow = shadow, itemColors = itemColors)
/** Creates an Int UI light [MenuItemColors] with the provided parameters. */
public fun MenuItemColors.Companion.light(
background: Color = IntUiLightTheme.colors.gray(14),
backgroundDisabled: Color = IntUiLightTheme.colors.gray(14),
@@ -91,6 +96,7 @@ public fun MenuItemColors.Companion.light(
separator = separator,
)
/** Creates an Int UI dark [MenuItemColors] with the provided parameters. */
public fun MenuItemColors.Companion.dark(
background: Color = IntUiDarkTheme.colors.gray(2),
backgroundDisabled: Color = IntUiDarkTheme.colors.gray(2),
@@ -138,6 +144,7 @@ public fun MenuItemColors.Companion.dark(
keybindingTintHovered = keybindingTintHovered,
)
/** Creates an Int UI default [MenuMetrics] with the provided parameters. */
public fun MenuMetrics.Companion.defaults(
cornerSize: CornerSize = CornerSize(8.dp),
menuMargin: PaddingValues = PaddingValues(vertical = 6.dp),
@@ -150,6 +157,7 @@ public fun MenuMetrics.Companion.defaults(
): MenuMetrics =
MenuMetrics(cornerSize, menuMargin, contentPadding, offset, shadowSize, borderWidth, itemMetrics, submenuMetrics)
/** Creates an Int UI default [MenuItemMetrics] with the provided parameters. */
public fun MenuItemMetrics.Companion.defaults(
selectionCornerSize: CornerSize = CornerSize(4.dp),
outerPadding: PaddingValues = PaddingValues(horizontal = 6.dp),
@@ -173,8 +181,10 @@ public fun MenuItemMetrics.Companion.defaults(
minHeight,
)
/** Creates an Int UI default [SubmenuMetrics] with the provided parameters. */
public fun SubmenuMetrics.Companion.defaults(offset: DpOffset = DpOffset(0.dp, (-8).dp)): SubmenuMetrics =
SubmenuMetrics(offset)
/** Creates an Int UI default [MenuIcons] with the provided parameters. */
public fun MenuIcons.Companion.defaults(submenuChevron: IconKey = AllIconsKeys.General.ChevronRight): MenuIcons =
MenuIcons(submenuChevron)
@@ -10,28 +10,34 @@ import org.jetbrains.jewel.ui.component.styling.PopupAdColors
import org.jetbrains.jewel.ui.component.styling.PopupAdMetrics
import org.jetbrains.jewel.ui.component.styling.PopupAdStyle
/** Creates an Int UI light [PopupAdStyle] with the provided parameters. */
public fun PopupAdStyle.Companion.light(
colors: PopupAdColors = PopupAdColors.light(),
metrics: PopupAdMetrics = PopupAdMetrics.light(),
): PopupAdStyle = PopupAdStyle(colors = colors, metrics = metrics)
/** Creates an Int UI light [PopupAdColors] with the provided parameters. */
public fun PopupAdColors.Companion.light(background: Color = Color(0xFFF2F2F2)): PopupAdColors =
PopupAdColors(background = background)
/** Creates an Int UI light [PopupAdMetrics] with the provided parameters. */
public fun PopupAdMetrics.Companion.light(
padding: PaddingValues = PaddingValues(horizontal = 20.dp, vertical = 6.dp),
minHeight: Dp = 20.dp,
): PopupAdMetrics = PopupAdMetrics(padding = padding, minHeight = minHeight)
/** Creates an Int UI dark [PopupAdStyle] with the provided parameters. */
public fun PopupAdStyle.Companion.dark(
colors: PopupAdColors = PopupAdColors.dark(),
metrics: PopupAdMetrics = PopupAdMetrics.dark(),
): PopupAdStyle = PopupAdStyle(colors = colors, metrics = metrics)
/** Creates an Int UI dark [PopupAdColors] with the provided parameters. */
public fun PopupAdColors.Companion.dark(
background: Color = IntUiDarkTheme.colors.grayOrNull(2) ?: Color(0xFF2B2B2B)
): PopupAdColors = PopupAdColors(background = background)
/** Creates an Int UI dark [PopupAdMetrics] with the provided parameters. */
public fun PopupAdMetrics.Companion.dark(
padding: PaddingValues = PaddingValues(horizontal = 20.dp, vertical = 6.dp),
minHeight: Dp = 20.dp,
@@ -12,28 +12,33 @@ import org.jetbrains.jewel.ui.component.styling.PopupContainerColors
import org.jetbrains.jewel.ui.component.styling.PopupContainerMetrics
import org.jetbrains.jewel.ui.component.styling.PopupContainerStyle
/** Creates an Int UI light [PopupContainerStyle] with the provided parameters. */
public fun PopupContainerStyle.Companion.light(
colors: PopupContainerColors = PopupContainerColors.light(),
metrics: PopupContainerMetrics = PopupContainerMetrics.defaults(),
): PopupContainerStyle = PopupContainerStyle(isDark = false, colors, metrics)
/** Creates an Int UI dark [PopupContainerStyle] with the provided parameters. */
public fun PopupContainerStyle.Companion.dark(
colors: PopupContainerColors = PopupContainerColors.dark(),
metrics: PopupContainerMetrics = PopupContainerMetrics.defaults(),
): PopupContainerStyle = PopupContainerStyle(isDark = true, colors, metrics)
/** Creates an Int UI light [PopupContainerColors] with the provided parameters. */
public fun PopupContainerColors.Companion.light(
background: Color = IntUiLightTheme.colors.gray(14),
border: Color = IntUiLightTheme.colors.gray(9),
shadow: Color = Color(0x78919191), // Not a palette color
): PopupContainerColors = PopupContainerColors(background = background, border = border, shadow = shadow)
/** Creates an Int UI dark [PopupContainerColors] with the provided parameters. */
public fun PopupContainerColors.Companion.dark(
background: Color = IntUiDarkTheme.colors.gray(2),
border: Color = IntUiDarkTheme.colors.gray(3),
shadow: Color = Color(0x66000000), // Not a palette color
): PopupContainerColors = PopupContainerColors(background = background, border = border, shadow = shadow)
/** Creates an Int UI default [PopupContainerMetrics] with the provided parameters. */
public fun PopupContainerMetrics.Companion.defaults(
cornerSize: CornerSize = CornerSize(8.dp),
menuMargin: PaddingValues = PaddingValues(vertical = 6.dp),
@@ -13,18 +13,21 @@ import org.jetbrains.jewel.ui.component.styling.RadioButtonStyle
import org.jetbrains.jewel.ui.icon.IconKey
import org.jetbrains.jewel.ui.icon.PathIconKey
/** Creates an Int UI light [RadioButtonStyle] with the provided parameters. */
public fun RadioButtonStyle.Companion.light(
colors: RadioButtonColors = RadioButtonColors.light(),
metrics: RadioButtonMetrics = RadioButtonMetrics.defaults(),
icons: RadioButtonIcons = RadioButtonIcons.light(),
): RadioButtonStyle = RadioButtonStyle(colors, metrics, icons)
/** Creates an Int UI dark [RadioButtonStyle] with the provided parameters. */
public fun RadioButtonStyle.Companion.dark(
colors: RadioButtonColors = RadioButtonColors.dark(),
metrics: RadioButtonMetrics = RadioButtonMetrics.defaults(),
icons: RadioButtonIcons = RadioButtonIcons.dark(),
): RadioButtonStyle = RadioButtonStyle(colors, metrics, icons)
/** Creates an Int UI light [RadioButtonColors] with the provided parameters. */
public fun RadioButtonColors.Companion.light(
content: Color = Color.Unspecified,
contentHovered: Color = content,
@@ -42,6 +45,7 @@ public fun RadioButtonColors.Companion.light(
contentSelectedDisabled = contentSelectedDisabled,
)
/** Creates an Int UI dark [RadioButtonColors] with the provided parameters. */
public fun RadioButtonColors.Companion.dark(
content: Color = Color.Unspecified,
contentHovered: Color = content,
@@ -59,6 +63,7 @@ public fun RadioButtonColors.Companion.dark(
contentSelectedDisabled = contentSelectedDisabled,
)
/** Creates an Int UI default [RadioButtonMetrics] with the provided parameters. */
public fun RadioButtonMetrics.Companion.defaults(
radioButtonSize: DpSize = DpSize(24.dp, 24.dp),
outlineSize: DpSize = DpSize(17.dp, 17.dp),
@@ -76,11 +81,13 @@ public fun RadioButtonMetrics.Companion.defaults(
iconContentGap = iconContentGap,
)
/** Creates an Int UI light [RadioButtonIcons] with the provided parameters. */
public fun RadioButtonIcons.Companion.light(
radioButton: IconKey =
PathIconKey(path = "com/intellij/ide/ui/laf/icons/intellij/radio.svg", iconClass = RadioButtonIcons::class.java)
): RadioButtonIcons = RadioButtonIcons(radioButton)
/** Creates an Int UI dark [RadioButtonIcons] with the provided parameters. */
public fun RadioButtonIcons.Companion.dark(
radioButton: IconKey =
PathIconKey(path = "com/intellij/ide/ui/laf/icons/darcula/radio.svg", iconClass = RadioButtonIcons::class.java)
@@ -11,16 +11,19 @@ import org.jetbrains.jewel.ui.component.styling.SearchMatchColors
import org.jetbrains.jewel.ui.component.styling.SearchMatchMetrics
import org.jetbrains.jewel.ui.component.styling.SearchMatchStyle
/** Creates an Int UI light [SearchMatchStyle] with the provided parameters. */
public fun SearchMatchStyle.Companion.light(
colors: SearchMatchColors = SearchMatchColors.light(),
metrics: SearchMatchMetrics = SearchMatchMetrics.default(),
): SearchMatchStyle = SearchMatchStyle(colors, metrics)
/** Creates an Int UI dark [SearchMatchStyle] with the provided parameters. */
public fun SearchMatchStyle.Companion.dark(
colors: SearchMatchColors = SearchMatchColors.dark(),
metrics: SearchMatchMetrics = SearchMatchMetrics.default(),
): SearchMatchStyle = SearchMatchStyle(colors, metrics)
/** Creates an Int UI light [SearchMatchColors] with the provided parameters. */
public fun SearchMatchColors.Companion.light(
startBackground: Color = IntUiLightTheme.colors.yellow(7),
endBackground: Color = IntUiLightTheme.colors.yellow(7),
@@ -28,6 +31,7 @@ public fun SearchMatchColors.Companion.light(
): SearchMatchColors =
SearchMatchColors(startBackground = startBackground, endBackground = endBackground, foreground = foreground)
/** Creates an Int UI dark [SearchMatchColors] with the provided parameters. */
public fun SearchMatchColors.Companion.dark(
startBackground: Color = IntUiDarkTheme.colors.yellow(5),
endBackground: Color = IntUiDarkTheme.colors.yellow(5),
@@ -35,6 +39,7 @@ public fun SearchMatchColors.Companion.dark(
): SearchMatchColors =
SearchMatchColors(startBackground = startBackground, endBackground = endBackground, foreground = foreground)
/** Creates an Int UI default [SearchMatchMetrics] with the provided parameters. */
public fun SearchMatchMetrics.Companion.default(
cornerSize: CornerSize = CornerSize(2.5.dp),
padding: PaddingValues = PaddingValues(2.dp),
@@ -14,16 +14,19 @@ import org.jetbrains.jewel.ui.component.styling.SegmentedControlButtonColors
import org.jetbrains.jewel.ui.component.styling.SegmentedControlButtonMetrics
import org.jetbrains.jewel.ui.component.styling.SegmentedControlButtonStyle
/** Creates an Int UI light [SegmentedControlButtonStyle] with the provided parameters. */
public fun SegmentedControlButtonStyle.Companion.light(
colors: SegmentedControlButtonColors = SegmentedControlButtonColors.light(),
metrics: SegmentedControlButtonMetrics = SegmentedControlButtonMetrics.defaults(),
): SegmentedControlButtonStyle = SegmentedControlButtonStyle(colors, metrics)
/** Creates an Int UI dark [SegmentedControlButtonStyle] with the provided parameters. */
public fun SegmentedControlButtonStyle.Companion.dark(
colors: SegmentedControlButtonColors = SegmentedControlButtonColors.dark(),
metrics: SegmentedControlButtonMetrics = SegmentedControlButtonMetrics.defaults(),
): SegmentedControlButtonStyle = SegmentedControlButtonStyle(colors, metrics)
/** Creates an Int UI light [SegmentedControlButtonColors] with the provided parameters. */
public fun SegmentedControlButtonColors.Companion.light(
background: Brush = SolidColor(Color.Transparent),
backgroundPressed: Brush = SolidColor(IntUiLightTheme.colors.gray(14)),
@@ -51,6 +54,7 @@ public fun SegmentedControlButtonColors.Companion.light(
borderSelectedFocused = borderSelectedFocused,
)
/** Creates an Int UI dark [SegmentedControlButtonColors] with the provided parameters. */
public fun SegmentedControlButtonColors.Companion.dark(
background: Brush = SolidColor(Color.Transparent),
backgroundPressed: Brush = SolidColor(IntUiDarkTheme.colors.gray(3)),
@@ -78,6 +82,7 @@ public fun SegmentedControlButtonColors.Companion.dark(
borderSelectedFocused = borderSelectedFocused,
)
/** Creates an Int UI default [SegmentedControlButtonMetrics] with the provided parameters. */
public fun SegmentedControlButtonMetrics.Companion.defaults(
cornerSize: CornerSize = CornerSize(3.dp),
segmentedButtonPadding: PaddingValues = PaddingValues(horizontal = 12.dp, vertical = 6.dp),
@@ -12,16 +12,19 @@ import org.jetbrains.jewel.ui.component.styling.SegmentedControlColors
import org.jetbrains.jewel.ui.component.styling.SegmentedControlMetrics
import org.jetbrains.jewel.ui.component.styling.SegmentedControlStyle
/** Creates an Int UI light [SegmentedControlStyle] with the provided parameters. */
public fun SegmentedControlStyle.Companion.light(
colors: SegmentedControlColors = SegmentedControlColors.light(),
metrics: SegmentedControlMetrics = SegmentedControlMetrics.defaults(),
): SegmentedControlStyle = SegmentedControlStyle(colors, metrics)
/** Creates an Int UI dark [SegmentedControlStyle] with the provided parameters. */
public fun SegmentedControlStyle.Companion.dark(
colors: SegmentedControlColors = SegmentedControlColors.dark(),
metrics: SegmentedControlMetrics = SegmentedControlMetrics.defaults(),
): SegmentedControlStyle = SegmentedControlStyle(colors, metrics)
/** Creates an Int UI light [SegmentedControlColors] with the provided parameters. */
public fun SegmentedControlColors.Companion.light(
border: Brush = SolidColor(IntUiLightTheme.colors.gray(9)),
borderDisabled: Brush = SolidColor(IntUiLightTheme.colors.gray(11)),
@@ -37,6 +40,7 @@ public fun SegmentedControlColors.Companion.light(
borderFocused = borderFocused,
)
/** Creates an Int UI dark [SegmentedControlColors] with the provided parameters. */
public fun SegmentedControlColors.Companion.dark(
border: Brush = SolidColor(IntUiDarkTheme.colors.gray(5)),
borderDisabled: Brush = SolidColor(IntUiDarkTheme.colors.gray(4)),
@@ -52,6 +56,7 @@ public fun SegmentedControlColors.Companion.dark(
borderFocused = borderFocused,
)
/** Creates an Int UI default [SegmentedControlMetrics] with the provided parameters. */
public fun SegmentedControlMetrics.Companion.defaults(
cornerSize: CornerSize = CornerSize(3.dp),
borderWidth: Dp = 1.dp,

Some files were not shown because too many files have changed in this diff Show More