From 580830798d0d629fea439370d319c7fc8ebbfe33 Mon Sep 17 00:00:00 2001 From: Sebastiano Poggi Date: Wed, 1 Nov 2023 20:09:53 +0100 Subject: [PATCH] Manually cleanup everything Never trust ktfmt, kids. It's weird. --- build.gradle.kts | 4 +- buildSrc/build.gradle.kts | 6 +- buildSrc/settings.gradle.kts | 7 +- buildSrc/src/main/kotlin/IdeaConfiguration.kt | 30 +- ...droid-studio-releases-generator.gradle.kts | 13 +- .../intellij-theme-generator.gradle.kts | 14 +- .../main/kotlin/jewel-ij-publish.gradle.kts | 21 +- .../src/main/kotlin/jewel-publish.gradle.kts | 6 +- buildSrc/src/main/kotlin/jewel.gradle.kts | 14 +- .../theme/IntUiThemeDescriptorReader.kt | 13 +- .../jetbrains/jewel/window/DecoratedWindow.kt | 107 +++---- .../jetbrains/jewel/window/TitleBar.MacOS.kt | 51 ++- .../jewel/window/TitleBar.Windows.kt | 12 +- .../org/jetbrains/jewel/window/TitleBar.kt | 83 ++--- .../jewel/window/utils/UnsafeAccessing.kt | 16 +- .../jewel/window/utils/macos/Foundation.kt | 31 +- .../window/utils/macos/FoundationLibrary.kt | 98 ++---- .../jetbrains/jewel/window/utils/macos/ID.kt | 13 +- .../jewel/window/utils/macos/MacUtil.kt | 17 +- .../jewel/foundation/ExperimentalJewelApi.kt | 14 +- .../jewel/foundation/GenerateDataFunctions.kt | 7 +- .../jewel/foundation/InternalJewelApi.kt | 12 +- .../jewel/foundation/RoundRectUtil.kt | 24 +- .../org/jetbrains/jewel/foundation/Stroke.kt | 6 +- .../jewel/foundation/lazy/Keybindings.kt | 48 ++- .../lazy/SelectableColumnOnKeyEvent.kt | 86 +++-- .../foundation/lazy/SelectableLazyColumn.kt | 11 +- .../lazy/SelectableLazyListScope.kt | 16 +- .../lazy/SelectableLazyListState.kt | 37 +-- .../foundation/lazy/tree/BasicLazyTree.kt | 78 +++-- .../jewel/foundation/lazy/tree/BuildTree.kt | 103 +++--- .../lazy/tree/DefaultTreeViewKeybindings.kt | 12 +- .../lazy/tree/DefaultTreeViewOnKeyEvent.kt | 3 +- .../jewel/foundation/lazy/tree/KeyActions.kt | 7 + .../lazy/tree/TreeViewOnKeyEvent.kt | 8 +- .../jewel/foundation/modifier/Activation.kt | 4 +- .../jewel/foundation/modifier/Border.kt | 301 ++++++++---------- .../jewel/foundation/theme/JewelTheme.kt | 18 +- ide-laf-bridge/build.gradle.kts | 5 +- .../jetbrains/jewel/bridge/BridgeIconData.kt | 4 +- .../bridge/BridgePainterHintsProvider.kt | 19 +- .../jewel/bridge/UiThemeExtensions.kt | 10 +- .../jetbrains/jewel/bridge/BridgeOverride.kt | 10 +- .../bridge/BridgePainterHintsProvider.kt | 19 +- .../org/jetbrains/jewel/bridge/Bridge.kt | 4 +- .../jewel/bridge/BridgeResourceResolver.kt | 11 +- .../org/jetbrains/jewel/bridge/BridgeUtils.kt | 59 ++-- .../jewel/bridge/JewelBridgeException.kt | 7 +- .../actionSystem/DataProviderElement.kt | 5 +- .../bridge/actionSystem/DataProviderNode.kt | 10 +- .../jewel/bridge/actionSystem/ProvideData.kt | 23 +- .../bridge/actionSystem/ProvideDataTest.kt | 8 +- .../IntUiDecoratedWindowResourceResolver.kt | 10 +- .../window/styling/IntUiTitleBarStyling.kt | 51 +-- .../StandalonePainterHintsProvider.kt | 13 +- .../standalone/styling/IntUiButtonStyling.kt | 12 +- .../styling/IntUiCheckboxStyling.kt | 24 +- .../standalone/styling/IntUiChipStyling.kt | 3 +- .../styling/IntUiCircularProgressStyling.kt | 6 +- .../standalone/styling/IntUiDividerStyle.kt | 6 +- .../styling/IntUiDropdownStyling.kt | 21 +- .../styling/IntUiGroupHeaderStyling.kt | 15 +- .../styling/IntUiIconButtonStyling.kt | 9 +- .../styling/IntUiLazyTreeStyling.kt | 6 +- .../standalone/styling/IntUiLinkStyling.kt | 18 +- .../standalone/styling/IntUiMenuStyling.kt | 20 +- .../styling/IntUiRadioButtonStyling.kt | 15 +- .../styling/IntUiScrollbarStyling.kt | 12 +- .../standalone/styling/IntUiTabStyling.kt | 18 +- .../styling/IntUiTextAreaStyling.kt | 9 +- .../styling/IntUiTextFieldStyling.kt | 9 +- .../standalone/styling/IntUiTooltipStyling.kt | 6 +- .../standalone/theme/IntUiGlobalColors.kt | 12 +- .../standalone/theme/IntUiGlobalMetrics.kt | 3 +- .../intui/standalone/theme/IntUiTheme.kt | 29 +- ui/api/ui.api | 20 +- .../jetbrains/jewel/ui/component/Button.kt | 9 +- .../jetbrains/jewel/ui/component/Checkbox.kt | 54 ++-- .../org/jetbrains/jewel/ui/component/Chip.kt | 43 +-- .../ui/component/CircularProgressIndicator.kt | 64 ++-- .../jetbrains/jewel/ui/component/Divider.kt | 6 +- .../jetbrains/jewel/ui/component/Dropdown.kt | 38 +-- .../jewel/ui/component/GroupHeader.kt | 1 + .../org/jetbrains/jewel/ui/component/Icon.kt | 72 +++-- .../jewel/ui/component/IconButton.kt | 52 ++- .../jewel/ui/component/InputField.kt | 44 +-- .../jetbrains/jewel/ui/component/LazyTree.kt | 21 +- .../jewel/ui/component/LinearProgressBar.kt | 46 ++- .../org/jetbrains/jewel/ui/component/Link.kt | 15 +- .../org/jetbrains/jewel/ui/component/Menu.kt | 97 +++--- .../jewel/ui/component/MenuManager.kt | 8 +- .../org/jetbrains/jewel/ui/component/Popup.kt | 76 +++-- .../jewel/ui/component/RadioButton.kt | 39 +-- .../jewel/ui/component/Scrollbars.kt | 61 ++-- .../jewel/ui/component/SplitLayout.kt | 87 ++--- .../jetbrains/jewel/ui/component/TabStrip.kt | 96 +----- .../org/jetbrains/jewel/ui/component/Tabs.kt | 36 +-- .../org/jetbrains/jewel/ui/component/Text.kt | 1 + .../jetbrains/jewel/ui/component/TextArea.kt | 81 ++--- .../jetbrains/jewel/ui/component/TextField.kt | 71 ++--- .../jetbrains/jewel/ui/component/Tooltip.kt | 49 ++- .../jewel/ui/painter/BadgePainter.kt | 12 +- .../jetbrains/jewel/ui/painter/PainterHint.kt | 54 ++-- .../jewel/ui/painter/PainterHintsProvider.kt | 15 +- .../jewel/ui/painter/PainterProvider.kt | 20 +- .../jewel/ui/painter/ResizedPainter.kt | 2 +- .../ui/painter/ResourcePainterProvider.kt | 13 +- .../jewel/ui/painter/badge/BadgeShape.kt | 8 +- .../jewel/ui/painter/badge/DotBadgeShape.kt | 6 +- .../jetbrains/jewel/ui/painter/hints/Badge.kt | 32 +- .../jewel/ui/painter/hints/DarkOrStroke.kt | 27 +- .../jewel/ui/painter/hints/Override.kt | 17 +- .../jewel/ui/painter/hints/Palette.kt | 71 ++--- .../jewel/ui/painter/hints/Selected.kt | 6 +- .../jetbrains/jewel/ui/painter/hints/Size.kt | 20 +- .../jewel/ui/painter/hints/Stateful.kt | 15 +- .../jewel/ui/util/ColorExtensions.kt | 16 +- .../org/jetbrains/jewel/ui/util/Debug.kt | 4 +- .../jewel/ui/util/ModifierExtensions.kt | 13 +- .../ui/util/SpinnerProgressIconGenerator.kt | 107 ------- .../org/jetbrains/jewel/BasicJewelUiTest.kt | 3 +- 121 files changed, 1519 insertions(+), 2001 deletions(-) delete mode 100644 ui/src/main/kotlin/org/jetbrains/jewel/ui/util/SpinnerProgressIconGenerator.kt diff --git a/build.gradle.kts b/build.gradle.kts index de3d33c176..d60312b3a5 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -17,10 +17,10 @@ dependencies { } tasks { - val mergeSarifReports by - registering(MergeSarifTask::class) { + val mergeSarifReports by registering(MergeSarifTask::class) { source(configurations.outgoingSarif) include { it.file.extension == "sarif" } } + register("check") { dependsOn(mergeSarifReports) } } diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 3e202f8bbb..68751fe39f 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -5,7 +5,11 @@ plugins { kotlin { sourceSets { - all { languageSettings { optIn("kotlinx.serialization.ExperimentalSerializationApi") } } + all { + languageSettings { + optIn("kotlinx.serialization.ExperimentalSerializationApi") + } + } } } diff --git a/buildSrc/settings.gradle.kts b/buildSrc/settings.gradle.kts index a14349429a..f8d784c5ba 100644 --- a/buildSrc/settings.gradle.kts +++ b/buildSrc/settings.gradle.kts @@ -10,5 +10,10 @@ dependencyResolutionManagement { gradlePluginPortal() mavenCentral() } - versionCatalogs { create("libs") { from(files("../gradle/libs.versions.toml")) } } + + versionCatalogs { + create("libs") { + from(files("../gradle/libs.versions.toml")) + } + } } diff --git a/buildSrc/src/main/kotlin/IdeaConfiguration.kt b/buildSrc/src/main/kotlin/IdeaConfiguration.kt index 6236618bae..abc014a0df 100644 --- a/buildSrc/src/main/kotlin/IdeaConfiguration.kt +++ b/buildSrc/src/main/kotlin/IdeaConfiguration.kt @@ -11,21 +11,18 @@ enum class SupportedIJVersion { private var warned = AtomicBoolean(false) fun Project.supportedIJVersion(): SupportedIJVersion { - val prop = - kotlin - .runCatching { - rootProject.findProperty("supported.ij.version")?.toString() - ?: localProperty("supported.ij.version") - } - .getOrNull() + val prop = kotlin.runCatching { + rootProject.findProperty("supported.ij.version")?.toString() + ?: localProperty("supported.ij.version") + }.getOrNull() if (prop == null) { if (!warned.getAndSet(true)) { logger.warn( """ - No 'supported.ij.version' property provided. Falling back to IJ 233. - It is recommended to provide it using local.properties file or -Psupported.ij.version to - avoid unexpected behavior. + No 'supported.ij.version' property provided. Falling back to IJ 233. + It is recommended to provide it using the local.properties file or + -Psupported.ij.version to avoid unexpected behavior. """.trimIndent() ) } @@ -35,12 +32,13 @@ fun Project.supportedIJVersion(): SupportedIJVersion { return when (prop) { "232" -> SupportedIJVersion.IJ_232 "233" -> SupportedIJVersion.IJ_233 - else -> - error( - "Invalid 'supported.ij.version' with value '$prop' is provided. " + - "It should be one of these values: ('232', '233')" - ) + else -> error( + "Invalid 'supported.ij.version' with value '$prop' is provided. " + + "It should be one of these values: ('232', '233')" + ) } } -fun Property.assign(version: Int) = set(JavaLanguageVersion.of(version)) +@Suppress("unused") // Used to set the Java toolchain version +fun Property.assign(version: Int) = + set(JavaLanguageVersion.of(version)) diff --git a/buildSrc/src/main/kotlin/android-studio-releases-generator.gradle.kts b/buildSrc/src/main/kotlin/android-studio-releases-generator.gradle.kts index ca9c1806bb..353c57a70d 100644 --- a/buildSrc/src/main/kotlin/android-studio-releases-generator.gradle.kts +++ b/buildSrc/src/main/kotlin/android-studio-releases-generator.gradle.kts @@ -10,25 +10,20 @@ import org.jetbrains.kotlin.gradle.tasks.BaseKotlinCompile val extension: StudioVersionsGenerationExtension = extensions.findByType() - ?: extensions.create( - "androidStudioReleasesGenerator", - StudioVersionsGenerationExtension::class.java - ) + ?: extensions.create("androidStudioReleasesGenerator", StudioVersionsGenerationExtension::class.java) val task = tasks.register("generateAndroidStudioReleasesList") { val className = ClassName.bestGuess(STUDIO_RELEASES_OUTPUT_CLASS_NAME) - outputFile = - extension.targetDir.file( - className.packageName.replace(".", "/").plus("/${className.simpleName}.kt") - ) + val filePath = className.packageName.replace(".", "/") + + "/${className.simpleName}.kt" + outputFile = extension.targetDir.file(filePath) dataUrl = extension.dataUrl resourcesDirs = extension.resourcesDirs } tasks { withType { dependsOn(task) } - withType { dependsOn(task) } } diff --git a/buildSrc/src/main/kotlin/intellij-theme-generator.gradle.kts b/buildSrc/src/main/kotlin/intellij-theme-generator.gradle.kts index 593b7b6726..dca065e939 100644 --- a/buildSrc/src/main/kotlin/intellij-theme-generator.gradle.kts +++ b/buildSrc/src/main/kotlin/intellij-theme-generator.gradle.kts @@ -16,13 +16,12 @@ extensions.add("intelliJThemeGenerator", extension) extension.all { val task = tasks.register("generate${GUtil.toCamelCase(name)}Theme") { - outputFile = - targetDir.file( - this@all.themeClassName.map { - val className = ClassName.bestGuess(it) - className.packageName.replace(".", "/").plus("/${className.simpleName}.kt") - } - ) + val paths = this@all.themeClassName.map { + val className = ClassName.bestGuess(it) + className.packageName.replace(".", "/") + "/${className.simpleName}.kt" + } + + outputFile = targetDir.file(paths) themeClassName = this@all.themeClassName ideaVersion = this@all.ideaVersion themeFile = this@all.themeFile @@ -30,7 +29,6 @@ extension.all { tasks { withType { dependsOn(task) } - withType { dependsOn(task) } } diff --git a/buildSrc/src/main/kotlin/jewel-ij-publish.gradle.kts b/buildSrc/src/main/kotlin/jewel-ij-publish.gradle.kts index 1d325cf1d2..14cc1bbd3e 100644 --- a/buildSrc/src/main/kotlin/jewel-ij-publish.gradle.kts +++ b/buildSrc/src/main/kotlin/jewel-ij-publish.gradle.kts @@ -9,15 +9,13 @@ plugins { id("org.jetbrains.dokka") } -val sourcesJar by -tasks.registering(Jar::class) { +val sourcesJar by tasks.registering(Jar::class) { from(kotlin.sourceSets.main.map { it.kotlin }) archiveClassifier = "sources" destinationDirectory = layout.buildDirectory.dir("artifacts") } -val javadocJar by -tasks.registering(Jar::class) { +val javadocJar by tasks.registering(Jar::class) { from(tasks.dokkaHtml) archiveClassifier = "javadoc" destinationDirectory = layout.buildDirectory.dir("artifacts") @@ -31,11 +29,10 @@ publishing { from(components["kotlin"]) artifact(javadocJar) artifact(sourcesJar) - val ijVersionRaw = - when (supportedIJVersion()) { - IJ_232 -> "232" - IJ_233 -> "233" - } + val ijVersionRaw = when (supportedIJVersion()) { + IJ_232 -> "232" + IJ_233 -> "233" + } version = project.version.toString().withVersionSuffix("ij-$ijVersionRaw") artifactId = "jewel-${project.name}" pom { configureJewelPom() } @@ -47,16 +44,14 @@ publishing { * Adds suffix to the version taking SNAPSHOT suffix into account * * For example, if [this] is "0.0.1-SNAPSHOT" and [suffix] is "ij-233" then - * result will be "0.0.1-ij-233-SNAPSHOT" + * the result will be "0.0.1-ij-233-SNAPSHOT" */ fun String.withVersionSuffix(suffix: String): String { val splitString = this.split('-') val snapshotRaw = "SNAPSHOT" val withSnapshot = splitString.contains(snapshotRaw) - if (!withSnapshot) { - return "$this-$suffix" - } + if (!withSnapshot) return "$this-$suffix" val withoutSnapshot = splitString.filter { it != snapshotRaw }.joinToString("-") diff --git a/buildSrc/src/main/kotlin/jewel-publish.gradle.kts b/buildSrc/src/main/kotlin/jewel-publish.gradle.kts index 62824d862d..af41e53d44 100644 --- a/buildSrc/src/main/kotlin/jewel-publish.gradle.kts +++ b/buildSrc/src/main/kotlin/jewel-publish.gradle.kts @@ -6,15 +6,13 @@ plugins { id("org.jetbrains.dokka") } -val sourcesJar by -tasks.registering(Jar::class) { +val sourcesJar by tasks.registering(Jar::class) { from(kotlin.sourceSets.main.map { it.kotlin }) archiveClassifier = "sources" destinationDirectory = layout.buildDirectory.dir("artifacts") } -val javadocJar by -tasks.registering(Jar::class) { +val javadocJar by tasks.registering(Jar::class) { from(tasks.dokkaHtml) archiveClassifier = "javadoc" destinationDirectory = layout.buildDirectory.dir("artifacts") diff --git a/buildSrc/src/main/kotlin/jewel.gradle.kts b/buildSrc/src/main/kotlin/jewel.gradle.kts index cea2157c03..049bedff22 100644 --- a/buildSrc/src/main/kotlin/jewel.gradle.kts +++ b/buildSrc/src/main/kotlin/jewel.gradle.kts @@ -7,15 +7,15 @@ group = "org.jetbrains.jewel" val gitHubRef: String? = System.getenv("GITHUB_REF") -version = - when { - gitHubRef?.startsWith("refs/tags/") == true -> { - gitHubRef.substringAfter("refs/tags/").removePrefix("v") - } - - else -> "1.0.0-SNAPSHOT" +version = when { + gitHubRef?.startsWith("refs/tags/") == true -> { + gitHubRef.substringAfter("refs/tags/") + .removePrefix("v") } + else -> "1.0.0-SNAPSHOT" +} + java { toolchain { vendor = JvmVendorSpec.JETBRAINS diff --git a/buildSrc/src/main/kotlin/org/jetbrains/jewel/buildlogic/theme/IntUiThemeDescriptorReader.kt b/buildSrc/src/main/kotlin/org/jetbrains/jewel/buildlogic/theme/IntUiThemeDescriptorReader.kt index 62bdeb96f5..629d691342 100644 --- a/buildSrc/src/main/kotlin/org/jetbrains/jewel/buildlogic/theme/IntUiThemeDescriptorReader.kt +++ b/buildSrc/src/main/kotlin/org/jetbrains/jewel/buildlogic/theme/IntUiThemeDescriptorReader.kt @@ -84,13 +84,12 @@ internal object IntUiThemeDescriptorReader { ) } - val rawMap = - colors - .map { (key, value) -> - val colorHexString = value.replace("#", "0xFF") - CodeBlock.of("%S to Color(%L)", key, colorHexString) - } - .joinToCode(prefix = "\nrawMap = mapOf(\n", separator = ",\n", suffix = "\n)") + val rawMap = colors + .map { (key, value) -> + val colorHexString = value.replace("#", "0xFF") + CodeBlock.of("%S to Color(%L)", key, colorHexString) + } + .joinToCode(prefix = "\nrawMap = mapOf(\n", separator = ",\n", suffix = "\n)") addProperty( PropertySpec.builder("colors", colorPaletteClassName, KModifier.OVERRIDE) diff --git a/decorated-window/src/main/kotlin/org/jetbrains/jewel/window/DecoratedWindow.kt b/decorated-window/src/main/kotlin/org/jetbrains/jewel/window/DecoratedWindow.kt index ba525c1ec2..32c0ba4224 100644 --- a/decorated-window/src/main/kotlin/org/jetbrains/jewel/window/DecoratedWindow.kt +++ b/decorated-window/src/main/kotlin/org/jetbrains/jewel/window/DecoratedWindow.kt @@ -5,6 +5,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.Immutable +import androidx.compose.runtime.ProvidableCompositionLocal import androidx.compose.runtime.Stable import androidx.compose.runtime.compositionLocalOf import androidx.compose.runtime.getValue @@ -61,7 +62,7 @@ public fun DecoratedWindow( remember { if (!JBR.isAvailable()) { error( - "DecoratedWindow only can be used on JetBrainsRuntime(JBR) platform, " + + "DecoratedWindow can only be used on JetBrainsRuntime(JBR) platform, " + "please check the document https://github.com/JetBrains/jewel#int-ui-standalone-theme", ) } @@ -77,7 +78,7 @@ public fun DecoratedWindow( title, icon, undecorated, - false, + transparent = false, resizable, enabled, focusable, @@ -88,47 +89,48 @@ public fun DecoratedWindow( var decoratedWindowState by remember { mutableStateOf(DecoratedWindowState.of(window)) } DisposableEffect(window) { - val adapter = - object : WindowAdapter(), ComponentListener { - override fun windowActivated(e: WindowEvent?) { - decoratedWindowState = DecoratedWindowState.of(window) - } + val adapter = object : WindowAdapter(), ComponentListener { + override fun windowActivated(e: WindowEvent?) { + decoratedWindowState = DecoratedWindowState.of(window) + } - override fun windowDeactivated(e: WindowEvent?) { - decoratedWindowState = DecoratedWindowState.of(window) - } + override fun windowDeactivated(e: WindowEvent?) { + decoratedWindowState = DecoratedWindowState.of(window) + } - override fun windowIconified(e: WindowEvent?) { - decoratedWindowState = DecoratedWindowState.of(window) - } + override fun windowIconified(e: WindowEvent?) { + decoratedWindowState = DecoratedWindowState.of(window) + } - override fun windowDeiconified(e: WindowEvent?) { - decoratedWindowState = DecoratedWindowState.of(window) - } + override fun windowDeiconified(e: WindowEvent?) { + decoratedWindowState = DecoratedWindowState.of(window) + } - override fun windowStateChanged(e: WindowEvent) { - decoratedWindowState = DecoratedWindowState.of(window) - } + override fun windowStateChanged(e: WindowEvent) { + decoratedWindowState = DecoratedWindowState.of(window) + } - override fun componentResized(e: ComponentEvent?) { - decoratedWindowState = DecoratedWindowState.of(window) - } + override fun componentResized(e: ComponentEvent?) { + decoratedWindowState = DecoratedWindowState.of(window) + } - override fun componentMoved(e: ComponentEvent?) { - // Empty - } + override fun componentMoved(e: ComponentEvent?) { + // Empty + } - override fun componentShown(e: ComponentEvent?) { - // Empty - } + override fun componentShown(e: ComponentEvent?) { + // Empty + } - override fun componentHidden(e: ComponentEvent?) { - // Empty - } + override fun componentHidden(e: ComponentEvent?) { + // Empty } + } + window.addWindowListener(adapter) window.addWindowStateListener(adapter) window.addComponentListener(adapter) + onDispose { window.removeWindowListener(adapter) window.removeWindowStateListener(adapter) @@ -143,8 +145,7 @@ public fun DecoratedWindow( style.metrics.borderWidth, style.colors.borderFor(decoratedWindowState).value, RectangleShape, - ) - .padding(style.metrics.borderWidth) + ).padding(style.metrics.borderWidth) } else { Modifier } @@ -153,15 +154,14 @@ public fun DecoratedWindow( LocalTitleBarInfo provides TitleBarInfo(title, icon), ) { Layout( - { - val scope = - object : DecoratedWindowScope { - override val state: DecoratedWindowState - get() = decoratedWindowState - - override val window: ComposeWindow - get() = this@Window.window - } + content = { + val scope = object : DecoratedWindowScope { + override val state: DecoratedWindowState + get() = decoratedWindowState + + override val window: ComposeWindow + get() = this@Window.window + } scope.content() }, modifier = undecoratedWindowBorder.trackWindowActivation(window), @@ -181,15 +181,9 @@ public interface DecoratedWindowScope : FrameWindowScope { private object DecoratedWindowMeasurePolicy : MeasurePolicy { - override fun MeasureScope.measure( - measurables: List, - constraints: Constraints, - ): MeasureResult { + override fun MeasureScope.measure(measurables: List, constraints: Constraints): MeasureResult { if (measurables.isEmpty()) { - return layout( - constraints.minWidth, - constraints.minHeight, - ) {} + return layout(width = constraints.minWidth, height = constraints.minHeight) {} } val titleBars = measurables.filter { it.layoutId == TITLE_BAR_LAYOUT_ID } @@ -287,14 +281,9 @@ public value class DecoratedWindowState(public val state: ULong) { } } -internal data class TitleBarInfo( - val title: String, - val icon: Painter?, -) +internal data class TitleBarInfo(val title: String, val icon: Painter?) -internal val LocalTitleBarInfo = - compositionLocalOf { - error( - "CompositionLocal LocalTitleBarInfo not provided, TitleBar must be used in DecoratedWindow", - ) +internal val LocalTitleBarInfo: ProvidableCompositionLocal = + compositionLocalOf { + error("CompositionLocal LocalTitleBarInfo not provided, TitleBar must be used in DecoratedWindow") } diff --git a/decorated-window/src/main/kotlin/org/jetbrains/jewel/window/TitleBar.MacOS.kt b/decorated-window/src/main/kotlin/org/jetbrains/jewel/window/TitleBar.MacOS.kt index c51e9b43d5..63475e2d14 100644 --- a/decorated-window/src/main/kotlin/org/jetbrains/jewel/window/TitleBar.MacOS.kt +++ b/decorated-window/src/main/kotlin/org/jetbrains/jewel/window/TitleBar.MacOS.kt @@ -15,29 +15,27 @@ import org.jetbrains.jewel.foundation.theme.JewelTheme import org.jetbrains.jewel.window.styling.TitleBarStyle import org.jetbrains.jewel.window.utils.macos.MacUtil -public fun Modifier.newFullscreenControls(newControls: Boolean = true): Modifier { - return then( - NewFullscreenControlsElement( - newControls, - inspectorInfo = - debugInspectorInfo { - name = "newFullscreenControls" - value = newControls - }, - ), +public fun Modifier.newFullscreenControls(newControls: Boolean = true): Modifier = + this then NewFullscreenControlsElement( + newControls, + debugInspectorInfo { + name = "newFullscreenControls" + value = newControls + }, ) -} private class NewFullscreenControlsElement( val newControls: Boolean, val inspectorInfo: InspectorInfo.() -> Unit, ) : ModifierNodeElement() { - override fun create(): NewFullscreenControlsNode = NewFullscreenControlsNode(newControls) + override fun create(): NewFullscreenControlsNode = + NewFullscreenControlsNode(newControls) override fun equals(other: Any?): Boolean { if (this === other) return true - val otherModifier = other as? NewFullscreenControlsElement ?: return false + val otherModifier = other as? NewFullscreenControlsElement + ?: return false return newControls == otherModifier.newControls } @@ -52,9 +50,7 @@ private class NewFullscreenControlsElement( } } -private class NewFullscreenControlsNode( - var newControls: Boolean, -) : Modifier.Node() +private class NewFullscreenControlsNode(var newControls: Boolean) : Modifier.Node() @Composable internal fun DecoratedWindowScope.TitleBarOnMacOs( @@ -63,14 +59,13 @@ internal fun DecoratedWindowScope.TitleBarOnMacOs( style: TitleBarStyle = JewelTheme.defaultTitleBarStyle, content: @Composable TitleBarScope.(DecoratedWindowState) -> Unit, ) { - val newFullscreenControls = - modifier.foldOut(false) { e, r -> - if (e is NewFullscreenControlsElement) { - e.newControls - } else { - r - } + val newFullscreenControls = modifier.foldOut(false) { e, r -> + if (e is NewFullscreenControlsElement) { + e.newControls + } else { + r } + } if (newFullscreenControls) { System.setProperty("apple.awt.newFullScreeControls", true.toString()) @@ -87,10 +82,10 @@ internal fun DecoratedWindowScope.TitleBarOnMacOs( val titleBar = remember { JBR.getWindowDecorations().createCustomTitleBar() } TitleBarImpl( - modifier.customTitleBarMouseEventHandler(titleBar), - gradientStartColor, - style, - { height, state -> + modifier = modifier.customTitleBarMouseEventHandler(titleBar), + gradientStartColor = gradientStartColor, + style = style, + applyTitleBar = { height, state -> if (state.isFullscreen) { MacUtil.updateFullScreenButtons(window) } @@ -103,6 +98,6 @@ internal fun DecoratedWindowScope.TitleBarOnMacOs( PaddingValues(start = titleBar.leftInset.dp, end = titleBar.rightInset.dp) } }, - content, + content = content, ) } diff --git a/decorated-window/src/main/kotlin/org/jetbrains/jewel/window/TitleBar.Windows.kt b/decorated-window/src/main/kotlin/org/jetbrains/jewel/window/TitleBar.Windows.kt index 531ed86486..e342f36bae 100644 --- a/decorated-window/src/main/kotlin/org/jetbrains/jewel/window/TitleBar.Windows.kt +++ b/decorated-window/src/main/kotlin/org/jetbrains/jewel/window/TitleBar.Windows.kt @@ -27,21 +27,21 @@ internal fun DecoratedWindowScope.TitleBarOnWindows( val titleBar = remember { JBR.getWindowDecorations().createCustomTitleBar() } TitleBarImpl( - modifier.customTitleBarMouseEventHandler(titleBar), - gradientStartColor, - style, - { height, _ -> + modifier = modifier.customTitleBarMouseEventHandler(titleBar), + gradientStartColor = gradientStartColor, + style = style, + applyTitleBar = { height, _ -> titleBar.height = height.value titleBar.putProperty("controls.dark", style.colors.background.isDark()) JBR.getWindowDecorations().setCustomTitleBar(window, titleBar) PaddingValues(start = titleBar.leftInset.dp, end = titleBar.rightInset.dp) }, - content, + content = content, ) } internal fun Modifier.customTitleBarMouseEventHandler(titleBar: CustomTitleBar): Modifier = - this.pointerInput(Unit) { + pointerInput(Unit) { val currentContext = currentCoroutineContext() awaitPointerEventScope { var inUserControl = false diff --git a/decorated-window/src/main/kotlin/org/jetbrains/jewel/window/TitleBar.kt b/decorated-window/src/main/kotlin/org/jetbrains/jewel/window/TitleBar.kt index 9c6c6b6b7d..acd1218ff1 100644 --- a/decorated-window/src/main/kotlin/org/jetbrains/jewel/window/TitleBar.kt +++ b/decorated-window/src/main/kotlin/org/jetbrains/jewel/window/TitleBar.kt @@ -67,8 +67,7 @@ public fun DecoratedWindowScope.TitleBar( DesktopPlatform.Linux -> TitleBarOnLinux(modifier, gradientStartColor, style, content) DesktopPlatform.Windows -> TitleBarOnWindows(modifier, gradientStartColor, style, content) DesktopPlatform.MacOS -> TitleBarOnMacOs(modifier, gradientStartColor, style, content) - DesktopPlatform.Unknown -> - error("TitleBar is not supported on this platform(${System.getProperty("os.name")})") + DesktopPlatform.Unknown -> error("TitleBar is not supported on this platform(${System.getProperty("os.name")})") } } @@ -86,25 +85,24 @@ internal fun DecoratedWindowScope.TitleBarImpl( val density = LocalDensity.current - val backgroundBrush = - remember(background, gradientStartColor) { - if (gradientStartColor.isUnspecified) { - SolidColor(background) - } else { - with(density) { - Brush.horizontalGradient( - 0.0f to background, - 0.5f to gradientStartColor, - 1.0f to background, - startX = style.metrics.gradientStartX.toPx(), - endX = style.metrics.gradientEndX.toPx(), - ) - } + val backgroundBrush = remember(background, gradientStartColor) { + if (gradientStartColor.isUnspecified) { + SolidColor(background) + } else { + with(density) { + Brush.horizontalGradient( + 0.0f to background, + 0.5f to gradientStartColor, + 1.0f to background, + startX = style.metrics.gradientStartX.toPx(), + endX = style.metrics.gradientEndX.toPx(), + ) } } + } Layout( - { + content = { CompositionLocalProvider( LocalContentColor provides style.colors.content, LocalIconButtonStyle provides style.iconButtonStyle, @@ -116,15 +114,13 @@ internal fun DecoratedWindowScope.TitleBarImpl( } } }, - modifier - .background(backgroundBrush) + modifier = modifier.background(backgroundBrush) .focusProperties { canFocus = false } .layoutId(TITLE_BAR_LAYOUT_ID) .height(style.metrics.height) .onSizeChanged { with(density) { applyTitleBar(it.height.toDp(), state) } } .fillMaxWidth(), - measurePolicy = - rememberTitleBarMeasurePolicy( + measurePolicy = rememberTitleBarMeasurePolicy( window, state, applyTitleBar, @@ -145,15 +141,9 @@ internal class TitleBarMeasurePolicy( private val applyTitleBar: (Dp, DecoratedWindowState) -> PaddingValues, ) : MeasurePolicy { - override fun MeasureScope.measure( - measurables: List, - constraints: Constraints, - ): MeasureResult { + override fun MeasureScope.measure(measurables: List, constraints: Constraints): MeasureResult { if (measurables.isEmpty()) { - return layout( - constraints.minWidth, - constraints.minHeight, - ) {} + return layout(width = constraints.minWidth, height = constraints.minHeight) {} } var occupiedSpaceHorizontally = 0 @@ -241,15 +231,10 @@ internal fun rememberTitleBarMeasurePolicy( window: Window, state: DecoratedWindowState, applyTitleBar: (Dp, DecoratedWindowState) -> PaddingValues, -): MeasurePolicy { - return remember(window, state, applyTitleBar) { - TitleBarMeasurePolicy( - window, - state, - applyTitleBar, - ) +): MeasurePolicy = + remember(window, state, applyTitleBar) { + TitleBarMeasurePolicy(window, state, applyTitleBar) } -} public interface TitleBarScope { @@ -257,7 +242,8 @@ public interface TitleBarScope { public val icon: Painter? - @Stable public fun Modifier.align(alignment: Alignment.Horizontal): Modifier + @Stable + public fun Modifier.align(alignment: Alignment.Horizontal): Modifier } private class TitleBarScopeImpl( @@ -265,18 +251,14 @@ private class TitleBarScopeImpl( override val icon: Painter?, ) : TitleBarScope { - override fun Modifier.align(alignment: Alignment.Horizontal): Modifier { - return then( - TitleBarChildDataElement( - alignment, - inspectorInfo = - debugInspectorInfo { - name = "align" - value = alignment - }, - ), + override fun Modifier.align(alignment: Alignment.Horizontal): Modifier = + this then TitleBarChildDataElement( + alignment, + debugInspectorInfo { + name = "align" + value = alignment + }, ) - } } private class TitleBarChildDataElement( @@ -307,5 +289,6 @@ private class TitleBarChildDataNode( var horizontalAlignment: Alignment.Horizontal, ) : ParentDataModifierNode, Modifier.Node() { - override fun Density.modifyParentData(parentData: Any?) = this@TitleBarChildDataNode + override fun Density.modifyParentData(parentData: Any?) = + this@TitleBarChildDataNode } diff --git a/decorated-window/src/main/kotlin/org/jetbrains/jewel/window/utils/UnsafeAccessing.kt b/decorated-window/src/main/kotlin/org/jetbrains/jewel/window/utils/UnsafeAccessing.kt index eb7c36b3a8..ed0e7920a2 100644 --- a/decorated-window/src/main/kotlin/org/jetbrains/jewel/window/utils/UnsafeAccessing.kt +++ b/decorated-window/src/main/kotlin/org/jetbrains/jewel/window/utils/UnsafeAccessing.kt @@ -34,20 +34,15 @@ internal object UnsafeAccessing { private val implAddOpens by lazy { try { - Module::class - .java - .getDeclaredMethod( - "implAddOpens", - String::class.java, - Module::class.java, - ) + Module::class.java + .getDeclaredMethod("implAddOpens", String::class.java, Module::class.java) .accessible() } catch (_: Throwable) { null } } - public fun assignAccessibility(obj: AccessibleObject) { + fun assignAccessibility(obj: AccessibleObject) { try { val theUnsafe = unsafe as? Unsafe ?: return val offset = isAccessibleFieldOffset ?: return @@ -57,7 +52,7 @@ internal object UnsafeAccessing { } } - public fun assignAccessibility(module: Module, packages: List) { + fun assignAccessibility(module: Module, packages: List) { try { packages.forEach { implAddOpens?.invoke(module, it, ownerModule) } } catch (_: Throwable) { @@ -69,7 +64,8 @@ internal object UnsafeAccessing { var first = false - @Volatile var second: Any? = null + @Volatile + var second: Any? = null } } diff --git a/decorated-window/src/main/kotlin/org/jetbrains/jewel/window/utils/macos/Foundation.kt b/decorated-window/src/main/kotlin/org/jetbrains/jewel/window/utils/macos/Foundation.kt index 94caa0c660..193b29c7eb 100644 --- a/decorated-window/src/main/kotlin/org/jetbrains/jewel/window/utils/macos/Foundation.kt +++ b/decorated-window/src/main/kotlin/org/jetbrains/jewel/window/utils/macos/Foundation.kt @@ -35,20 +35,20 @@ internal object Foundation { private val myObjcMsgSend: Function? by lazy { try { - (Proxy.getInvocationHandler(myFoundationLibrary) as Library.Handler) - .nativeLibrary - .getFunction("objc_msgSend") + (Proxy.getInvocationHandler(myFoundationLibrary) as Library.Handler).nativeLibrary.getFunction("objc_msgSend") } catch (_: Throwable) { null } } - /** Get the ID of the NSClass with className */ - public fun getObjcClass(className: String?): ID? = myFoundationLibrary?.objc_getClass(className) + /** + * Get the ID of the NSClass with className + */ + fun getObjcClass(className: String?): ID? = myFoundationLibrary?.objc_getClass(className) - public fun getProtocol(name: String?): ID? = myFoundationLibrary?.objc_getProtocol(name) + fun getProtocol(name: String?): ID? = myFoundationLibrary?.objc_getProtocol(name) - public fun createSelector(s: String?): Pointer? = myFoundationLibrary?.sel_registerName(s) + fun createSelector(s: String?): Pointer? = myFoundationLibrary?.sel_registerName(s) private fun prepInvoke(id: ID?, selector: Pointer?, args: Array): Array { val invokArgs = arrayOfNulls(args.size + 2) @@ -59,20 +59,17 @@ internal object Foundation { } // objc_msgSend is called with the calling convention of the target method - // on x86_64 this does not make a difference, but arm64 uses a different calling convention for - // varargs + // on x86_64 this does not make a difference, but arm64 uses a different calling convention for varargs // it is therefore important to not call objc_msgSend as a vararg function operator fun invoke(id: ID?, selector: Pointer?, vararg args: Any?): ID = ID(myObjcMsgSend?.invokeLong(prepInvoke(id, selector, args)) ?: 0) /** - * Invokes the given vararg selector. Expects `NSArray arrayWithObjects:(id), ...` like signature, i.e., - * exactly one fixed argument, followed by varargs. + * Invokes the given vararg selector. + * Expects `NSArray arrayWithObjects:(id), ...` like signature, i.e. exactly one fixed argument, followed by varargs. */ - public fun invokeVarArg(id: ID?, selector: Pointer?, vararg args: Any?): ID { - // c functions and objc methods have at least 1 fixed argument, we therefore need to - // separate - // out the first argument + fun invokeVarArg(id: ID?, selector: Pointer?, vararg args: Any?): ID { + // c functions and objc methods have at least 1 fixed argument, we therefore need to separate out the first argument return myFoundationLibrary?.objc_msgSend( id, selector, @@ -84,10 +81,10 @@ internal object Foundation { operator fun invoke(cls: String?, selector: String?, vararg args: Any?): ID = invoke(getObjcClass(cls), createSelector(selector), *args) - public fun invokeVarArg(cls: String?, selector: String?, vararg args: Any?): ID = + fun invokeVarArg(cls: String?, selector: String?, vararg args: Any?): ID = invokeVarArg(getObjcClass(cls), createSelector(selector), *args) - public fun safeInvoke(stringCls: String?, stringSelector: String?, vararg args: Any?): ID { + fun safeInvoke(stringCls: String?, stringSelector: String?, vararg args: Any?): ID { val cls = getObjcClass(stringCls) val selector = createSelector(stringSelector) if (!invoke(cls, "respondsToSelector:", selector).booleanValue()) { diff --git a/decorated-window/src/main/kotlin/org/jetbrains/jewel/window/utils/macos/FoundationLibrary.kt b/decorated-window/src/main/kotlin/org/jetbrains/jewel/window/utils/macos/FoundationLibrary.kt index 9ca7d1138c..a4c93807e2 100644 --- a/decorated-window/src/main/kotlin/org/jetbrains/jewel/window/utils/macos/FoundationLibrary.kt +++ b/decorated-window/src/main/kotlin/org/jetbrains/jewel/window/utils/macos/FoundationLibrary.kt @@ -5,16 +5,11 @@ import com.sun.jna.Library import com.sun.jna.Pointer internal interface FoundationLibrary : Library { - - public fun NSLog(pString: Pointer?, thing: Any?) - - public fun NSFullUserName(): ID? - - public fun objc_allocateClassPair(supercls: ID?, name: String?, extraBytes: Int): ID? - - public fun objc_registerClassPair(cls: ID?) - - public fun CFStringCreateWithBytes( + fun NSLog(pString: Pointer?, thing: Any?) + fun NSFullUserName(): ID? + fun objc_allocateClassPair(supercls: ID?, name: String?, extraBytes: Int): ID? + fun objc_registerClassPair(cls: ID?) + fun CFStringCreateWithBytes( allocator: Pointer?, bytes: ByteArray?, byteCount: Int, @@ -22,65 +17,36 @@ internal interface FoundationLibrary : Library { isExternalRepresentation: Byte, ): ID? - public fun CFStringGetCString( - theString: ID?, - buffer: ByteArray?, - bufferSize: Int, - encoding: Int, - ): Byte - - public fun CFStringGetLength(theString: ID?): Int - - public fun CFStringConvertNSStringEncodingToEncoding(nsEncoding: Long): Long - - public fun CFStringConvertEncodingToIANACharSetName(cfEncoding: Long): ID? - - public fun CFStringConvertIANACharSetNameToEncoding(encodingName: ID?): Long - - public fun CFStringConvertEncodingToNSStringEncoding(cfEncoding: Long): Long - - public fun CFRetain(cfTypeRef: ID?) - - public fun CFRelease(cfTypeRef: ID?) - - public fun CFGetRetainCount(cfTypeRef: Pointer?): Int - - public fun objc_getClass(className: String?): ID? - - public fun objc_getProtocol(name: String?): ID? - - public fun class_createInstance(pClass: ID?, extraBytes: Int): ID? - - public fun sel_registerName(selectorName: String?): Pointer? - - public fun class_replaceMethod(cls: ID?, selName: Pointer?, impl: Callback?, types: String?): ID? - - public fun objc_getMetaClass(name: String?): ID? + fun CFStringGetCString(theString: ID?, buffer: ByteArray?, bufferSize: Int, encoding: Int): Byte + fun CFStringGetLength(theString: ID?): Int + fun CFStringConvertNSStringEncodingToEncoding(nsEncoding: Long): Long + fun CFStringConvertEncodingToIANACharSetName(cfEncoding: Long): ID? + fun CFStringConvertIANACharSetNameToEncoding(encodingName: ID?): Long + fun CFStringConvertEncodingToNSStringEncoding(cfEncoding: Long): Long + fun CFRetain(cfTypeRef: ID?) + fun CFRelease(cfTypeRef: ID?) + fun CFGetRetainCount(cfTypeRef: Pointer?): Int + fun objc_getClass(className: String?): ID? + fun objc_getProtocol(name: String?): ID? + fun class_createInstance(pClass: ID?, extraBytes: Int): ID? + fun sel_registerName(selectorName: String?): Pointer? + fun class_replaceMethod(cls: ID?, selName: Pointer?, impl: Callback?, types: String?): ID? + fun objc_getMetaClass(name: String?): ID? /** - * Note: Vararg version. Should only be used only for selectors with a single fixed argument - * followed by varargs. + * Note: Vararg version. Should only be used only for selectors with a single fixed argument followed by varargs. */ - public fun objc_msgSend(receiver: ID?, selector: Pointer?, firstArg: Any?, vararg args: Any?): ID? - - public fun class_respondsToSelector(cls: ID?, selName: Pointer?): Boolean - - public fun class_addMethod(cls: ID?, selName: Pointer?, imp: Callback?, types: String?): Boolean - - public fun class_addMethod(cls: ID?, selName: Pointer?, imp: ID?, types: String?): Boolean - - public fun class_addProtocol(aClass: ID?, protocol: ID?): Boolean - - public fun class_isMetaClass(cls: ID?): Boolean - - public fun NSStringFromSelector(selector: Pointer?): ID? - - public fun NSStringFromClass(aClass: ID?): ID? - - public fun objc_getClass(clazz: Pointer?): Pointer? - - public companion object { - + fun objc_msgSend(receiver: ID?, selector: Pointer?, firstArg: Any?, vararg args: Any?): ID? + fun class_respondsToSelector(cls: ID?, selName: Pointer?): Boolean + fun class_addMethod(cls: ID?, selName: Pointer?, imp: Callback?, types: String?): Boolean + fun class_addMethod(cls: ID?, selName: Pointer?, imp: ID?, types: String?): Boolean + fun class_addProtocol(aClass: ID?, protocol: ID?): Boolean + fun class_isMetaClass(cls: ID?): Boolean + fun NSStringFromSelector(selector: Pointer?): ID? + fun NSStringFromClass(aClass: ID?): ID? + fun objc_getClass(clazz: Pointer?): Pointer? + + companion object { const val kCFStringEncodingMacRoman = 0 const val kCFStringEncodingWindowsLatin1 = 0x0500 const val kCFStringEncodingISOLatin1 = 0x0201 diff --git a/decorated-window/src/main/kotlin/org/jetbrains/jewel/window/utils/macos/ID.kt b/decorated-window/src/main/kotlin/org/jetbrains/jewel/window/utils/macos/ID.kt index c1d6128e48..df74e25e7f 100644 --- a/decorated-window/src/main/kotlin/org/jetbrains/jewel/window/utils/macos/ID.kt +++ b/decorated-window/src/main/kotlin/org/jetbrains/jewel/window/utils/macos/ID.kt @@ -2,14 +2,16 @@ package org.jetbrains.jewel.window.utils.macos import com.sun.jna.NativeLong -/** Could be an address in memory (if pointer to a class or method) or a value (like 0 or 1) */ +/** + * Could be an address in memory (if pointer to a class or method) or a + * value (like 0 or 1) + */ internal class ID : NativeLong { constructor() - constructor(peer: Long) : super(peer) - public fun booleanValue(): Boolean = toInt() != 0 + fun booleanValue(): Boolean = toInt() != 0 override fun toByte(): Byte = toInt().toByte() @@ -20,8 +22,9 @@ internal class ID : NativeLong { @Suppress("RedundantOverride") // Without this, we get a SOE override fun toInt(): Int = super.toInt() - public companion object { + companion object { - @JvmField val NIL = ID(0L) + @JvmField + val NIL = ID(0L) } } diff --git a/decorated-window/src/main/kotlin/org/jetbrains/jewel/window/utils/macos/MacUtil.kt b/decorated-window/src/main/kotlin/org/jetbrains/jewel/window/utils/macos/MacUtil.kt index 0c544d6252..248cb170a1 100644 --- a/decorated-window/src/main/kotlin/org/jetbrains/jewel/window/utils/macos/MacUtil.kt +++ b/decorated-window/src/main/kotlin/org/jetbrains/jewel/window/utils/macos/MacUtil.kt @@ -24,7 +24,7 @@ internal object MacUtil { } } - public fun getWindowFromJavaWindow(w: Window?): ID { + fun getWindowFromJavaWindow(w: Window?): ID { if (w == null) { return ID.NIL } @@ -43,12 +43,11 @@ internal object MacUtil { return ID.NIL } - public fun getPlatformWindow(w: Window): Any? { + fun getPlatformWindow(w: Window): Any? { try { val awtAccessor = Class.forName("sun.awt.AWTAccessor") val componentAccessor = awtAccessor.getMethod("getComponentAccessor").invoke(null) - val getPeer = - componentAccessor.javaClass.getMethod("getPeer", Component::class.java).accessible() + val getPeer = componentAccessor.javaClass.getMethod("getPeer", Component::class.java).accessible() val peer = getPeer.invoke(componentAccessor, w) if (peer != null) { val cWindowPeerClass: Class<*> = peer.javaClass @@ -70,15 +69,11 @@ internal object MacUtil { return null } - public fun updateColors(w: Window) { + fun updateColors(w: Window) { SwingUtilities.invokeLater { val window = getWindowFromJavaWindow(w) val delegate = Foundation.invoke(window, "delegate") - if (Foundation.invoke( - delegate, - "respondsToSelector:", - Foundation.createSelector("updateColors"), - ) + if (Foundation.invoke(delegate, "respondsToSelector:", Foundation.createSelector("updateColors")) .booleanValue() ) { Foundation.invoke(delegate, "updateColors") @@ -86,7 +81,7 @@ internal object MacUtil { } } - public fun updateFullScreenButtons(w: Window) { + fun updateFullScreenButtons(w: Window) { SwingUtilities.invokeLater { val selector = Foundation.createSelector("updateFullScreenButtons") val window = getWindowFromJavaWindow(w) diff --git a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/ExperimentalJewelApi.kt b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/ExperimentalJewelApi.kt index 84ce0adc5d..abb36a56fc 100644 --- a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/ExperimentalJewelApi.kt +++ b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/ExperimentalJewelApi.kt @@ -1,12 +1,20 @@ package org.jetbrains.jewel.foundation +import kotlin.RequiresOptIn.Level + @RequiresOptIn( - level = RequiresOptIn.Level.WARNING, - message = - "This is an experimental API for Jewel and is likely to change before becoming " + "stable.", + level = Level.WARNING, + message = "This is an experimental API for Jewel and is likely to change before becoming stable.", ) @Target( AnnotationTarget.CLASS, + AnnotationTarget.CONSTRUCTOR, + AnnotationTarget.FIELD, AnnotationTarget.FUNCTION, + AnnotationTarget.PROPERTY, + AnnotationTarget.PROPERTY_GETTER, + AnnotationTarget.PROPERTY_SETTER, + AnnotationTarget.TYPEALIAS, + AnnotationTarget.VALUE_PARAMETER, ) public annotation class ExperimentalJewelApi diff --git a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/GenerateDataFunctions.kt b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/GenerateDataFunctions.kt index 2e4bf843a4..d7f1be727e 100644 --- a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/GenerateDataFunctions.kt +++ b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/GenerateDataFunctions.kt @@ -1,10 +1,11 @@ package org.jetbrains.jewel.foundation /** - * Instructs the Poko compiler plugin to generate equals, hashcode, and toString functions for the - * class it's attached to. + * Instructs the Poko compiler plugin to generate equals, hashcode, and + * toString functions for the class it's attached to. * - * See https://github.com/JetBrains/jewel/issues/83 + * See [this issue](https://github.com/JetBrains/jewel/issues/83) for + * details. */ @Target(AnnotationTarget.CLASS) public annotation class GenerateDataFunctions diff --git a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/InternalJewelApi.kt b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/InternalJewelApi.kt index 049fee1418..6c41b68238 100644 --- a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/InternalJewelApi.kt +++ b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/InternalJewelApi.kt @@ -1,13 +1,21 @@ package org.jetbrains.jewel.foundation +import kotlin.RequiresOptIn.Level + @RequiresOptIn( - level = RequiresOptIn.Level.WARNING, + level = Level.WARNING, message = "This is an internal API for Jewel and is subject to change without notice.", ) @Target( AnnotationTarget.CLASS, - AnnotationTarget.FUNCTION, AnnotationTarget.CONSTRUCTOR, + AnnotationTarget.FIELD, + AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY, + AnnotationTarget.PROPERTY_GETTER, + AnnotationTarget.PROPERTY_SETTER, + AnnotationTarget.TYPEALIAS, + AnnotationTarget.VALUE_PARAMETER, + ) public annotation class InternalJewelApi diff --git a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/RoundRectUtil.kt b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/RoundRectUtil.kt index b0c40e04dd..b971fd65a4 100644 --- a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/RoundRectUtil.kt +++ b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/RoundRectUtil.kt @@ -9,14 +9,10 @@ internal fun RoundRect.grow(delta: Float) = top = top - delta, right = right + delta, bottom = bottom + delta, - topLeftCornerRadius = - CornerRadius(topLeftCornerRadius.x + delta, topLeftCornerRadius.y + delta), - topRightCornerRadius = - CornerRadius(topRightCornerRadius.x + delta, topRightCornerRadius.y + delta), - bottomLeftCornerRadius = - CornerRadius(bottomLeftCornerRadius.x + delta, bottomLeftCornerRadius.y + delta), - bottomRightCornerRadius = - CornerRadius(bottomRightCornerRadius.x + delta, bottomRightCornerRadius.y + delta), + topLeftCornerRadius = CornerRadius(topLeftCornerRadius.x + delta, topLeftCornerRadius.y + delta), + topRightCornerRadius = CornerRadius(topRightCornerRadius.x + delta, topRightCornerRadius.y + delta), + bottomLeftCornerRadius = CornerRadius(bottomLeftCornerRadius.x + delta, bottomLeftCornerRadius.y + delta), + bottomRightCornerRadius = CornerRadius(bottomRightCornerRadius.x + delta, bottomRightCornerRadius.y + delta), ) internal fun RoundRect.shrink(delta: Float) = @@ -25,14 +21,10 @@ internal fun RoundRect.shrink(delta: Float) = top = top + delta, right = right - delta, bottom = bottom - delta, - topLeftCornerRadius = - CornerRadius(topLeftCornerRadius.x - delta, topLeftCornerRadius.y - delta), - topRightCornerRadius = - CornerRadius(topRightCornerRadius.x - delta, topRightCornerRadius.y - delta), - bottomLeftCornerRadius = - CornerRadius(bottomLeftCornerRadius.x - delta, bottomLeftCornerRadius.y - delta), - bottomRightCornerRadius = - CornerRadius(bottomRightCornerRadius.x - delta, bottomRightCornerRadius.y - delta), + topLeftCornerRadius = CornerRadius(topLeftCornerRadius.x - delta, topLeftCornerRadius.y - delta), + topRightCornerRadius = CornerRadius(topRightCornerRadius.x - delta, topRightCornerRadius.y - delta), + bottomLeftCornerRadius = CornerRadius(bottomLeftCornerRadius.x - delta, bottomLeftCornerRadius.y - delta), + bottomRightCornerRadius = CornerRadius(bottomRightCornerRadius.x - delta, bottomRightCornerRadius.y - delta), ) internal fun RoundRect.hasAtLeastOneNonRoundedCorner() = diff --git a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/Stroke.kt b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/Stroke.kt index c7e7a3a743..cbbb0684bb 100644 --- a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/Stroke.kt +++ b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/Stroke.kt @@ -17,8 +17,7 @@ public sealed class Stroke { @Immutable @GenerateDataFunctions - public class Solid - internal constructor( + public class Solid internal constructor( public val width: Dp, public val color: Color, public val alignment: Alignment, @@ -27,8 +26,7 @@ public sealed class Stroke { @Immutable @GenerateDataFunctions - public class Brush - internal constructor( + public class Brush internal constructor( public val width: Dp, public val brush: androidx.compose.ui.graphics.Brush, public val alignment: Alignment, diff --git a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/Keybindings.kt b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/Keybindings.kt index 50d21ac4d3..7916a18608 100644 --- a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/Keybindings.kt +++ b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/Keybindings.kt @@ -21,58 +21,78 @@ public interface SelectableColumnKeybindings { public val PointerKeyboardModifiers.isMultiSelectionKeyPressed: Boolean - /** Select First Node */ + /** + * Select First Node. + */ public val KeyEvent.isSelectFirstItem: Boolean /** * Extend Selection to First Node inherited from Move Caret to Text Start - * with Selection + * with Selection. */ public val KeyEvent.isExtendSelectionToFirstItem: Boolean - /** Select Last Node inherited from Move Caret to Text End */ + /** + * Select Last Node inherited from Move Caret to Text End. + */ public val KeyEvent.isSelectLastItem: Boolean /** * Extend Selection to Last Node inherited from Move Caret to Text End with - * Selection + * Selection. */ public val KeyEvent.isExtendSelectionToLastItem: Boolean - /** Select Previous Node inherited from Up */ + /** + * Select Previous Node inherited from Up. + */ public val KeyEvent.isSelectPreviousItem: Boolean - /** Extend Selection with Previous Node inherited from Up with Selection */ + /** + * Extend Selection with Previous Node inherited from Up with Selection. + */ public val KeyEvent.isExtendSelectionWithPreviousItem: Boolean - /** Select Next Node inherited from Down */ + /** + * Select Next Node inherited from Down. + */ public val KeyEvent.isSelectNextItem: Boolean - /** Extend Selection with Next Node inherited from Down with Selection */ + /** + * Extend Selection with Next Node inherited from Down with Selection. + */ public val KeyEvent.isExtendSelectionWithNextItem: Boolean - /** Scroll Page Up and Select Node inherited from Page Up */ + /** + * Scroll Page Up and Select Node inherited from Page Up. + */ public val KeyEvent.isScrollPageUpAndSelectItem: Boolean /** * Scroll Page Up and Extend Selection inherited from Page Up with - * Selection + * Selection. */ public val KeyEvent.isScrollPageUpAndExtendSelection: Boolean - /** Scroll Page Down and Select Node inherited from Page Down */ + /** + * Scroll Page Down and Select Node inherited from Page Down. + */ public val KeyEvent.isScrollPageDownAndSelectItem: Boolean /** * Scroll Page Down and Extend Selection inherited from Page Down with - * Selection + * Selection. */ public val KeyEvent.isScrollPageDownAndExtendSelection: Boolean - /** Edit item */ + /** + * Edit item. + */ public val KeyEvent.isEdit: Boolean - /** SelectAll */ + /** + * Select all items. + */ public val KeyEvent.isSelectAll: Boolean } diff --git a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/SelectableColumnOnKeyEvent.kt b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/SelectableColumnOnKeyEvent.kt index 13490b095f..0795d4fda7 100644 --- a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/SelectableColumnOnKeyEvent.kt +++ b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/SelectableColumnOnKeyEvent.kt @@ -8,7 +8,9 @@ public interface SelectableColumnOnKeyEvent { public val keybindings: SelectableColumnKeybindings - /** Select First Node */ + /** + * Select First Node. + */ public fun onSelectFirstItem( allKeys: List, state: SelectableLazyListState, @@ -20,7 +22,10 @@ public interface SelectableColumnOnKeyEvent { } } - /** Extend Selection to First Node inherited from Move Caret to Text Start with Selection */ + /** + * Extend Selection to First Node inherited from Move Caret to Text Start + * with Selection. + */ public fun onExtendSelectionToFirst( keys: List, state: SelectableLazyListState, @@ -44,10 +49,14 @@ public interface SelectableColumnOnKeyEvent { } } - /** Select Last Node inherited from Move Caret to Text End */ - public fun onSelectLastItem(keys: List, state: SelectableLazyListState) { - keys - .withIndex() + /** + * Select Last Node inherited from Move Caret to Text End. + */ + public fun onSelectLastItem( + keys: List, + state: SelectableLazyListState, + ) { + keys.withIndex() .lastOrNull { it.value is Selectable } ?.let { state.selectedKeys = listOf(it) @@ -55,7 +64,10 @@ public interface SelectableColumnOnKeyEvent { } } - /** Extend Selection to Last Node inherited from Move Caret to Text End with Selection */ + /** + * Extend Selection to Last Node inherited from Move Caret to Text End with + * Selection. + */ public fun onExtendSelectionToLastItem( keys: List, state: SelectableLazyListState, @@ -72,15 +84,16 @@ public interface SelectableColumnOnKeyEvent { } } - /** Select Previous Node inherited from Up */ + /** + * Select Previous Node inherited from Up. + */ public fun onSelectPreviousItem( keys: List, state: SelectableLazyListState, ) { state.lastActiveItemIndex?.let { lastActiveIndex -> if (lastActiveIndex == 0) return@let - keys - .withIndex() + keys.withIndex() .toList() .dropLastWhile { it.index >= lastActiveIndex } .reversed() @@ -92,15 +105,16 @@ public interface SelectableColumnOnKeyEvent { } } - /** Extend Selection with Previous Node inherited from Up with Selection */ + /** + * Extend Selection with Previous Node inherited from Up with Selection. + */ public fun onExtendSelectionWithPreviousItem( keys: List, state: SelectableLazyListState, ) { state.lastActiveItemIndex?.let { lastActiveIndex -> if (lastActiveIndex == 0) return@let - keys - .withIndex() + keys.withIndex() .toList() .dropLastWhile { it.index >= lastActiveIndex } .reversed() @@ -112,12 +126,16 @@ public interface SelectableColumnOnKeyEvent { } } - /** Select Next Node inherited from Down */ - public fun onSelectNextItem(keys: List, state: SelectableLazyListState) { + /** + * Select Next Node inherited from Down. + */ + public fun onSelectNextItem( + keys: List, + state: SelectableLazyListState, + ) { state.lastActiveItemIndex?.let { lastActiveIndex -> if (lastActiveIndex == keys.lastIndex) return@let - keys - .withIndex() + keys.withIndex() .dropWhile { it.index <= lastActiveIndex } .firstOrNull { it.value is Selectable } ?.let { (index, selectableKey) -> @@ -127,7 +145,9 @@ public interface SelectableColumnOnKeyEvent { } } - /** Extend Selection with Next Node inherited from Down with Selection */ + /** + * Extend Selection with Next Node inherited from Down with Selection. + */ public fun onExtendSelectionWithNextItem( keys: List, state: SelectableLazyListState, @@ -146,7 +166,9 @@ public interface SelectableColumnOnKeyEvent { } } - /** Scroll Page Up and Select Node inherited from Page Up */ + /** + * Scroll Page Up and Select Node inherited from Page Up. + */ public fun onScrollPageUpAndSelectItem( keys: List, state: SelectableLazyListState, @@ -157,7 +179,10 @@ public interface SelectableColumnOnKeyEvent { state.lastActiveItemIndex = targetIndex } - /** Scroll Page Up and Extend Selection inherited from Page Up with Selection */ + /** + * Scroll Page Up and Extend Selection inherited from Page Up with + * Selection. + */ public fun onScrollPageUpAndExtendSelection( keys: List, state: SelectableLazyListState, @@ -174,7 +199,9 @@ public interface SelectableColumnOnKeyEvent { state.lastActiveItemIndex = targetIndex } - /** Scroll Page Down and Select Node inherited from Page Down */ + /** + * Scroll Page Down and Select Node inherited from Page Down. + */ public fun onScrollPageDownAndSelectItem( keys: List, state: SelectableLazyListState, @@ -185,7 +212,10 @@ public interface SelectableColumnOnKeyEvent { state.lastActiveItemIndex = targetIndex } - /** Scroll Page Down and Extend Selection inherited from Page Down with Selection */ + /** + * Scroll Page Down and Extend Selection inherited from Page Down with + * Selection. + */ public fun onScrollPageDownAndExtendSelection( keys: List, state: SelectableLazyListState, @@ -200,13 +230,17 @@ public interface SelectableColumnOnKeyEvent { state.lastActiveItemIndex = targetIndex } - /** Edit In Item */ + /** + * Edit Item. + */ public fun onEdit() { - // ij with this shortcut focuses the first element with issue - // unavailable here + // IntelliJ focuses the first element with an issue when this is pressed. + // It is thus unavailable here. } - /** Select All */ + /** + * Select All. + */ public fun onSelectAll(keys: List, state: SelectableLazyListState) { state.selectedKeys = keys.filterIsInstance().map { it.key } } diff --git a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/SelectableLazyColumn.kt b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/SelectableLazyColumn.kt index f96c4ace8b..c63ac72e1e 100644 --- a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/SelectableLazyColumn.kt +++ b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/SelectableLazyColumn.kt @@ -96,8 +96,7 @@ public fun SelectableLazyColumn( ) if (keys.any { it.key == entry.key && it is SelectableLazyListKey.Selectable }) { Box( - modifier = - Modifier.selectable( + modifier = Modifier.selectable( requester = focusRequester, keybindings = keyActions.keybindings, actionHandler = pointerEventActions, @@ -113,6 +112,7 @@ public fun SelectableLazyColumn( entry.content.invoke(itemScope) } } + is Entry.Items -> items( count = entry.count, @@ -124,8 +124,7 @@ public fun SelectableLazyColumn( if (keys.any { it.key == entry.key(index) && it is SelectableLazyListKey.Selectable }) { Box( - modifier = - Modifier.selectable( + modifier = Modifier.selectable( requester = focusRequester, keybindings = keyActions.keybindings, actionHandler = pointerEventActions, @@ -141,14 +140,14 @@ public fun SelectableLazyColumn( entry.itemContent.invoke(itemScope, index) } } + is Entry.StickyHeader -> stickyHeader(entry.key, entry.contentType) { val itemScope = SelectableLazyItemScope(entry.key in state.selectedKeys, isFocused) if (keys.any { it.key == entry.key && it is SelectableLazyListKey.Selectable }) { Box( - modifier = - Modifier.selectable( + modifier = Modifier.selectable( keybindings = keyActions.keybindings, actionHandler = pointerEventActions, selectionMode = selectionMode, diff --git a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/SelectableLazyListScope.kt b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/SelectableLazyListScope.kt index 98380c0682..4f0907c11e 100644 --- a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/SelectableLazyListScope.kt +++ b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/SelectableLazyListScope.kt @@ -6,7 +6,9 @@ import androidx.compose.runtime.Composable import org.jetbrains.jewel.foundation.lazy.SelectableLazyListKey.NotSelectable import org.jetbrains.jewel.foundation.lazy.SelectableLazyListKey.Selectable -/** Interface defining the scope for building a selectable lazy list. */ +/** + * Interface defining the scope for building a selectable lazy list. + */ public interface SelectableLazyListScope { /** @@ -14,7 +16,8 @@ public interface SelectableLazyListScope { * * @param key The unique identifier for the item. * @param contentType The type of content displayed in the item. - * @param selectable Determines if the item is selectable. Default is `true`. + * @param selectable Determines if the item is selectable. Default is + * `true`. * @param content The content of the item as a composable function. */ public fun item( @@ -51,8 +54,8 @@ public interface SelectableLazyListScope { * @param key The unique identifier for the sticky header. * @param contentType The type of content in the sticky header. * @param selectable Specifies whether the sticky header is selectable. - * @param content The content to be displayed in the sticky header, provided as a composable - * function + * @param content The content to be displayed in the sticky header, + * provided as a composable function */ public fun stickyHeader( key: Any, @@ -63,12 +66,13 @@ public interface SelectableLazyListScope { } internal class SelectableLazyListScopeContainer : SelectableLazyListScope { + private val keys = mutableListOf() private val entries = mutableListOf() - public fun getEntries() = entries.toList() + fun getEntries() = entries.toList() - public fun getKeys() = keys.toList() + fun getKeys() = keys.toList() internal sealed interface Entry { data class Item( diff --git a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/SelectableLazyListState.kt b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/SelectableLazyListState.kt index f10c4ec496..7fb8035789 100644 --- a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/SelectableLazyListState.kt +++ b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/SelectableLazyListState.kt @@ -25,7 +25,8 @@ public interface SelectableScope { } /** - * State object for a selectable lazy list, which extends [ScrollableState]. + * State object for a selectable lazy list, which extends + * [ScrollableState]. * * @param lazyListState The state object for the underlying lazy list. */ @@ -36,6 +37,7 @@ public class SelectableLazyListState( internal var lastKeyEventUsedMouse: Boolean = false override var selectedKeys: List by mutableStateOf(emptyList()) + public var lastActiveItemIndex: Int? = null /** @@ -51,19 +53,17 @@ public class SelectableLazyListState( val visibleRange = visibleItemsRange.drop(2).dropLast(4) if (itemIndex !in visibleRange && visibleRange.isNotEmpty()) { when { - itemIndex < visibleRange.first() -> - lazyListState.scrollToItem( - max(0, itemIndex - 2), - animateScroll, - scrollOffset, - ) - itemIndex > visibleRange.last() -> { - lazyListState.scrollToItem( - index = max(itemIndex - (visibleRange.size + 2), 0), - animate = animateScroll, - scrollOffset = 0, - ) - } + itemIndex < visibleRange.first() -> lazyListState.scrollToItem( + max(0, itemIndex - 2), + animateScroll, + scrollOffset, + ) + + itemIndex > visibleRange.last() -> lazyListState.scrollToItem( + index = max(itemIndex - (visibleRange.size + 2), 0), + animate = animateScroll, + scrollOffset = 0, + ) } } lastActiveItemIndex = itemIndex @@ -73,14 +73,14 @@ public class SelectableLazyListState( get() = lazyListState.layoutInfo /** - * The index of the first item that is visible + * The index of the first item that is visible. */ public val firstVisibleItemIndex: Int get() = lazyListState.firstVisibleItemIndex /** - * The scroll offset of the first visible item. Scrolling forward is positive - i.e., the amount - * that the item is offset backwards + * The scroll offset of the first visible item. Scrolling forward is + * positive - i.e., the amount that the item is offset backwards. */ @Suppress("unused") public val firstVisibleItemScrollOffset: Int @@ -178,7 +178,8 @@ public enum class SelectionMode { * Remembers the state of a selectable lazy list. * * @param firstVisibleItemIndex The index of the first visible item. - * @param firstVisibleItemScrollOffset The scroll offset of the first visible item. + * @param firstVisibleItemScrollOffset The scroll offset of the first + * visible item. * @return The remembered state of the selectable lazy list. */ @Composable diff --git a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/tree/BasicLazyTree.kt b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/tree/BasicLazyTree.kt index 234684ad7e..a588e8d269 100644 --- a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/tree/BasicLazyTree.kt +++ b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/tree/BasicLazyTree.kt @@ -46,27 +46,40 @@ import kotlin.time.Duration.Companion.milliseconds * * @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. - * @param elementBackgroundFocused The background color of a tree node when focused. - * @param elementBackgroundSelectedFocused The background color of a selected tree node when - * focused. - * @param elementBackgroundSelected The background color of a selected tree node. - * @param indentSize The size of the indent for each level of the tree node. - * @param elementBackgroundCornerSize The corner size of the background shape of a tree node. + * @param onElementClick Callback function triggered when a tree node is + * clicked. + * @param elementBackgroundFocused The background color of a tree node when + * focused. + * @param elementBackgroundSelectedFocused The background color of a + * selected tree node when focused. + * @param elementBackgroundSelected The background color of a selected tree + * node. + * @param indentSize The size of the indent for each level of the tree + * node. + * @param elementBackgroundCornerSize The corner size of the background + * shape of a tree node. * @param elementPadding The padding for the entire tree node. - * @param elementContentPadding The padding for the content within a tree node. + * @param elementContentPadding The padding for the content within a tree + * node. * @param elementMinHeight The minimum height of a tree node. - * @param chevronContentGap The gap between the chevron icon and the node content. + * @param chevronContentGap The gap between the chevron icon and the node + * content. * @param treeState The state object for managing the tree view state. - * @param modifier Optional modifier for styling or positioning the tree view. - * @param onElementDoubleClick Callback function triggered when a tree node is double-clicked. - * @param onSelectionChange Callback function triggered when the selected tree nodes change. - * @param platformDoubleClickDelay The duration between two consecutive clicks to be considered a - * double-click. + * @param modifier Optional modifier for styling or positioning the tree + * view. + * @param onElementDoubleClick Callback function triggered when a tree node + * is double-clicked. + * @param onSelectionChange Callback function triggered when the selected + * tree nodes change. + * @param platformDoubleClickDelay The duration between two consecutive + * clicks to be considered a double-click. * @param keyActions The key binding actions for the tree view. - * @param pointerEventScopedActions The pointer event actions for the tree view. - * @param chevronContent The composable function responsible for rendering the chevron icon. - * @param nodeContent The composable function responsible for rendering the content of a tree node. + * @param pointerEventScopedActions The pointer event actions for the tree + * view. + * @param chevronContent The composable function responsible for rendering + * the chevron icon. + * @param nodeContent The composable function responsible for rendering the + * content of a tree node. * * @suppress("UNCHECKED_CAST") * @@ -93,23 +106,19 @@ public fun BasicLazyTree( onSelectionChange: (List>) -> Unit, platformDoubleClickDelay: Duration = 500.milliseconds, keyActions: KeyActions = DefaultTreeViewKeyActions(treeState), - pointerEventScopedActions: PointerEventActions = remember { - DefaultTreeViewPointerEventAction(treeState) - }, + pointerEventScopedActions: PointerEventActions = remember { DefaultTreeViewPointerEventAction(treeState) }, chevronContent: @Composable (nodeState: TreeElementState) -> Unit, nodeContent: @Composable (SelectableLazyItemScope.(Tree.Element) -> Unit), ) { val scope = rememberCoroutineScope() - val flattenedTree = - remember(tree, treeState.openNodes, treeState.allNodes) { - tree.roots.flatMap { it.flattenTree(treeState) } - } + val flattenedTree = remember(tree, treeState.openNodes, treeState.allNodes) { + tree.roots.flatMap { it.flattenTree(treeState) } + } remember(tree) { // if tree changes we need to update selection changes onSelectionChange( - flattenedTree - .asSequence() + flattenedTree.asSequence() .filter { it.id in treeState.delegate.selectedKeys } .map { element -> element as Tree.Element } .toList(), @@ -175,8 +184,7 @@ public fun BasicLazyTree( ) { if (element is Tree.Element.Node) { Box( - modifier = - Modifier.clickable( + modifier = Modifier.clickable( interactionSource = remember { MutableInteractionSource() }, indication = null, ) { @@ -202,8 +210,7 @@ private fun Modifier.elementBackground( backgroundShape: RoundedCornerShape, ) = background( - color = - when { + color = when { state.isActive && state.isSelected -> selectedFocused state.isActive && !state.isSelected -> focused state.isSelected && !state.isActive -> selected @@ -313,6 +320,7 @@ private fun Tree.Element<*>.flattenTree(state: TreeState): MutableList orderedChildren.addAll(child.flattenTree(state)) } } + is Tree.Element.Leaf<*> -> { orderedChildren.add(this) } @@ -321,8 +329,10 @@ private fun Tree.Element<*>.flattenTree(state: TreeState): MutableList.getAllSubNodes(node: Tree.Element.Node<*>) { - node.children?.filterIsInstance>()?.forEach { - add(it.id) - this@getAllSubNodes getAllSubNodes (it) - } + node.children + ?.filterIsInstance>() + ?.forEach { + add(it.id) + this@getAllSubNodes getAllSubNodes (it) + } } diff --git a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/tree/BuildTree.kt b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/tree/BuildTree.kt index bfcb47c456..eed3bfb0d7 100644 --- a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/tree/BuildTree.kt +++ b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/tree/BuildTree.kt @@ -57,30 +57,26 @@ public class TreeBuilder : TreeGeneratorScope { private fun getCurrentTreeElement(index: Int, previous: Tree.Element?) = when (val elementBuilder = heads[index]) { - is Element.Leaf -> - Tree.Element.Leaf( - data = elementBuilder.data, - depth = 0, - childIndex = index, - parent = null, - previous = previous, - next = null, - id = elementBuilder.id ?: "$index", - ) - - is Element.Node -> - Tree.Element.Node( - data = elementBuilder.data, - depth = 0, - childIndex = index, - parent = null, - childrenGenerator = { parent -> - generateElements(parent, elementBuilder) - }, - previous = previous, - next = null, - id = elementBuilder.id ?: "$index", - ) + is Element.Leaf -> Tree.Element.Leaf( + data = elementBuilder.data, + depth = 0, + childIndex = index, + parent = null, + previous = previous, + next = null, + id = elementBuilder.id ?: "$index", + ) + + is Element.Node -> Tree.Element.Node( + data = elementBuilder.data, + depth = 0, + childIndex = index, + parent = null, + childrenGenerator = { parent -> generateElements(parent, elementBuilder) }, + previous = previous, + next = null, + id = elementBuilder.id ?: "$index", + ) } } @@ -95,27 +91,26 @@ private fun generateElements( val previous = if (index == 0) parent else elements[index - 1] val current = when (val elementBuilder = childrenGeneratorScope.elements[index]) { - is TreeBuilder.Element.Leaf -> - Tree.Element.Leaf( - data = elementBuilder.data, - depth = parent.depth + 1, - childIndex = index, - parent = parent, - previous = previous, - next = null, - id = elementBuilder.id ?: (parent.id.toString() + "." + index), - ) - is TreeBuilder.Element.Node -> - Tree.Element.Node( - data = elementBuilder.data, - depth = parent.depth + 1, - childIndex = index, - parent = parent, - childrenGenerator = { generateElements(it, elementBuilder) }, - previous = previous, - next = null, - id = elementBuilder.id ?: (parent.id.toString() + "." + index), - ) + is TreeBuilder.Element.Leaf -> Tree.Element.Leaf( + data = elementBuilder.data, + depth = parent.depth + 1, + childIndex = index, + parent = parent, + previous = previous, + next = null, + id = elementBuilder.id ?: (parent.id.toString() + "." + index), + ) + + is TreeBuilder.Element.Node -> Tree.Element.Node( + data = elementBuilder.data, + depth = parent.depth + 1, + childIndex = index, + parent = parent, + childrenGenerator = { generateElements(it, elementBuilder) }, + previous = previous, + next = null, + id = elementBuilder.id ?: (parent.id.toString() + "." + index), + ) } previous.next = current elements.add(current) @@ -146,8 +141,7 @@ public interface TreeGeneratorScope { public fun add(element: TreeBuilder.Element) } -public class ChildrenGeneratorScope(private val parentElement: Tree.Element.Node) : - TreeGeneratorScope { +public class ChildrenGeneratorScope(private val parentElement: Tree.Element.Node) : TreeGeneratorScope { @GenerateDataFunctions public class ParentInfo(public val data: T, public val depth: Int, public val index: Int) @@ -175,16 +169,19 @@ public class ChildrenGeneratorScope(private val parentElement: Tree.Element.N } } -public fun Path.asTree(isOpen: (File) -> Boolean = { false }): Tree = toFile().asTree(isOpen) +public fun Path.asTree(isOpen: (File) -> Boolean = { false }): Tree = + toFile().asTree(isOpen) -public fun File.asTree(isOpen: (File) -> Boolean = { false }): Tree = buildTree { - addNode(this@asTree, isOpen(this@asTree)) { generateFileNodes(isOpen) } -} +public fun File.asTree(isOpen: (File) -> Boolean = { false }): Tree = + buildTree { + addNode(this@asTree, isOpen(this@asTree)) { + generateFileNodes(isOpen) + } + } private fun ChildrenGeneratorScope.generateFileNodes(isOpen: (File) -> Boolean) { val files = parent.data.listFiles() ?: return - files - .sortedBy { if (it.isDirectory) "a" else "b" } + files.sortedBy { if (it.isDirectory) "a" else "b" } .forEach { file -> when { file.isFile -> addLeaf(file, file.absolutePath) diff --git a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/tree/DefaultTreeViewKeybindings.kt b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/tree/DefaultTreeViewKeybindings.kt index ef5e0a7f20..a9de90bbab 100644 --- a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/tree/DefaultTreeViewKeybindings.kt +++ b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/tree/DefaultTreeViewKeybindings.kt @@ -40,32 +40,32 @@ public open class DefaultTreeViewKeybindings : DefaultSelectableColumnKeybinding public interface TreeViewKeybindings : SelectableColumnKeybindings { /** - * Select Parent Node + * Select Parent Node. */ public val KeyEvent.isSelectParent: Boolean /** - * Extend Selection to Parent Node inherited from Left with Selection + * Extend Selection to Parent Node inherited from Left with Selection. */ public val KeyEvent.isExtendSelectionToParent: Boolean /** - * Select Child Node inherited from Right + * Select Child Node inherited from Right. */ public val KeyEvent.isSelectChild: Boolean /** - * Extend Selection to Child Node inherited from Right with Selection + * Extend Selection to Child Node inherited from Right with Selection. */ public val KeyEvent.isExtendSelectionToChild: Boolean /** - * Select Next Sibling Node + * Select Next Sibling Node. */ public val KeyEvent.isSelectNextSibling: Boolean /** - * Select Previous Sibling Node + * Select Previous Sibling Node. */ public val KeyEvent.isSelectPreviousSibling: Boolean } diff --git a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/tree/DefaultTreeViewOnKeyEvent.kt b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/tree/DefaultTreeViewOnKeyEvent.kt index 7779497fbe..33bfd4d868 100644 --- a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/tree/DefaultTreeViewOnKeyEvent.kt +++ b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/tree/DefaultTreeViewOnKeyEvent.kt @@ -36,8 +36,7 @@ public open class DefaultTreeViewOnKeyEvent( .reversed() .firstOrNull { it.second < currentNode.second } ?.let { (parentNodeKey, _) -> - keys - .first { it.key == parentNodeKey } + keys.first { it.key == parentNodeKey } .takeIf { it is SelectableLazyListKey.Selectable } ?.let { state.lastActiveItemIndex = diff --git a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/tree/KeyActions.kt b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/tree/KeyActions.kt index 9ba6609168..d91fa13dc5 100644 --- a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/tree/KeyActions.kt +++ b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/tree/KeyActions.kt @@ -75,14 +75,17 @@ public open class DefaultSelectableLazyColumnEventAction : PointerEventActions { Log.i("ctrl and shift pressed on click") // do nothing } + pointerEvent.keyboardModifiers.isContiguousSelectionKeyPressed -> { Log.i("shift pressed on click") onExtendSelectionToKey(key, allKeys, selectableLazyListState, selectionMode) } + pointerEvent.keyboardModifiers.isMultiSelectionKeyPressed -> { Log.i("ctrl pressed on click") toggleKeySelection(key, allKeys, selectableLazyListState) } + else -> { Log.i("single click") selectableLazyListState.selectedKeys = listOf(key) @@ -160,14 +163,17 @@ public class DefaultTreeViewPointerEventAction( pointerEvent.keyboardModifiers.isCtrlPressed -> { Log.t("ctrl and shift pressed on click") } + pointerEvent.keyboardModifiers.isContiguousSelectionKeyPressed -> { super.onExtendSelectionToKey(key, allKeys, selectableLazyListState, selectionMode) } + pointerEvent.keyboardModifiers.isMultiSelectionKeyPressed -> { Log.t("multi selection pressed") selectableLazyListState.lastKeyEventUsedMouse = false super.toggleKeySelection(key, allKeys, selectableLazyListState) } + else -> { selectableLazyListState.selectedKeys = listOf(key) } @@ -238,6 +244,7 @@ public class DefaultTreeViewKeyActions( isSelectChild -> onSelectChild(keys, state) super.handleOnKeyEvent(event, keys, state, selectionMode).invoke(keyEvent) -> return@lambda true + else -> return@lambda false } } diff --git a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/tree/TreeViewOnKeyEvent.kt b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/tree/TreeViewOnKeyEvent.kt index 59a32d0b74..10910b6618 100644 --- a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/tree/TreeViewOnKeyEvent.kt +++ b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/lazy/tree/TreeViewOnKeyEvent.kt @@ -6,9 +6,13 @@ import org.jetbrains.jewel.foundation.lazy.SelectableLazyListState public interface TreeViewOnKeyEvent : SelectableColumnOnKeyEvent { - /** Select Parent Node */ + /** + * Select Parent Node. + */ public fun onSelectParent(keys: List, state: SelectableLazyListState) - /** Select Child Node inherited from Right */ + /** + * Select Child Node inherited from Right. + */ public fun onSelectChild(keys: List, state: SelectableLazyListState) } diff --git a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/modifier/Activation.kt b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/modifier/Activation.kt index b67ff3c943..686f5b7d5e 100644 --- a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/modifier/Activation.kt +++ b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/modifier/Activation.kt @@ -82,7 +82,7 @@ public fun Modifier.trackComponentActivation(awtParent: Component): Modifier = @Stable public fun Modifier.trackActivation(): Modifier = composed( - inspectorInfo = debugInspectorInfo { name = "trackActivation" }, + debugInspectorInfo { name = "trackActivation" }, ) { val activatedModifierLocal = remember { ActivatedModifierLocal() } Modifier.focusGroup() @@ -129,7 +129,7 @@ public fun Modifier.onActivated( this then if (enabled) { ActivateChangedModifierElement( onChanged, - inspectorInfo = debugInspectorInfo { + debugInspectorInfo { name = "onActivated" properties["onChanged"] = onChanged }, diff --git a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/modifier/Border.kt b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/modifier/Border.kt index 42f0e9c968..af287dd598 100644 --- a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/modifier/Border.kt +++ b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/modifier/Border.kt @@ -41,7 +41,6 @@ import org.jetbrains.jewel.foundation.grow import org.jetbrains.jewel.foundation.hasAtLeastOneNonRoundedCorner import org.jetbrains.jewel.foundation.shrink import kotlin.math.ceil -import kotlin.math.max import kotlin.math.min public typealias DrawScopeStroke = androidx.compose.ui.graphics.drawscope.Stroke @@ -50,14 +49,13 @@ public fun Modifier.border(stroke: Stroke, shape: Shape): Modifier = when (stroke) { is Stroke.None -> this is Stroke.Solid -> border(stroke.alignment, stroke.width, stroke.color, shape, stroke.expand) - is Stroke.Brush -> - border( - alignment = stroke.alignment, - width = stroke.width, - brush = stroke.brush, - shape = shape, - expand = stroke.expand, - ) + is Stroke.Brush -> border( + alignment = stroke.alignment, + width = stroke.width, + brush = stroke.brush, + shape = shape, + expand = stroke.expand, + ) } public fun Modifier.border( @@ -66,7 +64,8 @@ public fun Modifier.border( color: Color, shape: Shape = RectangleShape, expand: Dp = Dp.Unspecified, -): Modifier = border(alignment, width, SolidColor(color), shape, expand) +): Modifier = + border(alignment, width, SolidColor(color), shape, expand) public fun Modifier.border( alignment: Stroke.Alignment, @@ -94,69 +93,29 @@ private fun Modifier.drawBorderWithAlignment( composed( factory = { val borderCacheRef = remember { Ref() } - this.then( - Modifier.drawWithCache { - onDrawWithContent { - drawContent() - val strokeWidthPx = - max( - min( - if (width == Dp.Hairline) 1f else ceil(width.toPx()), - ceil(size.minDimension / 2), - ), - 1f, - ) - - val expandWidthPx = expand.takeOrElse { 0.dp }.toPx() - - when (val outline = shape.createOutline(size, layoutDirection, this)) { - is Outline.Rectangle -> { - when (shape) { - is RoundedCornerShape -> - drawRoundedBorder( - borderCacheRef, - alignment, - Outline.Rounded(RoundRect(outline.rect)), - brush, - strokeWidthPx, - expandWidthPx, - ) - else -> - drawRectBorder( - borderCacheRef, - alignment, - outline, - brush, - strokeWidthPx, - expandWidthPx, - ) - } - } - is Outline.Rounded -> - drawRoundedBorder( - borderCacheRef, - alignment, - outline, - brush, - strokeWidthPx, - expandWidthPx, - ) - is Outline.Generic -> - drawGenericBorder( - borderCacheRef, - alignment, - outline, - brush, - strokeWidthPx, - expandWidthPx, - ) - } - } - }, - ) + this then Modifier.drawWithCache { + onDrawWithContent { + drawContent() + + val strokeWidthPx = + min(if (width == Dp.Hairline) 1f else ceil(width.toPx()), ceil(size.minDimension / 2)) + .coerceAtLeast(1f) + + val expandWidthPx = expand.takeOrElse { 0.dp }.toPx() + + drawBorderInner( + shape, + borderCacheRef, + alignment, + brush, + strokeWidthPx, + expandWidthPx, + cacheDrawScope = this@drawWithCache, + ) + } + } }, - inspectorInfo = - debugInspectorInfo { + inspectorInfo = debugInspectorInfo { name = "border" properties["alignment"] = alignment properties["width"] = width @@ -171,6 +130,58 @@ private fun Modifier.drawBorderWithAlignment( }, ) +private fun ContentDrawScope.drawBorderInner( + shape: Shape, + borderCacheRef: Ref, + alignment: Stroke.Alignment, + brush: Brush, + strokeWidthPx: Float, + expandWidthPx: Float, + cacheDrawScope: CacheDrawScope, +) { + when (val outline = shape.createOutline(size, layoutDirection, cacheDrawScope)) { + is Outline.Rectangle -> { + when (shape) { + is RoundedCornerShape -> drawRoundedBorder( + borderCacheRef = borderCacheRef, + alignment = alignment, + outline = Outline.Rounded(RoundRect(outline.rect)), + brush = brush, + strokeWidthPx = strokeWidthPx, + expandWidthPx = expandWidthPx, + ) + + else -> drawRectBorder( + borderCacheRef, + alignment, + outline, + brush, + strokeWidthPx, + expandWidthPx, + ) + } + } + + is Outline.Rounded -> drawRoundedBorder( + borderCacheRef, + alignment, + outline, + brush, + strokeWidthPx, + expandWidthPx, + ) + + is Outline.Generic -> cacheDrawScope.drawGenericBorder( + borderCacheRef, + alignment, + outline, + brush, + strokeWidthPx, + expandWidthPx, + ) + } +} + private class BorderCache( private var imageBitmap: ImageBitmap? = null, private var canvas: Canvas? = null, @@ -197,28 +208,15 @@ private class BorderCache( !compatibleConfig ) { targetImageBitmap = - ImageBitmap( - borderSize.width, - borderSize.height, - config = config, - ) + ImageBitmap(borderSize.width, borderSize.height, config = config) .also { imageBitmap = it } targetCanvas = Canvas(targetImageBitmap).also { canvas = it } } val targetDrawScope = canvasDrawScope ?: CanvasDrawScope().also { canvasDrawScope = it } val drawSize = borderSize.toSize() - targetDrawScope.draw( - this, - layoutDirection, - targetCanvas, - drawSize, - ) { - drawRect( - color = Color.Black, - size = drawSize, - blendMode = BlendMode.Clear, - ) + targetDrawScope.draw(this, layoutDirection, targetCanvas, drawSize) { + drawRect(color = Color.Black, size = drawSize, blendMode = BlendMode.Clear) block() } targetImageBitmap.prepareToDraw() @@ -239,18 +237,12 @@ private fun ContentDrawScope.drawRectBorder( strokeWidthPx: Float, expandWidthPx: Float, ) { - val rect = - when (alignment) { - Stroke.Alignment.Inside -> { - outline.rect.inflate(expandWidthPx - strokeWidthPx / 2f) - } - Stroke.Alignment.Center -> { - outline.rect.inflate(expandWidthPx) - } - Stroke.Alignment.Outside -> { - outline.rect.inflate(expandWidthPx + strokeWidthPx / 2f) - } - } + val rect = when (alignment) { + Stroke.Alignment.Inside -> outline.rect.inflate(expandWidthPx - strokeWidthPx / 2f) + Stroke.Alignment.Center -> outline.rect.inflate(expandWidthPx) + Stroke.Alignment.Outside -> outline.rect.inflate(expandWidthPx + strokeWidthPx / 2f) + } + drawRect(brush, rect.topLeft, rect.size, style = DrawScopeStroke(strokeWidthPx)) } @@ -262,18 +254,17 @@ private fun ContentDrawScope.drawRoundedBorder( strokeWidthPx: Float, expandWidthPx: Float, ) { - val roundRect = - when (alignment) { - Stroke.Alignment.Inside -> outline.roundRect.grow(expandWidthPx - strokeWidthPx / 2f) - Stroke.Alignment.Center -> outline.roundRect.grow(expandWidthPx) - Stroke.Alignment.Outside -> outline.roundRect.grow(expandWidthPx + strokeWidthPx / 2f) - } + val roundRect = when (alignment) { + Stroke.Alignment.Inside -> outline.roundRect.grow(expandWidthPx - strokeWidthPx / 2f) + Stroke.Alignment.Center -> outline.roundRect.grow(expandWidthPx) + Stroke.Alignment.Outside -> outline.roundRect.grow(expandWidthPx + strokeWidthPx / 2f) + } if (roundRect.hasAtLeastOneNonRoundedCorner()) { // Note: why do we need this? The Outline API can handle it just fine val cache = borderCacheRef.obtain() - val borderPath = - cache.obtainPath().apply { + val borderPath = cache.obtainPath() + .apply { reset() fillType = PathFillType.EvenOdd addRoundRect(roundRect.shrink(strokeWidthPx / 2f)) @@ -281,11 +272,7 @@ private fun ContentDrawScope.drawRoundedBorder( } drawPath(borderPath, brush) } else { - drawOutline( - outline = Outline.Rounded(roundRect), - brush = brush, - style = DrawScopeStroke(strokeWidthPx), - ) + drawOutline(Outline.Rounded(roundRect), brush, style = DrawScopeStroke(strokeWidthPx)) } } @@ -304,27 +291,16 @@ private fun CacheDrawScope.drawGenericBorder( // needs to be drawn val (outer, inner) = when (alignment) { - Stroke.Alignment.Inside -> { - // Inside border means the outer border inflate delta is 0 - 0f + expandWidthPx to -strokeWidth + expandWidthPx - } - Stroke.Alignment.Center -> { - strokeWidth / 2f + expandWidthPx to -strokeWidth / 2f + expandWidthPx - } - Stroke.Alignment.Outside -> { - strokeWidth + expandWidthPx to 0f + expandWidthPx - } + // Inside border means the outer border inflate delta is 0 + Stroke.Alignment.Inside -> 0f + expandWidthPx to -strokeWidth + expandWidthPx + Stroke.Alignment.Center -> strokeWidth / 2f + expandWidthPx to -strokeWidth / 2f + expandWidthPx + Stroke.Alignment.Outside -> strokeWidth + expandWidthPx to 0f + expandWidthPx } - // Nothing need to draw when (outer) { - inner -> { - return@onDrawWithContent - } - -inner -> { - // Samply draw the outline when abs(outer) and abs(inner) are the same - drawOutline(outline, brush, style = DrawScopeStroke(outer * 2f)) - } + inner -> return@onDrawWithContent + // Simply draw the outline when abs(outer) and abs(inner) are the same + -inner -> drawOutline(outline, brush, style = DrawScopeStroke(outer * 2f)) else -> { val config: ImageBitmapConfig val colorFilter: ColorFilter? @@ -351,47 +327,46 @@ private fun CacheDrawScope.drawGenericBorder( ) with(borderCache) { - cacheImageBitmap = - drawBorderCache( - pathBoundsSize, - config, - ) { - translate(-pathBounds.left, -pathBounds.top) { - if (inner < 0f && outer > 0f) { - TODO("Not implemented for generic border") - } - - if (outer > 0f && inner >= 0f) { - drawPath(path = outline.path, brush = brush, style = DrawScopeStroke(outer * 2f)) + cacheImageBitmap = drawBorderCache( + pathBoundsSize, + config, + ) { + translate(-pathBounds.left, -pathBounds.top) { + if (inner < 0f && outer > 0f) { + TODO("Not implemented for generic border") + } - if (inner > 0f) { - drawPath( - path = outline.path, - brush = brush, - blendMode = BlendMode.Clear, - style = DrawScopeStroke(inner * 2f), - ) - } + if (outer > 0f && inner >= 0f) { + drawPath(outline.path, brush, style = DrawScopeStroke(outer * 2f)) - drawPath(path = outline.path, brush = brush, blendMode = BlendMode.Clear) + if (inner > 0f) { + drawPath( + path = outline.path, + brush = brush, + blendMode = BlendMode.Clear, + style = DrawScopeStroke(inner * 2f), + ) } - if (outer <= 0f && inner < 0f) { - drawPath(path = outline.path, brush = brush, style = DrawScopeStroke(-inner * 2f)) + drawPath(path = outline.path, brush = brush, blendMode = BlendMode.Clear) + } - if (outer < 0f) { - drawPath( - path = outline.path, - brush = brush, - blendMode = BlendMode.Clear, - style = DrawScopeStroke(-outer * 2f), - ) - } + if (outer <= 0f && inner < 0f) { + drawPath(path = outline.path, brush = brush, style = DrawScopeStroke(-inner * 2f)) - drawPath(path = outerMaskPath, brush = brush, blendMode = BlendMode.Clear) + if (outer < 0f) { + drawPath( + path = outline.path, + brush = brush, + blendMode = BlendMode.Clear, + style = DrawScopeStroke(-outer * 2f), + ) } + + drawPath(path = outerMaskPath, brush = brush, blendMode = BlendMode.Clear) } } + } } onDrawWithContent { diff --git a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/theme/JewelTheme.kt b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/theme/JewelTheme.kt index 0e2a726f7c..cbfd661fac 100644 --- a/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/theme/JewelTheme.kt +++ b/foundation/src/main/kotlin/org/jetbrains/jewel/foundation/theme/JewelTheme.kt @@ -17,27 +17,33 @@ public interface JewelTheme { public companion object { public val globalColors: GlobalColors - @Composable @ReadOnlyComposable + @Composable + @ReadOnlyComposable get() = LocalGlobalColors.current public val globalMetrics: GlobalMetrics - @Composable @ReadOnlyComposable + @Composable + @ReadOnlyComposable get() = LocalGlobalMetrics.current public val textStyle: TextStyle - @Composable @ReadOnlyComposable + @Composable + @ReadOnlyComposable get() = LocalTextStyle.current public val contentColor: Color - @Composable @ReadOnlyComposable + @Composable + @ReadOnlyComposable get() = LocalContentColor.current public val isDark: Boolean - @Composable @ReadOnlyComposable + @Composable + @ReadOnlyComposable get() = LocalIsDarkTheme.current public val isSwingCompatMode: Boolean - @Composable @ReadOnlyComposable + @Composable + @ReadOnlyComposable get() = LocalSwingCompatMode.current } } diff --git a/ide-laf-bridge/build.gradle.kts b/ide-laf-bridge/build.gradle.kts index b1f6d8f3b6..7b7556d015 100644 --- a/ide-laf-bridge/build.gradle.kts +++ b/ide-laf-bridge/build.gradle.kts @@ -9,7 +9,10 @@ plugins { } dependencies { - api(projects.ui) { exclude(group = "org.jetbrains.kotlinx") } + api(projects.ui) { + exclude(group = "org.jetbrains.kotlinx") + } + when (supportedIJVersion()) { IJ_232 -> { api(projects.ideLafBridge.ideLafBridge232) diff --git a/ide-laf-bridge/ide-laf-bridge-232/src/main/kotlin/org/jetbrains/jewel/bridge/BridgeIconData.kt b/ide-laf-bridge/ide-laf-bridge-232/src/main/kotlin/org/jetbrains/jewel/bridge/BridgeIconData.kt index e01708cbea..fb6627088b 100644 --- a/ide-laf-bridge/ide-laf-bridge-232/src/main/kotlin/org/jetbrains/jewel/bridge/BridgeIconData.kt +++ b/ide-laf-bridge/ide-laf-bridge-232/src/main/kotlin/org/jetbrains/jewel/bridge/BridgeIconData.kt @@ -9,8 +9,8 @@ import org.jetbrains.jewel.foundation.theme.ThemeIconData public fun ThemeIconData.Companion.readFromLaF(): ThemeIconData { val uiTheme = currentUiThemeOrNull() val iconMap = uiTheme?.icons.orEmpty() - val selectedIconColorPalette = - uiTheme?.selectedIconColorPalette.orEmpty().mapValues { ColorUtil.fromHex(it.value).rgb } + val selectedIconColorPalette = uiTheme?.selectedIconColorPalette.orEmpty() + .mapValues { ColorUtil.fromHex(it.value).rgb } val colorPalette = UITheme.getColorPalette() return ThemeIconData(iconMap, colorPalette, selectedIconColorPalette) diff --git a/ide-laf-bridge/ide-laf-bridge-232/src/main/kotlin/org/jetbrains/jewel/bridge/BridgePainterHintsProvider.kt b/ide-laf-bridge/ide-laf-bridge-232/src/main/kotlin/org/jetbrains/jewel/bridge/BridgePainterHintsProvider.kt index ce11f826b1..6f600491c7 100644 --- a/ide-laf-bridge/ide-laf-bridge-232/src/main/kotlin/org/jetbrains/jewel/bridge/BridgePainterHintsProvider.kt +++ b/ide-laf-bridge/ide-laf-bridge-232/src/main/kotlin/org/jetbrains/jewel/bridge/BridgePainterHintsProvider.kt @@ -13,19 +13,12 @@ import org.jetbrains.jewel.ui.painter.hints.HiDpi import org.jetbrains.jewel.ui.util.fromRGBAHexStringOrNull @InternalJewelApi -public class BridgePainterHintsProvider -private constructor( +public class BridgePainterHintsProvider private constructor( isDark: Boolean, intellijIconPalette: Map = emptyMap(), themeIconPalette: Map = emptyMap(), themeColorPalette: Map = emptyMap(), -) : - BasePainterHintsProvider( - isDark, - intellijIconPalette, - themeIconPalette, - themeColorPalette, - ) { +) : BasePainterHintsProvider(isDark, intellijIconPalette, themeIconPalette, themeColorPalette) { @Composable override fun hints(path: String): List = buildList { @@ -41,14 +34,12 @@ private constructor( public operator fun invoke(isDark: Boolean): BasePainterHintsProvider { val uiTheme = currentUiThemeOrNull() ?: return BridgePainterHintsProvider(isDark) - logger.info( - "Parsing theme info from theme ${uiTheme.name} (id: ${uiTheme.id}, isDark: ${uiTheme.isDark})", - ) + logger.info("Parsing theme info from theme ${uiTheme.name} (id: ${uiTheme.id}, isDark: ${uiTheme.isDark})") val iconColorPalette = uiTheme.iconColorPalette val keyPalette = UITheme.getColorPalette() - val themeColors = - uiTheme.colors.orEmpty().mapValues { (_, v) -> + val themeColors = uiTheme.colors.orEmpty() + .mapValues { (_, v) -> when (v) { is Int -> Color(v) is String -> Color.fromRGBAHexStringOrNull(v) diff --git a/ide-laf-bridge/ide-laf-bridge-232/src/main/kotlin/org/jetbrains/jewel/bridge/UiThemeExtensions.kt b/ide-laf-bridge/ide-laf-bridge-232/src/main/kotlin/org/jetbrains/jewel/bridge/UiThemeExtensions.kt index efa401102f..c4a75d91af 100644 --- a/ide-laf-bridge/ide-laf-bridge-232/src/main/kotlin/org/jetbrains/jewel/bridge/UiThemeExtensions.kt +++ b/ide-laf-bridge/ide-laf-bridge-232/src/main/kotlin/org/jetbrains/jewel/bridge/UiThemeExtensions.kt @@ -12,20 +12,18 @@ private val logger = Logger.getInstance("UiThemeExtensions") private val classUITheme get() = UITheme::class.java -@Suppress("UnstableApiUsage") @InternalJewelApi internal fun currentUiThemeOrNull() = (LafManager.getInstance().currentLookAndFeel as? UIThemeBasedLookAndFeelInfo)?.theme @InternalJewelApi public val UITheme.icons: Map - get() = - readMapField(classUITheme.getDeclaredField("icons")).filterKeys { it != "ColorPalette" } + get() = readMapField(classUITheme.getDeclaredField("icons")) + .filterKeys { it != "ColorPalette" } internal val UITheme.iconColorPalette: Map - get() = - readMapField>(classUITheme.getDeclaredField("icons"))["ColorPalette"] - .orEmpty() + get() = readMapField>(classUITheme.getDeclaredField("icons"))["ColorPalette"] + .orEmpty() internal val UITheme.selectedIconColorPalette: Map get() = readMapField(classUITheme.getDeclaredField("iconColorsOnSelection")) diff --git a/ide-laf-bridge/ide-laf-bridge-233/src/main/kotlin/org/jetbrains/jewel/bridge/BridgeOverride.kt b/ide-laf-bridge/ide-laf-bridge-233/src/main/kotlin/org/jetbrains/jewel/bridge/BridgeOverride.kt index dd6e5b1169..e6a9af4231 100644 --- a/ide-laf-bridge/ide-laf-bridge-233/src/main/kotlin/org/jetbrains/jewel/bridge/BridgeOverride.kt +++ b/ide-laf-bridge/ide-laf-bridge-233/src/main/kotlin/org/jetbrains/jewel/bridge/BridgeOverride.kt @@ -22,9 +22,8 @@ internal object BridgeOverride : PainterPathHint { val fallbackPath = path.removePrefix(dirProvider.dir()) for (classLoader in classLoaders) { - val patchedPath = - patchIconPath(path.removePrefix("/"), classLoader)?.first - ?: patchIconPath(fallbackPath, classLoader)?.first + val patchedPath = patchIconPath(path.removePrefix("/"), classLoader)?.first + ?: patchIconPath(fallbackPath, classLoader)?.first // 233 EAP 4 broke path patching horribly; now it can return a // "reflective path", which is a FQN to an ExpUIIcons entry. @@ -46,8 +45,7 @@ internal object BridgeOverride : PainterPathHint { return buildString { append("expui/") - iconPath - .split('.') + iconPath.split('.') .map { it.trim() } .filter { it.isNotEmpty() } .forEach { @@ -55,7 +53,7 @@ internal object BridgeOverride : PainterPathHint { append(it.drop(1)) append('/') } - replace(length - 1, length, "") + replace(length - 1, length, "") // Drop last '/' if (iconPath.contains("_dark")) append("_dark") append(".svg") diff --git a/ide-laf-bridge/ide-laf-bridge-233/src/main/kotlin/org/jetbrains/jewel/bridge/BridgePainterHintsProvider.kt b/ide-laf-bridge/ide-laf-bridge-233/src/main/kotlin/org/jetbrains/jewel/bridge/BridgePainterHintsProvider.kt index e8025ad119..d7fa143f7a 100644 --- a/ide-laf-bridge/ide-laf-bridge-233/src/main/kotlin/org/jetbrains/jewel/bridge/BridgePainterHintsProvider.kt +++ b/ide-laf-bridge/ide-laf-bridge-233/src/main/kotlin/org/jetbrains/jewel/bridge/BridgePainterHintsProvider.kt @@ -12,19 +12,12 @@ import org.jetbrains.jewel.ui.painter.hints.Dark import org.jetbrains.jewel.ui.painter.hints.HiDpi @InternalJewelApi -public class BridgePainterHintsProvider -private constructor( +class BridgePainterHintsProvider private constructor( isDark: Boolean, intellijIconPalette: Map = emptyMap(), themeIconPalette: Map = emptyMap(), themeColorPalette: Map = emptyMap(), -) : - BasePainterHintsProvider( - isDark, - intellijIconPalette, - themeIconPalette, - themeColorPalette, - ) { +) : BasePainterHintsProvider(isDark, intellijIconPalette, themeIconPalette, themeColorPalette) { @Composable override fun hints(path: String): List = buildList { @@ -34,15 +27,13 @@ private constructor( add(Dark(JewelTheme.isDark)) } - public companion object { + companion object { private val logger = thisLogger() - public operator fun invoke(isDark: Boolean): BasePainterHintsProvider { + operator fun invoke(isDark: Boolean): BasePainterHintsProvider { val uiTheme = currentUiThemeOrNull() ?: return BridgePainterHintsProvider(isDark) - logger.info( - "Parsing theme info from theme ${uiTheme.name} (id: ${uiTheme.id}, isDark: ${uiTheme.isDark})", - ) + logger.info("Parsing theme info from theme ${uiTheme.name} (id: ${uiTheme.id}, isDark: ${uiTheme.isDark})") val bean = uiTheme.describe() val iconColorPalette = diff --git a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/Bridge.kt b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/Bridge.kt index 35772925a9..96a2199d05 100644 --- a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/Bridge.kt +++ b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/Bridge.kt @@ -24,7 +24,9 @@ private val Application.lookAndFeelFlow: Flow internal fun Application.lookAndFeelChangedFlow( scope: CoroutineScope, sharingStarted: SharingStarted = SharingStarted.Eagerly, -): Flow = lookAndFeelFlow.onStart { emit(Unit) }.shareIn(scope, sharingStarted, replay = 1) +): Flow = + lookAndFeelFlow.onStart { emit(Unit) } + .shareIn(scope, sharingStarted, replay = 1) internal fun MessageBus.flow( topic: Topic, diff --git a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/BridgeResourceResolver.kt b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/BridgeResourceResolver.kt index ffe40d3b72..58918c1434 100644 --- a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/BridgeResourceResolver.kt +++ b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/BridgeResourceResolver.kt @@ -3,10 +3,9 @@ package org.jetbrains.jewel.bridge import com.intellij.util.ui.DirProvider import org.jetbrains.jewel.ui.painter.ResourcePainterProvider -/** [ResourcePainterProvider] to resolve resource in Intellij Module and Bridge module. */ +/** + * [ResourcePainterProvider] to resolve resource in Intellij Module and + * Bridge module. + */ public fun bridgePainterProvider(path: String): ResourcePainterProvider = - ResourcePainterProvider( - path, - DirProvider::class.java.classLoader, - SwingBridgeService::class.java.classLoader, - ) + ResourcePainterProvider(path, DirProvider::class.java.classLoader, SwingBridgeService::class.java.classLoader) diff --git a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/BridgeUtils.kt b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/BridgeUtils.kt index 40bd7d86d7..1340bd8851 100644 --- a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/BridgeUtils.kt +++ b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/BridgeUtils.kt @@ -100,8 +100,9 @@ public fun retrieveInsetsAsPaddingValues(key: String): PaddingValues = UIManager.getInsets(key)?.toPaddingValues() ?: keyNotFound(key, "Insets") /** - * Converts a [Insets] to [PaddingValues]. If the receiver is a [JBInsets] instance, this function - * delegates to the specific [toPaddingValues] for it, which is scaling-aware. + * Converts a [Insets] to [PaddingValues]. If the receiver is a [JBInsets] + * instance, this function delegates to the specific [toPaddingValues] for + * it, which is scaling-aware. */ public fun Insets.toPaddingValues(): PaddingValues = if (this is JBInsets) { @@ -111,22 +112,25 @@ public fun Insets.toPaddingValues(): PaddingValues = } /** - * Converts a [JBInsets] to [PaddingValues], in a scaling-aware way. This means that the resulting - * [PaddingValues] will be constructed from the [JBInsets.getUnscaled] values, treated as [Dp]. This - * avoids double scaling. + * Converts a [JBInsets] to [PaddingValues], in a scaling-aware way. This + * means that the resulting [PaddingValues] will be constructed from the + * [JBInsets.getUnscaled] values, treated as [Dp]. This avoids double + * scaling. */ public fun JBInsets.toPaddingValues(): PaddingValues = PaddingValues(unscaled.left.dp, unscaled.top.dp, unscaled.right.dp, unscaled.bottom.dp) /** - * Converts a [Dimension] to [DpSize]. If the receiver is a [JBDimension] instance, this function - * delegates to the specific [toDpSize] for it, which is scaling-aware. + * Converts a [Dimension] to [DpSize]. If the receiver is a [JBDimension] + * instance, this function delegates to the specific [toDpSize] for it, + * which is scaling-aware. */ public fun Dimension.toDpSize(): DpSize = DpSize(width.dp, height.dp) /** - * Converts a [JBDimension] to [DpSize], in a scaling-aware way. This means that the resulting - * [DpSize] will be constructed by first obtaining the unscaled values. This avoids double scaling. + * Converts a [JBDimension] to [DpSize], in a scaling-aware way. This means + * that the resulting [DpSize] will be constructed by first obtaining the + * unscaled values. This avoids double scaling. */ public fun JBDimension.toDpSize(): DpSize { val scaleFactor = scale(1f) @@ -173,25 +177,19 @@ public suspend fun retrieveTextStyle( fontStyle: FontStyle = FontStyle.Normal, size: TextUnit = TextUnit.Unspecified, ): TextStyle { - val font = - JBFont.create( - UIManager.getFont(key) ?: keyNotFound(key, "Font"), - false, - ) - - val derivedFont = - font - .let { if (bold) it.asBold() else it.asPlain() } - .let { if (fontStyle == FontStyle.Italic) it.asItalic() else it } - - val typeface = - derivedFont.toSkikoTypefaceOrNull(awtFontManager) - ?: Typeface.makeDefault().also { - logger.warn( - "Unable to convert font ${font.fontName} into a Skiko typeface, " + - "fallback to 'Typeface.makeDefault()'", - ) - } + val lafFont = UIManager.getFont(key) ?: keyNotFound(key, "Font") + val jbFont = JBFont.create(lafFont, false) + + val derivedFont = jbFont.let { if (bold) it.asBold() else it.asPlain() } + .let { if (fontStyle == FontStyle.Italic) it.asItalic() else it } + + val typeface = derivedFont.toSkikoTypefaceOrNull(awtFontManager) + ?: Typeface.makeDefault().also { + logger.warn( + "Unable to convert font ${jbFont.fontName} into a Skiko typeface, " + + "fallback to 'Typeface.makeDefault()'", + ) + } return TextStyle( color = color, @@ -206,9 +204,8 @@ public suspend fun retrieveTextStyle( @DependsOnJBR public fun Font.toFontFamily(): FontFamily { - val typeface = - runBlocking { toSkikoTypefaceOrNull(awtFontManager) } - ?: error("Can't turn $this into a Typeface") + val typeface = runBlocking { toSkikoTypefaceOrNull(awtFontManager) } + ?: error("Can't turn $this into a Typeface") return FontFamily(Typeface(typeface)) } diff --git a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/JewelBridgeException.kt b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/JewelBridgeException.kt index 6679c51dd1..3b5d6fa801 100644 --- a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/JewelBridgeException.kt +++ b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/JewelBridgeException.kt @@ -1,12 +1,9 @@ package org.jetbrains.jewel.bridge -public sealed class JewelBridgeException(override val message: String?) : - RuntimeException(message) { +public sealed class JewelBridgeException(override val message: String?) : RuntimeException(message) { public class KeyNotFoundException(key: String, type: String) : - JewelBridgeException( - "Key '$key' not found in Swing LaF, was expecting a value of type $type", - ) + JewelBridgeException("Key '$key' not found in Swing LaF, was expecting a value of type $type") public class KeysNotFoundException(keys: List, type: String) : JewelBridgeException( diff --git a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/actionSystem/DataProviderElement.kt b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/actionSystem/DataProviderElement.kt index 28813a6b5b..ffe2c6658d 100644 --- a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/actionSystem/DataProviderElement.kt +++ b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/actionSystem/DataProviderElement.kt @@ -2,8 +2,9 @@ package org.jetbrains.jewel.bridge.actionSystem import androidx.compose.ui.node.ModifierNodeElement -internal class DataProviderElement(val dataProvider: (dataId: String) -> Any?) : - ModifierNodeElement() { +internal class DataProviderElement( + val dataProvider: (dataId: String) -> Any?, +) : ModifierNodeElement() { override fun create(): DataProviderNode = DataProviderNode(dataProvider) diff --git a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/actionSystem/DataProviderNode.kt b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/actionSystem/DataProviderNode.kt index 54c7b24d49..09354e282c 100644 --- a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/actionSystem/DataProviderNode.kt +++ b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/actionSystem/DataProviderNode.kt @@ -9,15 +9,17 @@ import androidx.compose.ui.modifier.modifierLocalMapOf import androidx.compose.ui.modifier.modifierLocalOf /** - * Holder for parent node of current [DataProviderNode]. So, each [DataProviderNode] provides itself - * and read parent node. It allows building tree of [DataProviderNode] and traverse it later on. + * Holder for parent node of current [DataProviderNode]. So, each + * [DataProviderNode] provides itself and read parent node. It allows + * building tree of [DataProviderNode] and traverse it later on. * * @see ModifierLocalModifierNode */ private val LocalDataProviderNode = modifierLocalOf { null } -internal class DataProviderNode(var dataProvider: (dataId: String) -> Any?) : - Modifier.Node(), ModifierLocalModifierNode, FocusEventModifierNode { +internal class DataProviderNode( + var dataProvider: (dataId: String) -> Any?, +) : Modifier.Node(), ModifierLocalModifierNode, FocusEventModifierNode { // TODO: should we use state here and in parent with children for thread safety? Will it trigger // recompositions? diff --git a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/actionSystem/ProvideData.kt b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/actionSystem/ProvideData.kt index 389fcb1ed8..bdf0e1fc6c 100644 --- a/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/actionSystem/ProvideData.kt +++ b/ide-laf-bridge/src/main/kotlin/org/jetbrains/jewel/bridge/actionSystem/ProvideData.kt @@ -15,11 +15,13 @@ import org.jetbrains.annotations.VisibleForTesting import javax.swing.JComponent /** - * Layout composable that create the bridge between [Modifier.provideData] used inside [content] and - * [component]. So, IntelliJ's [DataManager] can use [component] as [DataProvider]. + * Layout composable that create the bridge between [Modifier.provideData] + * used inside [content] and [component]. So, IntelliJ's [DataManager] can + * use [component] as [DataProvider]. * - * When IntelliJ requests [getData] from [component] Compose will traverse [DataProviderNode] - * hierarchy and collect it according [DataProvider] rules (see javadoc). + * When IntelliJ requests [getData] from [component] Compose will traverse + * [DataProviderNode] hierarchy and collect it according [DataProvider] + * rules (see javadoc). */ // TODO: choose better naming? @Suppress("unused", "FunctionName") @@ -31,7 +33,9 @@ public fun ComponentDataProviderBridge( ) { val rootDataProviderModifier = remember { RootDataProviderModifier() } - Box(modifier = Modifier.then(rootDataProviderModifier).then(modifier)) { content() } + Box(modifier = Modifier.then(rootDataProviderModifier).then(modifier)) { + content() + } DisposableEffect(component) { DataManager.registerDataProvider(component, rootDataProviderModifier.dataProvider) @@ -43,11 +47,12 @@ public fun ComponentDataProviderBridge( /** * Configure component to provide data for IntelliJ Actions system. * - * Use this modifier to provide context related data that can be used by IntelliJ Actions - * functionality such as Search Everywhere, Action Popups etc. + * Use this modifier to provide context related data that can be used by + * IntelliJ Actions functionality such as Search Everywhere, Action Popups + * etc. * - * Important note: modifiers order is important, so be careful with order of [focusable] and - * [provideData] (see [FocusEventModifierNode]). + * Important note: modifiers order is important, so be careful with order + * of [focusable] and [provideData] (see [FocusEventModifierNode]). * * @see DataProvider * @see DataContext diff --git a/ide-laf-bridge/src/test/kotlin/org/jetbrains/jewel/bridge/actionSystem/ProvideDataTest.kt b/ide-laf-bridge/src/test/kotlin/org/jetbrains/jewel/bridge/actionSystem/ProvideDataTest.kt index 7d256d7287..cc2afeadeb 100644 --- a/ide-laf-bridge/src/test/kotlin/org/jetbrains/jewel/bridge/actionSystem/ProvideDataTest.kt +++ b/ide-laf-bridge/src/test/kotlin/org/jetbrains/jewel/bridge/actionSystem/ProvideDataTest.kt @@ -28,9 +28,7 @@ class ProvideDataTest { rule.setContent { focusManager = LocalFocusManager.current Box( - modifier = - Modifier.then(rootDataProviderModifier) - .testTag("provider") + modifier = rootDataProviderModifier.testTag("provider") .provideData { when (it) { "data" -> "ok" @@ -59,9 +57,7 @@ class ProvideDataTest { rule.setContent { focusManager = LocalFocusManager.current Box( - modifier = - Modifier.then(rootDataProviderModifier) - .testTag("root_provider") + modifier = rootDataProviderModifier.testTag("root_provider") .provideData { when (it) { "isRoot" -> "yes" diff --git a/int-ui/int-ui-decorated-window/src/main/kotlin/org/jetbrains/jewel/intui/window/IntUiDecoratedWindowResourceResolver.kt b/int-ui/int-ui-decorated-window/src/main/kotlin/org/jetbrains/jewel/intui/window/IntUiDecoratedWindowResourceResolver.kt index 4081d93e15..359dd64c5a 100644 --- a/int-ui/int-ui-decorated-window/src/main/kotlin/org/jetbrains/jewel/intui/window/IntUiDecoratedWindowResourceResolver.kt +++ b/int-ui/int-ui-decorated-window/src/main/kotlin/org/jetbrains/jewel/intui/window/IntUiDecoratedWindowResourceResolver.kt @@ -5,12 +5,8 @@ import org.jetbrains.jewel.ui.painter.ResourcePainterProvider import org.jetbrains.jewel.window.styling.DecoratedWindowStyle /** - * Create [PainterProvider][org.jetbrains.jewel.painter.PainterProvider] for decorated window module - * resource. + * Create a [PainterProvider][org.jetbrains.jewel.painter.PainterProvider] + * for loading a decorated window module resource. */ public fun decoratedWindowPainterProvider(path: String): ResourcePainterProvider = - ResourcePainterProvider( - path, - DecoratedWindowStyle::class.java.classLoader, - JewelTheme::class.java.classLoader, - ) + ResourcePainterProvider(path, DecoratedWindowStyle::class.java.classLoader, JewelTheme::class.java.classLoader) diff --git a/int-ui/int-ui-decorated-window/src/main/kotlin/org/jetbrains/jewel/intui/window/styling/IntUiTitleBarStyling.kt b/int-ui/int-ui-decorated-window/src/main/kotlin/org/jetbrains/jewel/intui/window/styling/IntUiTitleBarStyling.kt index b37d20874e..40befb1a16 100644 --- a/int-ui/int-ui-decorated-window/src/main/kotlin/org/jetbrains/jewel/intui/window/styling/IntUiTitleBarStyling.kt +++ b/int-ui/int-ui-decorated-window/src/main/kotlin/org/jetbrains/jewel/intui/window/styling/IntUiTitleBarStyling.kt @@ -37,10 +37,8 @@ public fun TitleBarStyle.Companion.light( colors = colors, metrics = metrics, icons = icons, - dropdownStyle = - DropdownStyle.Undecorated.dark( - colors = - DropdownColors.Undecorated.dark( + dropdownStyle = DropdownStyle.Undecorated.dark( + colors = DropdownColors.Undecorated.dark( content = colors.content, contentFocused = colors.content, contentHovered = colors.content, @@ -57,20 +55,17 @@ public fun TitleBarStyle.Companion.light( ), menuStyle = MenuStyle.light(), ), - iconButtonStyle = - titleBarIconButtonStyle( + iconButtonStyle = titleBarIconButtonStyle( colors.iconButtonHoveredBackground, colors.iconButtonPressedBackground, IconButtonMetrics.defaults(borderWidth = 0.dp), ), - paneButtonStyle = - titleBarIconButtonStyle( + paneButtonStyle = titleBarIconButtonStyle( colors.titlePaneButtonHoveredBackground, colors.titlePaneButtonPressedBackground, IconButtonMetrics.defaults(cornerSize = CornerSize(0.dp), borderWidth = 0.dp), ), - paneCloseButtonStyle = - titleBarIconButtonStyle( + paneCloseButtonStyle = titleBarIconButtonStyle( colors.titlePaneCloseButtonHoveredBackground, colors.titlePaneCloseButtonPressedBackground, IconButtonMetrics.defaults(cornerSize = CornerSize(0.dp), borderWidth = 0.dp), @@ -87,10 +82,8 @@ public fun TitleBarStyle.Companion.lightWithLightHeader( colors = colors, metrics = metrics, icons = icons, - dropdownStyle = - DropdownStyle.Undecorated.light( - colors = - DropdownColors.Undecorated.light( + dropdownStyle = DropdownStyle.Undecorated.light( + colors = DropdownColors.Undecorated.light( content = colors.content, contentFocused = colors.content, contentHovered = colors.content, @@ -106,20 +99,17 @@ public fun TitleBarStyle.Companion.lightWithLightHeader( contentPadding = PaddingValues(start = 10.dp, end = 0.dp, top = 3.dp, bottom = 3.dp), ), ), - iconButtonStyle = - titleBarIconButtonStyle( + iconButtonStyle = titleBarIconButtonStyle( colors.iconButtonHoveredBackground, colors.iconButtonPressedBackground, IconButtonMetrics.defaults(borderWidth = 0.dp), ), - paneButtonStyle = - titleBarIconButtonStyle( + paneButtonStyle = titleBarIconButtonStyle( colors.titlePaneButtonHoveredBackground, colors.titlePaneButtonPressedBackground, IconButtonMetrics.defaults(cornerSize = CornerSize(0.dp), borderWidth = 0.dp), ), - paneCloseButtonStyle = - titleBarIconButtonStyle( + paneCloseButtonStyle = titleBarIconButtonStyle( colors.titlePaneCloseButtonHoveredBackground, colors.titlePaneCloseButtonPressedBackground, IconButtonMetrics.defaults(cornerSize = CornerSize(0.dp), borderWidth = 0.dp), @@ -136,10 +126,8 @@ public fun TitleBarStyle.Companion.dark( colors = colors, metrics = metrics, icons = icons, - dropdownStyle = - DropdownStyle.Undecorated.dark( - colors = - DropdownColors.Undecorated.dark( + dropdownStyle = DropdownStyle.Undecorated.dark( + colors = DropdownColors.Undecorated.dark( content = colors.content, contentFocused = colors.content, contentHovered = colors.content, @@ -155,20 +143,17 @@ public fun TitleBarStyle.Companion.dark( contentPadding = PaddingValues(start = 10.dp, end = 0.dp, top = 3.dp, bottom = 3.dp), ), ), - iconButtonStyle = - titleBarIconButtonStyle( + iconButtonStyle = titleBarIconButtonStyle( colors.iconButtonHoveredBackground, colors.iconButtonPressedBackground, IconButtonMetrics.defaults(borderWidth = 0.dp), ), - paneButtonStyle = - titleBarIconButtonStyle( + paneButtonStyle = titleBarIconButtonStyle( colors.titlePaneButtonHoveredBackground, colors.titlePaneButtonPressedBackground, IconButtonMetrics.defaults(cornerSize = CornerSize(0.dp), borderWidth = 0.dp), ), - paneCloseButtonStyle = - titleBarIconButtonStyle( + paneCloseButtonStyle = titleBarIconButtonStyle( colors.titlePaneCloseButtonHoveredBackground, colors.titlePaneCloseButtonPressedBackground, IconButtonMetrics.defaults(cornerSize = CornerSize(0.dp), borderWidth = 0.dp), @@ -320,10 +305,8 @@ public fun TitleBarMetrics.Companion.defaults( ): TitleBarMetrics = TitleBarMetrics(height, gradientStartX, gradientEndX, titlePaneButtonSize) public fun TitleBarIcons.Companion.defaults( - minimizeButton: PainterProvider = - decoratedWindowPainterProvider("icons/intui/window/minimize.svg"), - maximizeButton: PainterProvider = - decoratedWindowPainterProvider("icons/intui/window/maximize.svg"), + minimizeButton: PainterProvider = decoratedWindowPainterProvider("icons/intui/window/minimize.svg"), + maximizeButton: PainterProvider = decoratedWindowPainterProvider("icons/intui/window/maximize.svg"), restoreButton: PainterProvider = decoratedWindowPainterProvider("icons/intui/window/restore.svg"), closeButton: PainterProvider = decoratedWindowPainterProvider("icons/intui/window/close.svg"), ): TitleBarIcons = TitleBarIcons(minimizeButton, maximizeButton, restoreButton, closeButton) diff --git a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/StandalonePainterHintsProvider.kt b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/StandalonePainterHintsProvider.kt index 3f7d8cb95f..052c067222 100644 --- a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/StandalonePainterHintsProvider.kt +++ b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/StandalonePainterHintsProvider.kt @@ -11,13 +11,12 @@ import org.jetbrains.jewel.ui.painter.hints.Override public class StandalonePainterHintsProvider( theme: ThemeDefinition, -) : - BasePainterHintsProvider( - theme.isDark, - intellijColorPalette, - theme.iconData.colorPalette, - theme.colorPalette.rawMap, - ) { +) : BasePainterHintsProvider( + theme.isDark, + intellijColorPalette, + theme.iconData.colorPalette, + theme.colorPalette.rawMap, +) { private val overrideHint: PainterHint = Override( diff --git a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiButtonStyling.kt b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiButtonStyling.kt index 8e86459b27..f6c4cdd759 100644 --- a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiButtonStyling.kt +++ b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiButtonStyling.kt @@ -42,13 +42,15 @@ public object IntUiOutlinedButtonStyleFactory { public fun light( colors: ButtonColors = ButtonColors.Outlined.light(), metrics: ButtonMetrics = ButtonMetrics.outlined(), - ): ButtonStyle = ButtonStyle(colors, metrics) + ): ButtonStyle = + ButtonStyle(colors, metrics) @Composable public fun dark( colors: ButtonColors = ButtonColors.Outlined.dark(), metrics: ButtonMetrics = ButtonMetrics.outlined(), - ): ButtonStyle = ButtonStyle(colors, metrics) + ): ButtonStyle = + ButtonStyle(colors, metrics) } public val ButtonColors.Companion.Default: IntUiDefaultButtonColorFactory @@ -212,11 +214,13 @@ public fun ButtonMetrics.Companion.default( padding: PaddingValues = PaddingValues(horizontal = 12.dp, vertical = 6.dp), minSize: DpSize = DpSize(72.dp, 28.dp), borderWidth: Dp = 0.dp, -): ButtonMetrics = ButtonMetrics(cornerSize, padding, minSize, borderWidth) +): ButtonMetrics = + ButtonMetrics(cornerSize, padding, minSize, borderWidth) public fun ButtonMetrics.Companion.outlined( cornerSize: CornerSize = CornerSize(4.dp), padding: PaddingValues = PaddingValues(horizontal = 12.dp, vertical = 6.dp), minSize: DpSize = DpSize(72.dp, 28.dp), borderWidth: Dp = 1.dp, -): ButtonMetrics = ButtonMetrics(cornerSize, padding, minSize, borderWidth) +): ButtonMetrics = + ButtonMetrics(cornerSize, padding, minSize, borderWidth) diff --git a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiCheckboxStyling.kt b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiCheckboxStyling.kt index 2727fd79e3..f4729f20fc 100644 --- a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiCheckboxStyling.kt +++ b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiCheckboxStyling.kt @@ -21,28 +21,32 @@ public fun CheckboxStyle.Companion.light( colors: CheckboxColors = CheckboxColors.light(), metrics: CheckboxMetrics = CheckboxMetrics.defaults(), icons: CheckboxIcons = CheckboxIcons.light(), -): CheckboxStyle = CheckboxStyle(colors, metrics, icons) +): CheckboxStyle = + CheckboxStyle(colors, metrics, icons) @Composable public fun CheckboxStyle.Companion.dark( colors: CheckboxColors = CheckboxColors.dark(), metrics: CheckboxMetrics = CheckboxMetrics.defaults(), icons: CheckboxIcons = CheckboxIcons.dark(), -): CheckboxStyle = CheckboxStyle(colors, metrics, icons) +): CheckboxStyle = + CheckboxStyle(colors, metrics, icons) @Composable public fun CheckboxColors.Companion.light( content: Color = Color.Unspecified, contentDisabled: Color = IntUiLightTheme.colors.grey(8), contentSelected: Color = content, -): CheckboxColors = CheckboxColors(content, contentDisabled, contentSelected) +): CheckboxColors = + CheckboxColors(content, contentDisabled, contentSelected) @Composable public fun CheckboxColors.Companion.dark( content: Color = Color.Unspecified, contentDisabled: Color = IntUiDarkTheme.colors.grey(7), contentSelected: Color = content, -): CheckboxColors = CheckboxColors(content, contentDisabled, contentSelected) +): CheckboxColors = + CheckboxColors(content, contentDisabled, contentSelected) public fun CheckboxMetrics.Companion.defaults( checkboxSize: DpSize = DpSize(19.dp, 19.dp), @@ -61,12 +65,12 @@ public fun CheckboxMetrics.Companion.defaults( @Composable public fun CheckboxIcons.Companion.light( - checkbox: PainterProvider = - standalonePainterProvider("com/intellij/ide/ui/laf/icons/intellij/checkBox.svg"), -): CheckboxIcons = CheckboxIcons(checkbox) + checkbox: PainterProvider = standalonePainterProvider("com/intellij/ide/ui/laf/icons/intellij/checkBox.svg"), +): CheckboxIcons = + CheckboxIcons(checkbox) @Composable public fun CheckboxIcons.Companion.dark( - checkbox: PainterProvider = - standalonePainterProvider("com/intellij/ide/ui/laf/icons/darcula/checkBox.svg"), -): CheckboxIcons = CheckboxIcons(checkbox) + checkbox: PainterProvider = standalonePainterProvider("com/intellij/ide/ui/laf/icons/darcula/checkBox.svg"), +): CheckboxIcons = + CheckboxIcons(checkbox) diff --git a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiChipStyling.kt b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiChipStyling.kt index 9bef42bfc4..54f57bf535 100644 --- a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiChipStyling.kt +++ b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiChipStyling.kt @@ -163,4 +163,5 @@ public fun ChipMetrics.Companion.defaults( padding: PaddingValues = PaddingValues(horizontal = 12.dp, vertical = 8.dp), borderWidth: Dp = 1.dp, borderWidthSelected: Dp = 2.dp, -): ChipMetrics = ChipMetrics(cornerSize, padding, borderWidth, borderWidthSelected) +): ChipMetrics = + ChipMetrics(cornerSize, padding, borderWidth, borderWidthSelected) diff --git a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiCircularProgressStyling.kt b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiCircularProgressStyling.kt index 15b29b78c1..81a1c4ab32 100644 --- a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiCircularProgressStyling.kt +++ b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiCircularProgressStyling.kt @@ -13,9 +13,11 @@ import kotlin.time.Duration.Companion.milliseconds public fun CircularProgressStyle.Companion.dark( frameTime: Duration = 125.milliseconds, color: Color = Color(0xFF6F737A), -): CircularProgressStyle = CircularProgressStyle(frameTime, color) +): CircularProgressStyle = + CircularProgressStyle(frameTime, color) public fun CircularProgressStyle.Companion.light( frameTime: Duration = 125.milliseconds, color: Color = Color(0xFFA8ADBD), -): CircularProgressStyle = CircularProgressStyle(frameTime, color) +): CircularProgressStyle = + CircularProgressStyle(frameTime, color) diff --git a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiDividerStyle.kt b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiDividerStyle.kt index 86d399036b..8702a39538 100644 --- a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiDividerStyle.kt +++ b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiDividerStyle.kt @@ -11,10 +11,12 @@ import org.jetbrains.jewel.ui.component.styling.DividerStyle public fun DividerStyle.Companion.light( color: Color = IntUiLightTheme.colors.grey(12), metrics: DividerMetrics = DividerMetrics.defaults(), -): DividerStyle = DividerStyle(color, metrics) +): DividerStyle = + DividerStyle(color, metrics) @Composable public fun DividerStyle.Companion.dark( color: Color = IntUiDarkTheme.colors.grey(1), metrics: DividerMetrics = DividerMetrics.defaults(), -): DividerStyle = DividerStyle(color, metrics) +): DividerStyle = + DividerStyle(color, metrics) diff --git a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiDropdownStyling.kt b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiDropdownStyling.kt index 11ba866019..dc600cfd7a 100644 --- a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiDropdownStyling.kt +++ b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiDropdownStyling.kt @@ -32,7 +32,8 @@ public object IntUiDefaultDropdownStyleFactory { icons: DropdownIcons = DropdownIcons.defaults(), textStyle: TextStyle = JewelTheme.defaultTextStyle, menuStyle: MenuStyle = MenuStyle.light(), - ): DropdownStyle = DropdownStyle(colors, metrics, icons, textStyle, menuStyle) + ): DropdownStyle = + DropdownStyle(colors, metrics, icons, textStyle, menuStyle) @Composable public fun dark( @@ -41,7 +42,8 @@ public object IntUiDefaultDropdownStyleFactory { icons: DropdownIcons = DropdownIcons.defaults(), textStyle: TextStyle = JewelTheme.defaultTextStyle, menuStyle: MenuStyle = MenuStyle.dark(), - ): DropdownStyle = DropdownStyle(colors, metrics, icons, textStyle, menuStyle) + ): DropdownStyle = + DropdownStyle(colors, metrics, icons, textStyle, menuStyle) } public val DropdownStyle.Companion.Undecorated: IntUiUndecoratedDropdownStyleFactory @@ -56,7 +58,8 @@ public object IntUiUndecoratedDropdownStyleFactory { icons: DropdownIcons = DropdownIcons.defaults(), textStyle: TextStyle = JewelTheme.defaultTextStyle, menuStyle: MenuStyle = MenuStyle.light(), - ): DropdownStyle = DropdownStyle(colors, metrics, icons, textStyle, menuStyle) + ): DropdownStyle = + DropdownStyle(colors, metrics, icons, textStyle, menuStyle) @Composable public fun dark( @@ -65,7 +68,8 @@ public object IntUiUndecoratedDropdownStyleFactory { icons: DropdownIcons = DropdownIcons.defaults(), textStyle: TextStyle = JewelTheme.defaultTextStyle, menuStyle: MenuStyle = MenuStyle.dark(), - ): DropdownStyle = DropdownStyle(colors, metrics, icons, textStyle, menuStyle) + ): DropdownStyle = + DropdownStyle(colors, metrics, icons, textStyle, menuStyle) } public val DropdownColors.Companion.Default: IntUiDefaultDropdownColorsFactory @@ -260,7 +264,8 @@ public fun DropdownMetrics.Companion.default( cornerSize: CornerSize = CornerSize(4.dp), contentPadding: PaddingValues = PaddingValues(horizontal = 6.dp, vertical = 3.dp), borderWidth: Dp = 1.dp, -): DropdownMetrics = DropdownMetrics(arrowMinSize, minSize, cornerSize, contentPadding, borderWidth) +): DropdownMetrics = + DropdownMetrics(arrowMinSize, minSize, cornerSize, contentPadding, borderWidth) public fun DropdownMetrics.Companion.undecorated( arrowMinSize: DpSize = DpSize((23 + 3).dp, 24.dp), @@ -268,8 +273,10 @@ public fun DropdownMetrics.Companion.undecorated( cornerSize: CornerSize = CornerSize(4.dp), contentPadding: PaddingValues = PaddingValues(horizontal = 6.dp, vertical = 3.dp), borderWidth: Dp = 0.dp, -): DropdownMetrics = DropdownMetrics(arrowMinSize, minSize, cornerSize, contentPadding, borderWidth) +): DropdownMetrics = + DropdownMetrics(arrowMinSize, minSize, cornerSize, contentPadding, borderWidth) public fun DropdownIcons.Companion.defaults( chevronDown: PainterProvider = standalonePainterProvider("expui/general/chevronDown.svg"), -): DropdownIcons = DropdownIcons(chevronDown) +): DropdownIcons = + DropdownIcons(chevronDown) diff --git a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiGroupHeaderStyling.kt b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiGroupHeaderStyling.kt index 51da7d925d..f5431e6e71 100644 --- a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiGroupHeaderStyling.kt +++ b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiGroupHeaderStyling.kt @@ -14,25 +14,30 @@ import org.jetbrains.jewel.ui.component.styling.GroupHeaderStyle public fun GroupHeaderStyle.Companion.light( colors: GroupHeaderColors = GroupHeaderColors.light(), metrics: GroupHeaderMetrics = GroupHeaderMetrics.defaults(), -): GroupHeaderStyle = GroupHeaderStyle(colors, metrics) +): GroupHeaderStyle = + GroupHeaderStyle(colors, metrics) @Composable public fun GroupHeaderStyle.Companion.dark( colors: GroupHeaderColors = GroupHeaderColors.dark(), metrics: GroupHeaderMetrics = GroupHeaderMetrics.defaults(), -): GroupHeaderStyle = GroupHeaderStyle(colors, metrics) +): GroupHeaderStyle = + GroupHeaderStyle(colors, metrics) @Composable public fun GroupHeaderColors.Companion.light( divider: Color = IntUiLightTheme.colors.grey(12), -): GroupHeaderColors = GroupHeaderColors(divider) +): GroupHeaderColors = + GroupHeaderColors(divider) @Composable public fun GroupHeaderColors.Companion.dark( divider: Color = IntUiDarkTheme.colors.grey(3), -): GroupHeaderColors = GroupHeaderColors(divider) +): GroupHeaderColors = + GroupHeaderColors(divider) public fun GroupHeaderMetrics.Companion.defaults( dividerThickness: Dp = 1.dp, indent: Dp = 8.dp, -): GroupHeaderMetrics = GroupHeaderMetrics(dividerThickness, indent) +): GroupHeaderMetrics = + GroupHeaderMetrics(dividerThickness, indent) diff --git a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiIconButtonStyling.kt b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiIconButtonStyling.kt index 5e09d392ec..4ecae089bd 100644 --- a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiIconButtonStyling.kt +++ b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiIconButtonStyling.kt @@ -17,13 +17,15 @@ import org.jetbrains.jewel.ui.component.styling.IconButtonStyle public fun IconButtonStyle.Companion.light( colors: IconButtonColors = IconButtonColors.light(), metrics: IconButtonMetrics = IconButtonMetrics.defaults(), -): IconButtonStyle = IconButtonStyle(colors, metrics) +): IconButtonStyle = + IconButtonStyle(colors, metrics) @Composable public fun IconButtonStyle.Companion.dark( colors: IconButtonColors = IconButtonColors.dark(), metrics: IconButtonMetrics = IconButtonMetrics.defaults(), -): IconButtonStyle = IconButtonStyle(colors, metrics) +): IconButtonStyle = + IconButtonStyle(colors, metrics) @Composable public fun IconButtonColors.Companion.light( @@ -102,4 +104,5 @@ public fun IconButtonMetrics.Companion.defaults( borderWidth: Dp = 1.dp, padding: PaddingValues = PaddingValues(0.dp), minSize: DpSize = DpSize(16.dp, 16.dp), -): IconButtonMetrics = IconButtonMetrics(cornerSize, borderWidth, padding, minSize) +): IconButtonMetrics = + IconButtonMetrics(cornerSize, borderWidth, padding, minSize) diff --git a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiLazyTreeStyling.kt b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiLazyTreeStyling.kt index 46f31a809f..2a44e456db 100644 --- a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiLazyTreeStyling.kt +++ b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiLazyTreeStyling.kt @@ -20,14 +20,16 @@ public fun LazyTreeStyle.Companion.light( colors: LazyTreeColors = LazyTreeColors.light(), metrics: LazyTreeMetrics = LazyTreeMetrics.defaults(), icons: LazyTreeIcons = LazyTreeIcons.defaults(), -): LazyTreeStyle = LazyTreeStyle(colors, metrics, icons) +): LazyTreeStyle = + LazyTreeStyle(colors, metrics, icons) @Composable public fun LazyTreeStyle.Companion.dark( colors: LazyTreeColors = LazyTreeColors.dark(), metrics: LazyTreeMetrics = LazyTreeMetrics.defaults(), icons: LazyTreeIcons = LazyTreeIcons.defaults(), -): LazyTreeStyle = LazyTreeStyle(colors, metrics, icons) +): LazyTreeStyle = + LazyTreeStyle(colors, metrics, icons) @Composable public fun LazyTreeColors.Companion.light( diff --git a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiLinkStyling.kt b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiLinkStyling.kt index 4af39b975d..4e06d48fef 100644 --- a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiLinkStyling.kt +++ b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiLinkStyling.kt @@ -26,7 +26,8 @@ public fun LinkStyle.Companion.light( metrics: LinkMetrics = LinkMetrics.defaults(), icons: LinkIcons = LinkIcons.defaults(), textStyles: LinkTextStyles = LinkTextStyles.light(), -): LinkStyle = LinkStyle(colors, metrics, icons, textStyles) +): LinkStyle = + LinkStyle(colors, metrics, icons, textStyles) @Composable public fun LinkStyle.Companion.dark( @@ -34,7 +35,8 @@ public fun LinkStyle.Companion.dark( metrics: LinkMetrics = LinkMetrics.defaults(), icons: LinkIcons = LinkIcons.defaults(), textStyles: LinkTextStyles = LinkTextStyles.dark(), -): LinkStyle = LinkStyle(colors, metrics, icons, textStyles) +): LinkStyle = + LinkStyle(colors, metrics, icons, textStyles) @Composable public fun LinkColors.Companion.light( @@ -76,12 +78,14 @@ 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) +): LinkMetrics = + LinkMetrics(focusHaloCornerSize, textIconGap, iconSize) public fun LinkIcons.Companion.defaults( dropdownChevron: PainterProvider = standalonePainterProvider("expui/general/chevronDown.svg"), externalLink: PainterProvider = standalonePainterProvider("expui/ide/externalLink.svg"), -): LinkIcons = LinkIcons(dropdownChevron, externalLink) +): LinkIcons = + LinkIcons(dropdownChevron, externalLink) @Composable public fun LinkTextStyles.Companion.light( @@ -91,7 +95,8 @@ public fun LinkTextStyles.Companion.light( pressed: TextStyle = normal, hovered: TextStyle = normal, visited: TextStyle = normal, -): LinkTextStyles = LinkTextStyles(normal, disabled, focused, pressed, hovered, visited) +): LinkTextStyles = + LinkTextStyles(normal, disabled, focused, pressed, hovered, visited) @Composable public fun LinkTextStyles.Companion.dark( @@ -101,4 +106,5 @@ public fun LinkTextStyles.Companion.dark( pressed: TextStyle = normal, hovered: TextStyle = normal, visited: TextStyle = normal, -): LinkTextStyles = LinkTextStyles(normal, disabled, focused, pressed, hovered, visited) +): LinkTextStyles = + LinkTextStyles(normal, disabled, focused, pressed, hovered, visited) diff --git a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiMenuStyling.kt b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiMenuStyling.kt index 3ab4654d2a..2eac84e45c 100644 --- a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiMenuStyling.kt +++ b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiMenuStyling.kt @@ -25,12 +25,7 @@ public fun MenuStyle.Companion.light( metrics: MenuMetrics = MenuMetrics.defaults(), icons: MenuIcons = MenuIcons.defaults(), ): MenuStyle = - MenuStyle( - isDark = false, - colors = colors, - metrics = metrics, - icons = icons, - ) + MenuStyle(isDark = false, colors, metrics, icons) @Composable public fun MenuStyle.Companion.dark( @@ -38,12 +33,7 @@ public fun MenuStyle.Companion.dark( metrics: MenuMetrics = MenuMetrics.defaults(), icons: MenuIcons = MenuIcons.defaults(), ): MenuStyle = - MenuStyle( - isDark = true, - colors = colors, - metrics = metrics, - icons = icons, - ) + MenuStyle(isDark = true, colors, metrics, icons) @Composable public fun MenuColors.Companion.light( @@ -187,8 +177,10 @@ public fun MenuItemMetrics.Companion.defaults( public fun SubmenuMetrics.Companion.defaults( offset: DpOffset = DpOffset(0.dp, (-8).dp), -): SubmenuMetrics = SubmenuMetrics(offset) +): SubmenuMetrics = + SubmenuMetrics(offset) public fun MenuIcons.Companion.defaults( submenuChevron: PainterProvider = standalonePainterProvider("expui/general/chevronRight.svg"), -): MenuIcons = MenuIcons(submenuChevron) +): MenuIcons = + MenuIcons(submenuChevron) diff --git a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiRadioButtonStyling.kt b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiRadioButtonStyling.kt index 8f7bc604c0..0f683234ce 100644 --- a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiRadioButtonStyling.kt +++ b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiRadioButtonStyling.kt @@ -19,14 +19,16 @@ public fun RadioButtonStyle.Companion.light( colors: RadioButtonColors = RadioButtonColors.light(), metrics: RadioButtonMetrics = RadioButtonMetrics.defaults(), icons: RadioButtonIcons = RadioButtonIcons.light(), -): RadioButtonStyle = RadioButtonStyle(colors, metrics, icons) +): RadioButtonStyle = + RadioButtonStyle(colors, metrics, icons) @Composable public fun RadioButtonStyle.Companion.dark( colors: RadioButtonColors = RadioButtonColors.dark(), metrics: RadioButtonMetrics = RadioButtonMetrics.defaults(), icons: RadioButtonIcons = RadioButtonIcons.dark(), -): RadioButtonStyle = RadioButtonStyle(colors, metrics, icons) +): RadioButtonStyle = + RadioButtonStyle(colors, metrics, icons) @Composable public fun RadioButtonColors.Companion.light( @@ -67,14 +69,17 @@ public fun RadioButtonColors.Companion.dark( public fun RadioButtonMetrics.Companion.defaults( radioButtonSize: DpSize = DpSize(19.dp, 19.dp), iconContentGap: Dp = 8.dp, -): RadioButtonMetrics = RadioButtonMetrics(radioButtonSize, iconContentGap) +): RadioButtonMetrics = + RadioButtonMetrics(radioButtonSize, iconContentGap) public fun RadioButtonIcons.Companion.light( radioButton: PainterProvider = standalonePainterProvider("com/intellij/ide/ui/laf/icons/intellij/radio.svg"), -): RadioButtonIcons = RadioButtonIcons(radioButton) +): RadioButtonIcons = + RadioButtonIcons(radioButton) public fun RadioButtonIcons.Companion.dark( radioButton: PainterProvider = standalonePainterProvider("com/intellij/ide/ui/laf/icons/darcula/radio.svg"), -): RadioButtonIcons = RadioButtonIcons(radioButton) +): RadioButtonIcons = + RadioButtonIcons(radioButton) diff --git a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiScrollbarStyling.kt b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiScrollbarStyling.kt index acfef18922..f55ccf83c9 100644 --- a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiScrollbarStyling.kt +++ b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiScrollbarStyling.kt @@ -17,26 +17,30 @@ public fun ScrollbarStyle.Companion.light( colors: ScrollbarColors = ScrollbarColors.light(), metrics: ScrollbarMetrics = ScrollbarMetrics.defaults(), hoverDuration: Duration = 300.milliseconds, -): ScrollbarStyle = ScrollbarStyle(colors, metrics, hoverDuration) +): ScrollbarStyle = + ScrollbarStyle(colors, metrics, hoverDuration) @Composable public fun ScrollbarStyle.Companion.dark( colors: ScrollbarColors = ScrollbarColors.dark(), metrics: ScrollbarMetrics = ScrollbarMetrics.defaults(), hoverDuration: Duration = 300.milliseconds, -): ScrollbarStyle = ScrollbarStyle(colors, metrics, hoverDuration) +): ScrollbarStyle = + ScrollbarStyle(colors, metrics, hoverDuration) @Composable public fun ScrollbarColors.Companion.light( thumbBackground: Color = Color(0x33000000), thumbBackgroundHovered: Color = Color(0x80000000), -): ScrollbarColors = ScrollbarColors(thumbBackground, thumbBackgroundHovered) +): ScrollbarColors = + ScrollbarColors(thumbBackground, thumbBackgroundHovered) @Composable public fun ScrollbarColors.Companion.dark( thumbBackground: Color = Color(0x59808080), thumbBackgroundHovered: Color = Color(0x8C808080), -): ScrollbarColors = ScrollbarColors(thumbBackground, thumbBackgroundHovered) +): ScrollbarColors = + ScrollbarColors(thumbBackground, thumbBackgroundHovered) public fun ScrollbarMetrics.Companion.defaults( thumbCornerSize: CornerSize = CornerSize(100), diff --git a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiTabStyling.kt b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiTabStyling.kt index 0f5e3143bb..c7e2b4cad2 100644 --- a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiTabStyling.kt +++ b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiTabStyling.kt @@ -26,7 +26,8 @@ public object IntUiDefaultTabStyleFactory { metrics: TabMetrics = TabMetrics.defaults(), icons: TabIcons = TabIcons.defaults(), contentAlpha: TabContentAlpha = TabContentAlpha.default(), - ): TabStyle = TabStyle(colors, metrics, icons, contentAlpha) + ): TabStyle = + TabStyle(colors, metrics, icons, contentAlpha) @Composable public fun dark( @@ -34,7 +35,8 @@ public object IntUiDefaultTabStyleFactory { metrics: TabMetrics = TabMetrics.defaults(), icons: TabIcons = TabIcons.defaults(), contentAlpha: TabContentAlpha = TabContentAlpha.default(), - ): TabStyle = TabStyle(colors, metrics, icons, contentAlpha) + ): TabStyle = + TabStyle(colors, metrics, icons, contentAlpha) } public val TabStyle.Companion.Editor: IntUiEditorTabStyleFactory @@ -48,7 +50,8 @@ public object IntUiEditorTabStyleFactory { metrics: TabMetrics = TabMetrics.defaults(), icons: TabIcons = TabIcons.defaults(), contentAlpha: TabContentAlpha = TabContentAlpha.editor(), - ): TabStyle = TabStyle(colors, metrics, icons, contentAlpha) + ): TabStyle = + TabStyle(colors, metrics, icons, contentAlpha) @Composable public fun dark( @@ -56,7 +59,8 @@ public object IntUiEditorTabStyleFactory { metrics: TabMetrics = TabMetrics.defaults(), icons: TabIcons = TabIcons.defaults(), contentAlpha: TabContentAlpha = TabContentAlpha.editor(), - ): TabStyle = TabStyle(colors, metrics, icons, contentAlpha) + ): TabStyle = + TabStyle(colors, metrics, icons, contentAlpha) } public val TabColors.Companion.Default: IntUiDefaultTabColorsFactory @@ -216,7 +220,8 @@ public fun TabMetrics.Companion.defaults( tabPadding: PaddingValues = PaddingValues(horizontal = 8.dp), closeContentGap: Dp = 8.dp, tabHeight: Dp = 40.dp, -): TabMetrics = TabMetrics(underlineThickness, tabPadding, tabHeight, closeContentGap) +): TabMetrics = + TabMetrics(underlineThickness, tabPadding, tabHeight, closeContentGap) public fun TabContentAlpha.Companion.default( iconNormal: Float = 1f, @@ -270,4 +275,5 @@ public fun TabContentAlpha.Companion.editor( public fun TabIcons.Companion.defaults( close: PainterProvider = standalonePainterProvider("expui/general/closeSmall.svg"), -): TabIcons = TabIcons(close) +): TabIcons = + TabIcons(close) diff --git a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiTextAreaStyling.kt b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiTextAreaStyling.kt index 019166db8c..77bdeaeec9 100644 --- a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiTextAreaStyling.kt +++ b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiTextAreaStyling.kt @@ -21,14 +21,16 @@ public fun TextAreaStyle.Companion.light( colors: TextAreaColors = TextAreaColors.light(), metrics: TextAreaMetrics = TextAreaMetrics.defaults(), textStyle: TextStyle = JewelTheme.defaultTextStyle, -): TextAreaStyle = TextAreaStyle(colors, metrics, textStyle) +): TextAreaStyle = + TextAreaStyle(colors, metrics, textStyle) @Composable public fun TextAreaStyle.Companion.dark( colors: TextAreaColors = TextAreaColors.dark(), metrics: TextAreaMetrics = TextAreaMetrics.defaults(), textStyle: TextStyle = JewelTheme.defaultTextStyle, -): TextAreaStyle = TextAreaStyle(colors, metrics, textStyle) +): TextAreaStyle = + TextAreaStyle(colors, metrics, textStyle) @Composable public fun TextAreaColors.Companion.light( @@ -131,4 +133,5 @@ public fun TextAreaMetrics.Companion.defaults( contentPadding: PaddingValues = PaddingValues(horizontal = 6.dp, vertical = 2.dp), minSize: DpSize = DpSize(144.dp, 28.dp), borderWidth: Dp = 1.dp, -): TextAreaMetrics = TextAreaMetrics(borderWidth, contentPadding, cornerSize, minSize) +): TextAreaMetrics = + TextAreaMetrics(borderWidth, contentPadding, cornerSize, minSize) diff --git a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiTextFieldStyling.kt b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiTextFieldStyling.kt index 79af8918aa..7939f3c811 100644 --- a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiTextFieldStyling.kt +++ b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiTextFieldStyling.kt @@ -21,14 +21,16 @@ public fun TextFieldStyle.Companion.light( colors: TextFieldColors = TextFieldColors.light(), metrics: TextFieldMetrics = TextFieldMetrics.defaults(), textStyle: TextStyle = JewelTheme.defaultTextStyle, -): TextFieldStyle = TextFieldStyle(colors, metrics, textStyle) +): TextFieldStyle = + TextFieldStyle(colors, metrics, textStyle) @Composable public fun TextFieldStyle.Companion.dark( colors: TextFieldColors = TextFieldColors.dark(), metrics: TextFieldMetrics = TextFieldMetrics.defaults(), textStyle: TextStyle = JewelTheme.defaultTextStyle, -): TextFieldStyle = TextFieldStyle(colors, metrics, textStyle) +): TextFieldStyle = + TextFieldStyle(colors, metrics, textStyle) @Composable public fun TextFieldColors.Companion.light( @@ -131,4 +133,5 @@ public fun TextFieldMetrics.Companion.defaults( contentPadding: PaddingValues = PaddingValues(horizontal = 9.dp, vertical = 6.dp), minSize: DpSize = DpSize(144.dp, 28.dp), borderWidth: Dp = 1.dp, -): TextFieldMetrics = TextFieldMetrics(borderWidth, contentPadding, cornerSize, minSize) +): TextFieldMetrics = + TextFieldMetrics(borderWidth, contentPadding, cornerSize, minSize) diff --git a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiTooltipStyling.kt b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiTooltipStyling.kt index f4d7785fbf..41b56f8a39 100644 --- a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiTooltipStyling.kt +++ b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/styling/IntUiTooltipStyling.kt @@ -34,7 +34,8 @@ public fun TooltipColors.Companion.light( contentColor: Color = IntUiLightTheme.colors.grey(12), borderColor: Color = backgroundColor, shadow: Color = Color(0x78919191), // Not a palette color -): TooltipColors = TooltipColors(backgroundColor, contentColor, borderColor, shadow) +): TooltipColors = + TooltipColors(backgroundColor, contentColor, borderColor, shadow) @Composable public fun TooltipColors.Companion.dark( @@ -42,4 +43,5 @@ public fun TooltipColors.Companion.dark( contentColor: Color = IntUiDarkTheme.colors.grey(12), borderColor: Color = IntUiDarkTheme.colors.grey(3), shadow: Color = Color(0x66000000), // Not a palette color -): TooltipColors = TooltipColors(backgroundColor, contentColor, borderColor, shadow) +): TooltipColors = + TooltipColors(backgroundColor, contentColor, borderColor, shadow) diff --git a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/theme/IntUiGlobalColors.kt b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/theme/IntUiGlobalColors.kt index 9402f33edb..00674a2d3d 100644 --- a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/theme/IntUiGlobalColors.kt +++ b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/theme/IntUiGlobalColors.kt @@ -41,14 +41,16 @@ public fun BorderColors.Companion.light( normal: Color = IntUiLightTheme.colors.grey(9), focused: Color = IntUiLightTheme.colors.grey(14), disabled: Color = IntUiLightTheme.colors.grey(11), -): BorderColors = BorderColors(normal, focused, disabled) +): BorderColors = + BorderColors(normal, focused, disabled) @Composable public fun BorderColors.Companion.dark( normal: Color = IntUiDarkTheme.colors.grey(5), focused: Color = IntUiDarkTheme.colors.grey(2), disabled: Color = IntUiDarkTheme.colors.grey(4), -): BorderColors = BorderColors(normal, focused, disabled) +): BorderColors = + BorderColors(normal, focused, disabled) @Composable public fun OutlineColors.Companion.light( @@ -57,7 +59,8 @@ public fun OutlineColors.Companion.light( focusedError: Color = IntUiLightTheme.colors.red(4), warning: Color = IntUiLightTheme.colors.yellow(7), error: Color = IntUiLightTheme.colors.red(9), -): OutlineColors = OutlineColors(focused, focusedWarning, focusedError, warning, error) +): OutlineColors = + OutlineColors(focused, focusedWarning, focusedError, warning, error) @Composable public fun OutlineColors.Companion.dark( @@ -66,4 +69,5 @@ public fun OutlineColors.Companion.dark( focusedError: Color = IntUiDarkTheme.colors.red(4), warning: Color = IntUiDarkTheme.colors.yellow(2), error: Color = IntUiDarkTheme.colors.red(2), -): OutlineColors = OutlineColors(focused, focusedWarning, focusedError, warning, error) +): OutlineColors = + OutlineColors(focused, focusedWarning, focusedError, warning, error) diff --git a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/theme/IntUiGlobalMetrics.kt b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/theme/IntUiGlobalMetrics.kt index e2ed3b49db..8b009b8aa6 100644 --- a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/theme/IntUiGlobalMetrics.kt +++ b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/theme/IntUiGlobalMetrics.kt @@ -7,4 +7,5 @@ import org.jetbrains.jewel.foundation.GlobalMetrics public fun GlobalMetrics.Companion.defaults( outlineWidth: Dp = 2.dp, rowHeight: Dp = 24.dp, -): GlobalMetrics = GlobalMetrics(outlineWidth, rowHeight) +): GlobalMetrics = + GlobalMetrics(outlineWidth, rowHeight) diff --git a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/theme/IntUiTheme.kt b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/theme/IntUiTheme.kt index 3fdde63d05..554ed00ff6 100644 --- a/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/theme/IntUiTheme.kt +++ b/int-ui/int-ui-standalone/src/main/kotlin/org/jetbrains/jewel/intui/standalone/theme/IntUiTheme.kt @@ -48,13 +48,12 @@ import org.jetbrains.jewel.ui.painter.LocalPainterHintsProvider import org.jetbrains.jewel.ui.theme.BaseJewelTheme public val JewelTheme.Companion.defaultTextStyle: TextStyle - get() = - TextStyle.Default.copy( - fontFamily = FontFamily.Inter, - fontSize = 13.sp, - fontWeight = FontWeight.Normal, - fontStyle = FontStyle.Normal, - ) + get() = TextStyle.Default.copy( + fontFamily = FontFamily.Inter, + fontSize = 13.sp, + fontWeight = FontWeight.Normal, + fontStyle = FontStyle.Normal, + ) @Composable public fun JewelTheme.Companion.lightThemeDefinition( @@ -65,15 +64,7 @@ public fun JewelTheme.Companion.lightThemeDefinition( defaultTextStyle: TextStyle = JewelTheme.defaultTextStyle, contentColor: Color = IntUiLightTheme.colors.grey(1), ): ThemeDefinition = - ThemeDefinition( - isDark = false, - colors, - metrics, - defaultTextStyle, - contentColor, - palette, - iconData, - ) + ThemeDefinition(isDark = false, colors, metrics, defaultTextStyle, contentColor, palette, iconData) @Composable public fun JewelTheme.Companion.darkThemeDefinition( @@ -199,11 +190,7 @@ public fun IntUiTheme( content: @Composable () -> Unit, ) { val themeDefinition = - if (isDark) { - JewelTheme.darkThemeDefinition() - } else { - JewelTheme.lightThemeDefinition() - } + if (isDark) JewelTheme.darkThemeDefinition() else JewelTheme.lightThemeDefinition() IntUiTheme( theme = themeDefinition, diff --git a/ui/api/ui.api b/ui/api/ui.api index 05dd098912..79404619ba 100644 --- a/ui/api/ui.api +++ b/ui/api/ui.api @@ -595,6 +595,7 @@ public final class org/jetbrains/jewel/ui/component/TabData$Default : org/jetbra public fun getOnClose ()Lkotlin/jvm/functions/Function0; public fun getSelected ()Z public fun hashCode ()I + public fun toString ()Ljava/lang/String; } public final class org/jetbrains/jewel/ui/component/TabData$Editor : org/jetbrains/jewel/ui/component/TabData { @@ -609,6 +610,7 @@ public final class org/jetbrains/jewel/ui/component/TabData$Editor : org/jetbrai public fun getOnClose ()Lkotlin/jvm/functions/Function0; public fun getSelected ()Z public fun hashCode ()I + public fun toString ()Ljava/lang/String; } public final class org/jetbrains/jewel/ui/component/TabState : org/jetbrains/jewel/foundation/state/SelectableComponentState { @@ -2229,24 +2231,6 @@ public final class org/jetbrains/jewel/ui/util/DebugKt { } public final class org/jetbrains/jewel/ui/util/ModifierExtensionsKt { - public static final fun appendIf (Landroidx/compose/ui/Modifier;ZLkotlin/jvm/functions/Function1;)Landroidx/compose/ui/Modifier; public static final fun thenIf (Landroidx/compose/ui/Modifier;ZLkotlin/jvm/functions/Function1;)Landroidx/compose/ui/Modifier; } -public final class org/jetbrains/jewel/ui/util/SpinnerProgressIconGenerator { - public static final field $stable I - public static final field INSTANCE Lorg/jetbrains/jewel/ui/util/SpinnerProgressIconGenerator; -} - -public final class org/jetbrains/jewel/ui/util/SpinnerProgressIconGenerator$Big { - public static final field $stable I - public static final field INSTANCE Lorg/jetbrains/jewel/ui/util/SpinnerProgressIconGenerator$Big; - public final fun generateRawSvg (Ljava/lang/String;)Ljava/util/List; -} - -public final class org/jetbrains/jewel/ui/util/SpinnerProgressIconGenerator$Small { - public static final field $stable I - public static final field INSTANCE Lorg/jetbrains/jewel/ui/util/SpinnerProgressIconGenerator$Small; - public final fun generateRawSvg (Ljava/lang/String;)Ljava/util/List; -} - diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Button.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Button.kt index 9d0dcb9945..235ae3919f 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Button.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Button.kt @@ -17,7 +17,6 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.Immutable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.Stable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -120,8 +119,7 @@ private fun ButtonImpl( val borderColor by colors.borderFor(buttonState) Box( - modifier = - modifier + modifier = modifier .clickable( onClick = onClick, enabled = enabled, @@ -155,23 +153,18 @@ private fun ButtonImpl( @JvmInline public value class ButtonState(public val state: ULong) : FocusableComponentState { - @Stable override val isActive: Boolean get() = state and Active != 0UL - @Stable override val isEnabled: Boolean get() = state and Enabled != 0UL - @Stable override val isFocused: Boolean get() = state and Focused != 0UL - @Stable override val isHovered: Boolean get() = state and Hovered != 0UL - @Stable override val isPressed: Boolean get() = state and Pressed != 0UL diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Checkbox.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Checkbox.kt index f8e2dba5ff..2b364f7e2b 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Checkbox.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Checkbox.kt @@ -17,7 +17,6 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.Immutable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.Stable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -247,8 +246,10 @@ private fun CheckboxImpl( textStyle: TextStyle, content: (@Composable RowScope.() -> Unit)?, ) { - var checkboxState by - remember(interactionSource) { mutableStateOf(CheckboxState.of(state, enabled = enabled)) } + var checkboxState by remember(interactionSource) { + mutableStateOf(CheckboxState.of(state, enabled = enabled)) + } + remember(state, enabled) { checkboxState = checkboxState.copy(toggleableState = state, enabled = enabled) } @@ -283,27 +284,25 @@ private fun CheckboxImpl( ) val checkBoxImageModifier = Modifier.size(metrics.checkboxSize) - val outlineModifier = - Modifier.size(metrics.outlineSize) - .offset(metrics.outlineOffset.x, metrics.outlineOffset.y) - .outline( - state = checkboxState, - outline = outline, - outlineShape = RoundedCornerShape(metrics.checkboxCornerSize), - alignment = Stroke.Alignment.Center, - ) - - val checkboxPainter by - icons.checkbox.getPainter( - if (checkboxState.toggleableState == ToggleableState.Indeterminate) { - CheckBoxIndeterminate - } else { - PainterHint.None - }, - Selected(checkboxState), - Stateful(checkboxState), + val outlineModifier = Modifier.size(metrics.outlineSize) + .offset(metrics.outlineOffset.x, metrics.outlineOffset.y) + .outline( + state = checkboxState, + outline = outline, + outlineShape = RoundedCornerShape(metrics.checkboxCornerSize), + alignment = Stroke.Alignment.Center, ) + val checkboxPainter by icons.checkbox.getPainter( + if (checkboxState.toggleableState == ToggleableState.Indeterminate) { + CheckBoxIndeterminate + } else { + PainterHint.None + }, + Selected(checkboxState), + Stateful(checkboxState), + ) + if (content == null) { Box(contentAlignment = Alignment.TopStart) { CheckBoxImage(wrapperModifier, checkboxPainter, checkBoxImageModifier) @@ -338,11 +337,11 @@ private object CheckBoxIndeterminate : PainterSuffixHint() { @Composable private fun CheckBoxImage( - outerModifier: Modifier, + modifier: Modifier, checkboxPainter: Painter, checkBoxModifier: Modifier, ) { - Box(outerModifier, contentAlignment = Alignment.Center) { + Box(modifier, contentAlignment = Alignment.Center) { Image(checkboxPainter, contentDescription = null, modifier = checkBoxModifier) } } @@ -351,31 +350,24 @@ private fun CheckBoxImage( @JvmInline public value class CheckboxState(private val state: ULong) : ToggleableComponentState, FocusableComponentState { - @Stable override val toggleableState: ToggleableState get() = state.readToggleableState() - @Stable override val isEnabled: Boolean get() = state and Enabled != 0UL - @Stable override val isActive: Boolean get() = state and Active != 0UL - @Stable override val isSelected: Boolean get() = toggleableState != ToggleableState.Off - @Stable override val isFocused: Boolean get() = state and Focused != 0UL - @Stable override val isHovered: Boolean get() = state and Hovered != 0UL - @Stable override val isPressed: Boolean get() = state and Pressed != 0UL diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Chip.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Chip.kt index 7c47914483..1b4ef82908 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Chip.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Chip.kt @@ -16,14 +16,13 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.Immutable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.Stable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.isUnspecified +import androidx.compose.ui.graphics.takeOrElse import androidx.compose.ui.semantics.Role import org.jetbrains.jewel.foundation.Stroke import org.jetbrains.jewel.foundation.modifier.border @@ -56,8 +55,7 @@ public fun Chip( enabled = enabled, selected = selected, style = style, - modifier = - modifier.clickable( + modifier = modifier.clickable( onClick = onClick, enabled = enabled, role = Role.Button, @@ -83,8 +81,7 @@ public fun ToggleableChip( enabled = enabled, selected = checked, style = style, - modifier = - modifier.toggleable( + modifier = modifier.toggleable( onValueChange = onClick, enabled = enabled, role = Role.Checkbox, @@ -111,7 +108,7 @@ public fun RadioButtonChip( enabled, selected, style, - modifier.selectable( + modifier = modifier.selectable( onClick = onClick, enabled = enabled, role = Role.RadioButton, @@ -132,19 +129,17 @@ private fun ChipImpl( modifier: Modifier, content: @Composable () -> Unit, ) { - var chipState by - remember(interactionSource) { - mutableStateOf(ChipState.of(enabled = enabled, selected = selected)) - } + var chipState by remember(interactionSource) { + mutableStateOf(ChipState.of(enabled = enabled, selected = selected)) + } + remember(enabled, selected) { chipState = chipState.copy(enabled = enabled, selected = selected) } LaunchedEffect(interactionSource) { interactionSource.interactions.collect { interaction -> when (interaction) { is PressInteraction.Press -> chipState = chipState.copy(pressed = true) - is PressInteraction.Cancel, - is PressInteraction.Release, - -> chipState = chipState.copy(pressed = false) + is PressInteraction.Cancel, is PressInteraction.Release -> chipState = chipState.copy(pressed = false) is HoverInteraction.Enter -> chipState = chipState.copy(hovered = true) is HoverInteraction.Exit -> chipState = chipState.copy(hovered = false) is FocusInteraction.Focus -> chipState = chipState.copy(focused = true) @@ -165,8 +160,7 @@ private fun ChipImpl( } Row( - modifier = - modifier + modifier = modifier .background(colors.backgroundFor(chipState).value, shape) .border(Stroke.Alignment.Center, borderWidth, borderColor, shape) .focusOutline(chipState, shape) @@ -174,13 +168,10 @@ private fun ChipImpl( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center, ) { - CompositionLocalProvider( - LocalContentColor provides - ( - colors.contentFor(state = chipState).value.takeIf { !it.isUnspecified } - ?: LocalContentColor.current - ), - ) { + val resolvedContentColor = colors.contentFor(state = chipState).value + .takeOrElse { LocalContentColor.current } + + CompositionLocalProvider(LocalContentColor provides resolvedContentColor) { content() } } @@ -191,27 +182,21 @@ private fun ChipImpl( public value class ChipState(public val state: ULong) : FocusableComponentState, SelectableComponentState { - @Stable override val isActive: Boolean get() = state and Active != 0UL - @Stable override val isEnabled: Boolean get() = state and Enabled != 0UL - @Stable override val isFocused: Boolean get() = state and Focused != 0UL - @Stable override val isSelected: Boolean get() = state and Selected != 0UL - @Stable override val isHovered: Boolean get() = state and Hovered != 0UL - @Stable override val isPressed: Boolean get() = state and Pressed != 0UL diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/CircularProgressIndicator.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/CircularProgressIndicator.kt index e449da6337..563c401663 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/CircularProgressIndicator.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/CircularProgressIndicator.kt @@ -76,10 +76,11 @@ private fun CircularProgressIndicatorImpl( val density = LocalDensity.current LaunchedEffect(density, style.color) { - val frames = - frameRetriever(style.color.takeOrElse { defaultColor }).map { + val frames = frameRetriever(style.color.takeOrElse { defaultColor }) + .map { loadSvgPainter(it.byteInputStream(), density) } + while (true) { for (i in frames.indices) { currentFrame = frames[i] @@ -90,7 +91,7 @@ private fun CircularProgressIndicatorImpl( } } -public object SpinnerProgressIconGenerator { +private object SpinnerProgressIconGenerator { private val opacityList = listOf(1.0f, 0.93f, 0.78f, 0.69f, 0.62f, 0.48f, 0.38f, 0.0f) @@ -115,56 +116,39 @@ public object SpinnerProgressIconGenerator { closeRoot() } - private fun StringBuilder.elements( - colorHex: String, - opacityList: List, - ) { - append( - "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n", - ) + private fun StringBuilder.elements(colorHex: String, opacityList: List) { + appendLine() + appendLine(""" """) + appendLine(""" """) + appendLine(""" """) + appendLine(""" """) + appendLine(""" """) + appendLine(""" """) + appendLine(""" """) + appendLine(""" """) } - public object Small { + object Small { - public fun generateSvgFrames(colorHex: String): List = buildList { + fun generateSvgFrames(colorHex: String): List = buildList { val opacityListShifted = opacityList.toMutableList() repeat(opacityList.count()) { - add( - generateSvgIcon( - size = 16, - colorHex = colorHex, - opacityListShifted = opacityListShifted, - ), - ) + add(generateSvgIcon(size = 16, colorHex = colorHex, opacityListShifted = opacityListShifted)) opacityListShifted.shtr() } } } - public object Big { + object Big { - public fun generateSvgFrames(colorHex: String): List = buildList { + fun generateSvgFrames(colorHex: String): List = buildList { val opacityListShifted = opacityList.toMutableList() repeat(opacityList.count()) { - add( - generateSvgIcon( - size = 32, - colorHex = colorHex, - opacityListShifted = opacityListShifted, - ), - ) + add(generateSvgIcon(size = 32, colorHex = colorHex, opacityListShifted = opacityListShifted)) opacityListShifted.shtr() } } diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Divider.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Divider.kt index 744de36cf4..1bde7c9b89 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Divider.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Divider.kt @@ -27,7 +27,7 @@ public fun Divider( startIndent: Dp = Dp.Unspecified, style: DividerStyle = JewelTheme.dividerStyle, ) { - val indentMod = + val indentModifier = if (startIndent.value != 0f) { Modifier.padding(start = startIndent.takeOrElse { style.metrics.startIndent }) } else { @@ -43,6 +43,8 @@ public fun Divider( val lineColor = color.takeOrElse { style.color } Box( - modifier.then(indentMod).then(orientationModifier).background(color = lineColor), + modifier.then(indentModifier) + .then(orientationModifier) + .background(color = lineColor), ) } diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Dropdown.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Dropdown.kt index 62580dd7e9..ba1879bc84 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Dropdown.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Dropdown.kt @@ -19,7 +19,6 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.Immutable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.Stable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -70,8 +69,9 @@ public fun Dropdown( var expanded by remember { mutableStateOf(false) } var skipNextClick by remember { mutableStateOf(false) } - var dropdownState by - remember(interactionSource) { mutableStateOf(DropdownState.of(enabled = enabled)) } + var dropdownState by remember(interactionSource) { + mutableStateOf(DropdownState.of(enabled = enabled)) + } remember(enabled) { dropdownState = dropdownState.copy(enabled = enabled) } @@ -99,7 +99,7 @@ public fun Dropdown( val hasNoOutline = outline == Outline.None Box( - modifier + modifier = modifier .clickable( onClick = { // TODO: Trick to skip click event when close menu by click dropdown @@ -123,12 +123,9 @@ public fun Dropdown( .defaultMinSize(minSize.width, minSize.height.coerceAtLeast(arrowMinSize.height)), contentAlignment = Alignment.CenterStart, ) { - CompositionLocalProvider( - LocalContentColor provides colors.contentFor(dropdownState).value, - ) { + CompositionLocalProvider(LocalContentColor provides colors.contentFor(dropdownState).value) { Box( - modifier = - Modifier.fillMaxWidth() + modifier = Modifier.fillMaxWidth() .padding(style.metrics.contentPadding) .padding(end = arrowMinSize.width), contentAlignment = Alignment.CenterStart, @@ -176,13 +173,12 @@ internal fun DropdownMenu( ) { val density = LocalDensity.current - val popupPositionProvider = - AnchorVerticalMenuPositionProvider( - contentOffset = style.metrics.offset, - contentMargin = style.metrics.menuMargin, - alignment = horizontalAlignment, - density = density, - ) + val popupPositionProvider = AnchorVerticalMenuPositionProvider( + contentOffset = style.metrics.offset, + contentMargin = style.metrics.menuMargin, + alignment = horizontalAlignment, + density = density, + ) var focusManager: FocusManager? by remember { mutableStateOf(null) } var inputModeManager: InputModeManager? by remember { mutableStateOf(null) } @@ -207,10 +203,7 @@ internal fun DropdownMenu( LocalMenuManager provides menuManager, LocalMenuStyle provides style, ) { - MenuContent( - modifier = modifier, - content = content, - ) + MenuContent(modifier, content = content) } } } @@ -219,23 +212,18 @@ internal fun DropdownMenu( @JvmInline public value class DropdownState(public val state: ULong) : FocusableComponentState { - @Stable override val isActive: Boolean get() = state and Active != 0UL - @Stable override val isEnabled: Boolean get() = state and Enabled != 0UL - @Stable override val isFocused: Boolean get() = state and Focused != 0UL - @Stable override val isHovered: Boolean get() = state and Hovered != 0UL - @Stable override val isPressed: Boolean get() = state and Pressed != 0UL diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/GroupHeader.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/GroupHeader.kt index 7c8a12a024..175d8d147a 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/GroupHeader.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/GroupHeader.kt @@ -18,6 +18,7 @@ public fun GroupHeader( ) { Row(modifier, verticalAlignment = Alignment.CenterVertically) { Text(text, color = textColor) + Divider( orientation = Orientation.Horizontal, color = style.colors.divider, diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Icon.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Icon.kt index fc62989baa..de42e3d156 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Icon.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Icon.kt @@ -32,6 +32,7 @@ import androidx.compose.ui.semantics.role import androidx.compose.ui.semantics.semantics import androidx.compose.ui.unit.dp import org.jetbrains.jewel.ui.painter.rememberResourcePainterProvider +import org.jetbrains.jewel.ui.util.thenIf import org.xml.sax.InputSource import java.io.InputStream @@ -74,15 +75,17 @@ public fun Icon( } /** - * Icon component that draws [imageVector] using [tint], defaulting to [Color.Unspecified]. + * Icon component that draws [imageVector] using [tint], defaulting to + * [Color.Unspecified]. * * @param imageVector [ImageVector] to draw inside this Icon - * @param contentDescription text used by accessibility services to describe what this icon - * represents. This should always be provided unless this icon is used for decorative purposes, - * and does not represent a meaningful action that a user can take. + * @param contentDescription text used by accessibility services to + * describe what this icon represents. This should always be provided + * unless this icon is used for decorative purposes, and does not + * represent a meaningful action that a user can take. * @param modifier optional [Modifier] for this Icon - * @param tint tint to be applied to [imageVector]. If [Color.Unspecified] is provided, then no tint - * is applied + * @param tint tint to be applied to [imageVector]. If [Color.Unspecified] + * is provided, then no tint is applied */ @Composable public fun Icon( @@ -100,15 +103,17 @@ public fun Icon( } /** - * Icon component that draws [bitmap] using [tint], defaulting to [Color.Unspecified]. + * Icon component that draws [bitmap] using [tint], defaulting to + * [Color.Unspecified]. * * @param bitmap [ImageBitmap] to draw inside this Icon - * @param contentDescription text used by accessibility services to describe what this icon - * represents. This should always be provided unless this icon is used for decorative purposes, - * and does not represent a meaningful action that a user can take. + * @param contentDescription text used by accessibility services to + * describe what this icon represents. This should always be provided + * unless this icon is used for decorative purposes, and does not + * represent a meaningful action that a user can take. * @param modifier optional [Modifier] for this Icon - * @param tint tint to be applied to [bitmap]. If [Color.Unspecified] is provided, then no tint is - * applied + * @param tint tint to be applied to [bitmap]. If [Color.Unspecified] is + * provided, then no tint is applied */ @Composable public fun Icon( @@ -127,15 +132,17 @@ public fun Icon( } /** - * Icon component that draws a [painter] using [tint], defaulting to [Color.Unspecified] + * Icon component that draws a [painter] using [tint], defaulting to + * [Color.Unspecified] * * @param painter [Painter] to draw inside this Icon - * @param contentDescription text used by accessibility services to describe what this icon - * represents. This should always be provided unless this icon is used for decorative purposes, - * and does not represent a meaningful action that a user can take. + * @param contentDescription text used by accessibility services to + * describe what this icon represents. This should always be provided + * unless this icon is used for decorative purposes, and does not + * represent a meaningful action that a user can take. * @param modifier optional [Modifier] for this Icon - * @param tint tint to be applied to [painter]. If [Color.Unspecified] is provided, then no tint is - * applied + * @param tint tint to be applied to [painter]. If [Color.Unspecified] is + * provided, then no tint is applied */ @Composable public fun Icon( @@ -152,11 +159,12 @@ public fun Icon( * Icon component that draws a [painter] using a [colorFilter] * * @param painter [Painter] to draw inside this Icon - * @param contentDescription text used by accessibility services to describe what this icon - * represents. This should always be provided unless this icon is used for decorative purposes, - * and does not represent a meaningful action that a user can take. - * @param modifier optional [Modifier] for this Icon + * @param contentDescription text used by accessibility services to + * describe what this icon represents. This should always be provided + * unless this icon is used for decorative purposes, and does not + * represent a meaningful action that a user can take. * @param colorFilter color filter to be applied to [painter] + * @param modifier optional [Modifier] for this Icon */ @Composable public fun Icon( @@ -175,8 +183,7 @@ public fun Icon( Modifier } Box( - modifier - .toolingGraphicsLayer() + modifier.toolingGraphicsLayer() .defaultSizeFor(painter) .paint( painter, @@ -215,10 +222,9 @@ private fun rememberVectorXmlResource( loader: ResourceLoader = ResourceLoader.Default, ): Painter { val density = LocalDensity.current - val image = - remember(resourcePath, density, loader) { - useResource(resourcePath, loader) { loadXmlImageVector(InputSource(it), density) } - } + val image = remember(resourcePath, density, loader) { + useResource(resourcePath, loader) { loadXmlImageVector(InputSource(it), density) } + } return rememberVectorPainter(image) } @@ -238,13 +244,9 @@ private inline fun useResource( ): T = loader.load(resourcePath).use(block) private fun Modifier.defaultSizeFor(painter: Painter) = - then( - if (painter.intrinsicSize == Size.Unspecified || painter.intrinsicSize.isInfinite()) { - DefaultIconSizeModifier - } else { - Modifier - }, - ) + thenIf(painter.intrinsicSize == Size.Unspecified || painter.intrinsicSize.isInfinite()) { + DefaultIconSizeModifier + } private fun Size.isInfinite() = width.isInfinite() && height.isInfinite() diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/IconButton.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/IconButton.kt index 186f5906ca..6f73d76212 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/IconButton.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/IconButton.kt @@ -17,7 +17,6 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.Immutable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.MutableState -import androidx.compose.runtime.Stable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -43,21 +42,19 @@ public fun IconButton( interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, content: @Composable (BoxScope.(IconButtonState) -> Unit), ) { - val buttonState = - remember(interactionSource) { mutableStateOf(IconButtonState.of(enabled = enabled)) } + val buttonState = remember(interactionSource) { mutableStateOf(IconButtonState.of(enabled = enabled)) } remember(enabled) { buttonState.value = buttonState.value.copy(enabled = enabled) } IconButtonImpl( state = buttonState, - modifier = modifier - .clickable( - onClick = onClick, - enabled = enabled, - role = Role.Button, - interactionSource = interactionSource, - indication = NoIndication, - ), + modifier = modifier.clickable( + onClick = onClick, + enabled = enabled, + role = Role.Button, + interactionSource = interactionSource, + indication = NoIndication, + ), style = style, interactionSource = interactionSource, content = content, @@ -84,16 +81,18 @@ public fun SelectableIconButton( IconButtonImpl( state = buttonState, - modifier = modifier.selectable( - onClick = onClick, - enabled = enabled, - role = Role.RadioButton, - interactionSource = interactionSource, - indication = null, - selected = selected, - ).onActivated(enabled = enabled) { - buttonState.value = buttonState.value.copy(active = it) - }, + modifier = modifier + .selectable( + onClick = onClick, + enabled = enabled, + role = Role.RadioButton, + interactionSource = interactionSource, + indication = null, + selected = selected, + ) + .onActivated(enabled = enabled) { + buttonState.value = buttonState.value.copy(active = it) + }, style = style, interactionSource = interactionSource, content = content, @@ -117,6 +116,7 @@ private fun IconButtonImpl( is PressInteraction.Cancel, is PressInteraction.Release, -> buttonState = buttonState.copy(pressed = false) + is HoverInteraction.Enter -> buttonState = buttonState.copy(hovered = true) is HoverInteraction.Exit -> buttonState = buttonState.copy(hovered = false) is FocusInteraction.Focus -> buttonState = buttonState.copy(focused = true) @@ -128,9 +128,7 @@ private fun IconButtonImpl( val background by style.colors.backgroundFor(buttonState) val border by style.colors.borderFor(buttonState) Box( - modifier = - modifier - .defaultMinSize(style.metrics.minSize.width, style.metrics.minSize.height) + modifier = modifier.defaultMinSize(style.metrics.minSize.width, style.metrics.minSize.height) .padding(style.metrics.padding) .background(background, shape) .border(style.metrics.borderWidth, border, shape), @@ -143,27 +141,21 @@ private fun IconButtonImpl( @JvmInline public value class IconButtonState(public val state: ULong) : FocusableComponentState, SelectableComponentState { - @Stable override val isSelected: Boolean get() = state and CommonStateBitMask.Selected != 0UL - @Stable override val isActive: Boolean get() = state and CommonStateBitMask.Active != 0UL - @Stable override val isEnabled: Boolean get() = state and CommonStateBitMask.Enabled != 0UL - @Stable override val isFocused: Boolean get() = state and CommonStateBitMask.Focused != 0UL - @Stable override val isHovered: Boolean get() = state and CommonStateBitMask.Hovered != 0UL - @Stable override val isPressed: Boolean get() = state and CommonStateBitMask.Pressed != 0UL diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/InputField.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/InputField.kt index 26f1ecd8dd..d40b2b57e4 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/InputField.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/InputField.kt @@ -10,7 +10,6 @@ import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.runtime.Composable import androidx.compose.runtime.Immutable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.Stable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -54,13 +53,11 @@ internal fun InputField( interactionSource: MutableInteractionSource, style: InputFieldStyle, textStyle: TextStyle, - decorationBox: - @Composable - (innerTextField: @Composable () -> Unit, state: InputFieldState) -> Unit, + decorationBox: @Composable (innerTextField: @Composable () -> Unit, state: InputFieldState) -> Unit, ) { - var inputState by - remember(interactionSource) { mutableStateOf(InputFieldState.of(enabled = enabled)) } + var inputState by remember(interactionSource) { mutableStateOf(InputFieldState.of(enabled = enabled)) } remember(enabled) { inputState = inputState.copy(enabled = enabled) } + LaunchedEffect(interactionSource) { interactionSource.interactions.collect { interaction -> when (interaction) { @@ -74,22 +71,20 @@ internal fun InputField( val backgroundColor by colors.backgroundFor(inputState) val shape = RoundedCornerShape(style.metrics.cornerSize) - val backgroundModifier = - Modifier.thenIf(!undecorated && backgroundColor.isSpecified) { - background(backgroundColor, shape) - } + val backgroundModifier = Modifier.thenIf(!undecorated && backgroundColor.isSpecified) { + background(backgroundColor, shape) + } val borderColor by style.colors.borderFor(inputState) val hasNoOutline = outline == Outline.None - val borderModifier = - Modifier.thenIf(!undecorated && borderColor.isSpecified && hasNoOutline) { - Modifier.border( - alignment = Stroke.Alignment.Center, - width = style.metrics.borderWidth, - color = borderColor, - shape = shape, - ) - } + val borderModifier = Modifier.thenIf(!undecorated && borderColor.isSpecified && hasNoOutline) { + border( + alignment = Stroke.Alignment.Center, + width = style.metrics.borderWidth, + color = borderColor, + shape = shape, + ) + } val contentColor by colors.contentFor(inputState) val mergedTextStyle = style.textStyle.merge(textStyle).copy(color = contentColor) @@ -97,8 +92,7 @@ internal fun InputField( BasicTextField( value = value, - modifier = - modifier + modifier = modifier .then(backgroundModifier) .then(borderModifier) .thenIf(!undecorated && hasNoOutline) { focusOutline(inputState, shape) } @@ -115,8 +109,7 @@ internal fun InputField( interactionSource = interactionSource, singleLine = singleLine, maxLines = maxLines, - decorationBox = - @Composable { innerTextField: @Composable () -> Unit -> + decorationBox = @Composable { innerTextField: @Composable () -> Unit -> decorationBox(innerTextField, inputState) }, ) @@ -126,23 +119,18 @@ internal fun InputField( @JvmInline public value class InputFieldState(public val state: ULong) : FocusableComponentState { - @Stable override val isActive: Boolean get() = state and Active != 0UL - @Stable override val isEnabled: Boolean get() = state and Enabled != 0UL - @Stable override val isFocused: Boolean get() = state and Focused != 0UL - @Stable override val isHovered: Boolean get() = state and Hovered != 0UL - @Stable override val isPressed: Boolean get() = state and Pressed != 0UL diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/LazyTree.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/LazyTree.kt index bf2d34d0de..731f85c8a5 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/LazyTree.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/LazyTree.kt @@ -34,6 +34,7 @@ public fun LazyTree( ) { val colors = style.colors val metrics = style.metrics + BasicLazyTree( tree = tree, onElementClick = onElementClick, @@ -57,21 +58,11 @@ public fun LazyTree( Icon(painter = painter, contentDescription = null) }, ) { - CompositionLocalProvider( - LocalContentColor provides - ( - style.colors - .contentFor( - TreeElementState.of( - focused = isActive, - selected = isSelected, - expanded = false, - ), - ) - .value - .takeOrElse { LocalContentColor.current } - ), - ) { + val resolvedContentColor = style.colors + .contentFor(TreeElementState.of(focused = isActive, selected = isSelected, expanded = false)) + .value.takeOrElse { LocalContentColor.current } + + CompositionLocalProvider(LocalContentColor provides resolvedContentColor) { nodeContent(it) } } diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/LinearProgressBar.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/LinearProgressBar.kt index 968b240929..1bdde38db1 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/LinearProgressBar.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/LinearProgressBar.kt @@ -39,20 +39,21 @@ public fun HorizontalProgressBar( val shape = RoundedCornerShape(style.metrics.cornerSize) Box( - modifier.defaultMinSize(minHeight = style.metrics.minHeight).clip(shape).drawWithContent { - drawRect(color = colors.track) // Draw the background - val progressWidth = size.width * progress - val progressX = if (layoutDirection == LayoutDirection.Ltr) 0f else size.width - progressWidth + modifier.defaultMinSize(minHeight = style.metrics.minHeight).clip(shape) + .drawWithContent { + drawRect(color = colors.track) // Draw the background + val progressWidth = size.width * progress + val progressX = if (layoutDirection == LayoutDirection.Ltr) 0f else size.width - progressWidth - val cornerSizePx = style.metrics.cornerSize.toPx(size, Density(density, fontScale)) - val cornerRadius = CornerRadius(cornerSizePx, cornerSizePx) - drawRoundRect( - color = colors.progress, - topLeft = Offset(progressX, 0f), - size = size.copy(width = progressWidth), - cornerRadius = cornerRadius, - ) - }, + val cornerSizePx = style.metrics.cornerSize.toPx(size, Density(density, fontScale)) + val cornerRadius = CornerRadius(cornerSizePx, cornerSizePx) + drawRoundRect( + color = colors.progress, + topLeft = Offset(progressX, 0f), + size = size.copy(width = progressWidth), + cornerRadius = cornerRadius, + ) + }, ) } @@ -66,16 +67,14 @@ public fun IndeterminateHorizontalProgressBar( val cycleDurationMillis by remember { mutableStateOf(style.indeterminateCycleDuration.inWholeMilliseconds.toInt()) } - val animatedProgress by - infiniteTransition.animateFloat( - initialValue = 0f, - targetValue = 2f, - animationSpec = - infiniteRepeatable( - tween(durationMillis = cycleDurationMillis, easing = LinearEasing), - repeatMode = RepeatMode.Restart, - ), - ) + val animatedProgress by infiniteTransition.animateFloat( + initialValue = 0f, + targetValue = 2f, + animationSpec = infiniteRepeatable( + tween(durationMillis = cycleDurationMillis, easing = LinearEasing), + repeatMode = RepeatMode.Restart, + ), + ) val highlightWidth = style.metrics.indeterminateHighlightWidth val colors = style.colors @@ -91,7 +90,6 @@ public fun IndeterminateHorizontalProgressBar( // Draw the animated highlight drawRect( - brush = Brush.linearGradient( colors = colorsList, start = Offset(x, 0f), diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Link.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Link.kt index f9bb9fb5d5..072620e5d4 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Link.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Link.kt @@ -14,7 +14,6 @@ import androidx.compose.foundation.text.BasicText import androidx.compose.runtime.Composable import androidx.compose.runtime.Immutable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.Stable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -209,8 +208,7 @@ private fun LinkImpl( interactionSource: MutableInteractionSource, icon: PainterProvider?, ) { - var linkState by - remember(interactionSource, enabled) { mutableStateOf(LinkState.of(enabled = enabled)) } + var linkState by remember(interactionSource, enabled) { mutableStateOf(LinkState.of(enabled = enabled)) } remember(enabled) { linkState = linkState.copy(enabled = enabled) } val inputModeManager = LocalInputModeManager.current @@ -221,6 +219,7 @@ private fun LinkImpl( is PressInteraction.Cancel, is PressInteraction.Release, -> linkState = linkState.copy(pressed = false) + is HoverInteraction.Enter -> linkState = linkState.copy(hovered = true) is HoverInteraction.Exit -> linkState = linkState.copy(hovered = false) is FocusInteraction.Focus -> { @@ -228,6 +227,7 @@ private fun LinkImpl( linkState = linkState.copy(focused = true) } } + is FocusInteraction.Unfocus -> linkState = linkState.copy(focused = false, pressed = false) } } @@ -255,8 +255,7 @@ private fun LinkImpl( val pointerChangeModifier = Modifier.pointerHoverIcon(PointerIcon(Cursor(Cursor.HAND_CURSOR))) Row( - modifier = - modifier + modifier = modifier .thenIf(linkState.isEnabled) { pointerChangeModifier } .clickable( onClick = { @@ -297,27 +296,21 @@ private fun LinkImpl( @JvmInline public value class LinkState(public val state: ULong) : FocusableComponentState { - @Stable override val isActive: Boolean get() = state and Active != 0UL - @Stable override val isEnabled: Boolean get() = state and Enabled != 0UL - @Stable override val isFocused: Boolean get() = state and Focused != 0UL - @Stable public val isVisited: Boolean get() = state and Visited != 0UL - @Stable override val isPressed: Boolean get() = state and Pressed != 0UL - @Stable override val isHovered: Boolean get() = state and Hovered != 0UL diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Menu.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Menu.kt index e50393a160..ef644e3177 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Menu.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Menu.kt @@ -27,7 +27,6 @@ import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.Immutable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.Stable import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -111,8 +110,7 @@ public fun PopupMenu( onPreviewKeyEvent = { false }, onKeyEvent = { val currentFocusManager = checkNotNull(focusManager) { "FocusManager must not be null" } - val currentInputModeManager = - checkNotNull(inputModeManager) { "InputModeManager must not be null" } + val currentInputModeManager = checkNotNull(inputModeManager) { "InputModeManager must not be null" } handlePopupMenuOnKeyEvent(it, currentFocusManager, currentInputModeManager, menuManager) }, ) { @@ -147,8 +145,7 @@ internal fun MenuContent( val menuShape = RoundedCornerShape(style.metrics.cornerSize) Box( - modifier = - modifier + modifier = modifier .shadow( elevation = style.metrics.shadowSize, shape = menuShape, @@ -160,32 +157,10 @@ internal fun MenuContent( .width(IntrinsicSize.Max) .onHover { localMenuManager.onHoveredChange(it) }, ) { - Column( - modifier = Modifier.verticalScroll(scrollState).padding(style.metrics.contentPadding), - ) { - items.forEach { - when (it) { - is MenuSelectableItem -> { - MenuItem( - selected = it.isSelected, - onClick = it.onClick, - enabled = it.isEnabled, - content = it.content, - ) - } - is SubmenuItem -> { - MenuSubmenuItem( - enabled = it.isEnabled, - submenu = it.submenu, - content = it.content, - ) - } - else -> { - it.content() - } - } - } + Column(Modifier.verticalScroll(scrollState).padding(style.metrics.contentPadding)) { + items.forEach { ShowMenuItem(it) } } + Box(modifier = Modifier.matchParentSize()) { VerticalScrollbar( rememberScrollbarAdapter(scrollState), @@ -195,6 +170,26 @@ internal fun MenuContent( } } +@Composable +private fun ShowMenuItem(item: MenuItem) { + when (item) { + is MenuSelectableItem -> MenuItem( + selected = item.isSelected, + onClick = item.onClick, + enabled = item.isEnabled, + content = item.content, + ) + + is SubmenuItem -> MenuSubmenuItem( + enabled = item.isEnabled, + submenu = item.submenu, + content = item.content, + ) + + else -> item.content() + } +} + public interface MenuScope { public fun selectableItem( @@ -223,7 +218,9 @@ public fun MenuScope.items( onItemClick: (Int) -> Unit, content: @Composable (Int) -> Unit, ) { - repeat(count) { selectableItem(isSelected(it), onClick = { onItemClick(it) }) { content(it) } } + repeat(count) { + selectableItem(isSelected(it), onClick = { onItemClick(it) }) { content(it) } + } } public fun MenuScope.items( @@ -312,10 +309,9 @@ public fun MenuItem( style: MenuStyle = JewelTheme.menuStyle, content: @Composable () -> Unit, ) { - var itemState by - remember(interactionSource) { - mutableStateOf(MenuItemState.of(selected = selected, enabled = enabled)) - } + var itemState by remember(interactionSource) { + mutableStateOf(MenuItemState.of(selected = selected, enabled = enabled)) + } remember(enabled, selected) { itemState = itemState.copy(selected = selected, enabled = enabled) } @@ -325,13 +321,13 @@ public fun MenuItem( interactionSource.interactions.collect { interaction -> when (interaction) { is PressInteraction.Press -> itemState = itemState.copy(pressed = true) - is PressInteraction.Cancel, - is PressInteraction.Release, - -> itemState = itemState.copy(pressed = false) + is PressInteraction.Cancel, is PressInteraction.Release -> itemState = itemState.copy(pressed = false) + is HoverInteraction.Enter -> { itemState = itemState.copy(hovered = true) focusRequester.requestFocus() } + is HoverInteraction.Exit -> itemState = itemState.copy(hovered = false) is FocusInteraction.Focus -> itemState = itemState.copy(focused = true) is FocusInteraction.Unfocus -> itemState = itemState.copy(focused = false) @@ -343,8 +339,7 @@ public fun MenuItem( val localInputModeManager = LocalInputModeManager.current Box( - modifier = - modifier + modifier = modifier .focusRequester(focusRequester) .selectable( selected = selected, @@ -408,13 +403,13 @@ public fun MenuSubmenuItem( interactionSource.interactions.collect { interaction -> when (interaction) { is PressInteraction.Press -> itemState = itemState.copy(pressed = true) - is PressInteraction.Cancel, - is PressInteraction.Release, - -> itemState = itemState.copy(pressed = false) + is PressInteraction.Cancel, is PressInteraction.Release -> itemState = itemState.copy(pressed = false) + is HoverInteraction.Enter -> { itemState = itemState.copy(hovered = true, selected = true) focusRequester.requestFocus() } + is HoverInteraction.Exit -> itemState = itemState.copy(hovered = false) is FocusInteraction.Focus -> itemState = itemState.copy(focused = true) is FocusInteraction.Unfocus -> itemState = itemState.copy(focused = false) @@ -427,8 +422,7 @@ public fun MenuSubmenuItem( val backgroundColor by itemColors.backgroundFor(itemState) Box( - modifier = - modifier + modifier = modifier .fillMaxWidth() .drawItemBackground(menuMetrics.itemMetrics, backgroundColor) .focusRequester(focusRequester) @@ -539,10 +533,9 @@ internal fun Submenu( var focusManager: FocusManager? by remember { mutableStateOf(null) } var inputModeManager: InputModeManager? by remember { mutableStateOf(null) } val parentMenuManager = LocalMenuManager.current - val menuManager = - remember(parentMenuManager, onDismissRequest) { - parentMenuManager.submenuManager(onDismissRequest) - } + val menuManager = remember(parentMenuManager, onDismissRequest) { + parentMenuManager.submenuManager(onDismissRequest) + } Popup( popupPositionProvider = popupPositionProvider, @@ -572,27 +565,21 @@ internal fun Submenu( @JvmInline public value class MenuItemState(public val state: ULong) : SelectableComponentState, FocusableComponentState { - @Stable override val isActive: Boolean get() = state and Selected != 0UL - @Stable override val isSelected: Boolean get() = state and Selected != 0UL - @Stable override val isEnabled: Boolean get() = state and Enabled != 0UL - @Stable override val isFocused: Boolean get() = state and Focused != 0UL - @Stable override val isHovered: Boolean get() = state and Hovered != 0UL - @Stable override val isPressed: Boolean get() = state and Pressed != 0UL diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/MenuManager.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/MenuManager.kt index bd70c2b0f9..b9e27d4aea 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/MenuManager.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/MenuManager.kt @@ -12,8 +12,9 @@ public class MenuManager( private var isHovered: Boolean = false /** - * Called when the hovered state of the menu changes. This is used to abort parent menu closing in - * unforced mode when submenu closed by click parent menu's item. + * Called when the hovered state of the menu changes. This is used to abort + * parent menu closing in unforced mode when submenu closed by click parent + * menu's item. * * @param hovered true if the menu is hovered, false otherwise. */ @@ -25,7 +26,8 @@ public class MenuManager( * Close all menus in the hierarchy. * * @param mode the input mode, menus close by pointer or keyboard event. - * @param force true to force close all menus ignore parent hover state, false otherwise. + * @param force true to force close all menus ignore parent hover state, + * false otherwise. */ public fun closeAll(mode: InputMode, force: Boolean) { // We ignore the pointer event if the menu is hovered in unforced mode. diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Popup.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Popup.kt index 3f7e011afd..73d67b1976 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Popup.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Popup.kt @@ -27,22 +27,26 @@ internal fun handlePopupMenuOnKeyEvent( menuManager: MenuManager, ): Boolean { if (keyEvent.type != KeyEventType.KeyDown) return false + return when (keyEvent.key) { Key.DirectionDown -> { inputModeManager.requestInputMode(InputMode.Keyboard) focusManager.moveFocus(FocusDirection.Next) true } + Key.DirectionUp -> { inputModeManager.requestInputMode(InputMode.Keyboard) focusManager.moveFocus(FocusDirection.Previous) true } + Key.Escape -> { inputModeManager.requestInputMode(InputMode.Keyboard) menuManager.closeAll(InputMode.Keyboard, true) true } + Key.DirectionLeft -> { if (menuManager.isSubmenu()) { inputModeManager.requestInputMode(InputMode.Keyboard) @@ -52,6 +56,7 @@ internal fun handlePopupMenuOnKeyEvent( false } } + else -> false } } @@ -72,31 +77,26 @@ internal data class AnchorVerticalMenuPositionProvider( ): IntOffset { val topMargin = with(density) { contentMargin.calculateTopPadding().roundToPx() } val bottomMargin = with(density) { contentMargin.calculateBottomPadding().roundToPx() } - val leftMargin = - with(density) { contentMargin.calculateLeftPadding(layoutDirection).roundToPx() } - val rightMargin = - with(density) { contentMargin.calculateRightPadding(layoutDirection).roundToPx() } - - val windowSpaceBounds = - IntRect( - left = leftMargin, - top = topMargin, - right = windowSize.width - rightMargin, - bottom = windowSize.height - bottomMargin, - ) + val leftMargin = with(density) { contentMargin.calculateLeftPadding(layoutDirection).roundToPx() } + val rightMargin = with(density) { contentMargin.calculateRightPadding(layoutDirection).roundToPx() } + + val windowSpaceBounds = IntRect( + left = leftMargin, + top = topMargin, + right = windowSize.width - rightMargin, + bottom = windowSize.height - bottomMargin, + ) // The content offset specified using the dropdown offset parameter. - val contentOffsetX = - with(density) { - contentOffset.x.roundToPx() * if (layoutDirection == LayoutDirection.Ltr) 1 else -1 - } + val contentOffsetX = with(density) { + contentOffset.x.roundToPx() * if (layoutDirection == LayoutDirection.Ltr) 1 else -1 + } val contentOffsetY = with(density) { contentOffset.y.roundToPx() } // Compute horizontal position. - val x = - anchorBounds.left + - alignment.align(popupContentSize.width, anchorBounds.width, layoutDirection) + - contentOffsetX + val x = anchorBounds.left + + alignment.align(popupContentSize.width, anchorBounds.width, layoutDirection) + + contentOffsetX // Compute vertical position. val aboveSpacing = anchorBounds.top - contentOffsetY - topMargin @@ -136,31 +136,26 @@ internal data class AnchorHorizontalMenuPositionProvider( ): IntOffset { val topMargin = with(density) { contentMargin.calculateTopPadding().roundToPx() } val bottomMargin = with(density) { contentMargin.calculateBottomPadding().roundToPx() } - val leftMargin = - with(density) { contentMargin.calculateLeftPadding(layoutDirection).roundToPx() } - val rightMargin = - with(density) { contentMargin.calculateRightPadding(layoutDirection).roundToPx() } - - val windowSpaceBounds = - IntRect( - left = leftMargin, - top = topMargin, - right = windowSize.width - rightMargin, - bottom = windowSize.height - bottomMargin, - ) + val leftMargin = with(density) { contentMargin.calculateLeftPadding(layoutDirection).roundToPx() } + val rightMargin = with(density) { contentMargin.calculateRightPadding(layoutDirection).roundToPx() } + + val windowSpaceBounds = IntRect( + left = leftMargin, + top = topMargin, + right = windowSize.width - rightMargin, + bottom = windowSize.height - bottomMargin, + ) // The content offset specified using the dropdown offset parameter. - val contentOffsetX = - with(density) { - contentOffset.x.roundToPx() * if (layoutDirection == LayoutDirection.Ltr) 1 else -1 - } + val contentOffsetX = with(density) { + contentOffset.x.roundToPx() * if (layoutDirection == LayoutDirection.Ltr) 1 else -1 + } val contentOffsetY = with(density) { contentOffset.y.roundToPx() } // Compute horizontal position. - val y = - anchorBounds.top + - alignment.align(popupContentSize.height, anchorBounds.height) + - contentOffsetY + val y = anchorBounds.top + + alignment.align(popupContentSize.height, anchorBounds.height) + + contentOffsetY // Compute vertical position. val leftSpacing = anchorBounds.left - contentOffsetX - windowSpaceBounds.left @@ -197,5 +192,6 @@ internal fun IntRect.constrainedIn(rect: IntRect): IntRect { if (y < rect.top) { y = rect.top } + return IntRect(x, y, x + width, y + height) } diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/RadioButton.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/RadioButton.kt index d8831e976c..7c992493ad 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/RadioButton.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/RadioButton.kt @@ -16,7 +16,6 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.Immutable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.Stable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -133,10 +132,10 @@ private fun RadioButtonImpl( textStyle: TextStyle, content: (@Composable RowScope.() -> Unit)?, ) { - var radioButtonState by - remember(interactionSource) { - mutableStateOf(RadioButtonState.of(selected = selected, enabled = enabled)) - } + var radioButtonState by remember(interactionSource) { + mutableStateOf(RadioButtonState.of(selected = selected, enabled = enabled)) + } + remember(selected, enabled) { radioButtonState = radioButtonState.copy(selected = selected, enabled = enabled) } @@ -148,6 +147,7 @@ private fun RadioButtonImpl( is PressInteraction.Cancel, is PressInteraction.Release -> { radioButtonState = radioButtonState.copy(pressed = false) } + is HoverInteraction.Enter -> radioButtonState = radioButtonState.copy(hovered = true) is HoverInteraction.Exit -> radioButtonState = radioButtonState.copy(hovered = false) is FocusInteraction.Focus -> radioButtonState = radioButtonState.copy(focused = true) @@ -172,19 +172,17 @@ private fun RadioButtonImpl( val colors = style.colors val metrics = style.metrics - val radioButtonModifier = - Modifier.size(metrics.radioButtonSize) - .outline( - radioButtonState, - outline, - outlineShape = CircleShape, - alignment = Stroke.Alignment.Inside, - ) - val radioButtonPainter by - style.icons.radioButton.getPainter( - Selected(radioButtonState), - Stateful(radioButtonState), + val radioButtonModifier = Modifier.size(metrics.radioButtonSize) + .outline( + radioButtonState, + outline, + outlineShape = CircleShape, + alignment = Stroke.Alignment.Inside, ) + val radioButtonPainter by style.icons.radioButton.getPainter( + Selected(radioButtonState), + Stateful(radioButtonState), + ) if (content == null) { RadioButtonImage(wrapperModifier, radioButtonPainter, radioButtonModifier) @@ -216,7 +214,6 @@ private fun RadioButtonImage( radioButtonPainter: Painter, radioButtonModifier: Modifier, ) { - // TODO tint icon painter Box(outerModifier) { Image(radioButtonPainter, contentDescription = null, modifier = radioButtonModifier) } @@ -226,27 +223,21 @@ private fun RadioButtonImage( @JvmInline public value class RadioButtonState(public val state: ULong) : SelectableComponentState, FocusableComponentState { - @Stable override val isActive: Boolean get() = state and Active != 0UL - @Stable override val isSelected: Boolean get() = state and Selected != 0UL - @Stable override val isEnabled: Boolean get() = state and Enabled != 0UL - @Stable override val isFocused: Boolean get() = state and Focused != 0UL - @Stable override val isHovered: Boolean get() = state and Hovered != 0UL - @Stable override val isPressed: Boolean get() = state and Pressed != 0UL diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Scrollbars.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Scrollbars.kt index 4b5fa69a9a..d2e6150b95 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Scrollbars.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Scrollbars.kt @@ -31,17 +31,16 @@ public fun VerticalScrollbar( val shape by remember { mutableStateOf(RoundedCornerShape(style.metrics.thumbCornerSize)) } val hoverDurationMillis by remember { mutableStateOf(style.hoverDuration.inWholeMilliseconds) } - CompositionLocalProvider( - LocalScrollbarStyle provides - ComposeScrollbarStyle( - minimalHeight = style.metrics.minThumbLength, - thickness = style.metrics.thumbThickness, - shape = shape, - hoverDurationMillis = hoverDurationMillis.toInt(), - unhoverColor = style.colors.thumbBackground, - hoverColor = style.colors.thumbBackgroundHovered, - ), - ) { + val composeScrollbarStyle = ComposeScrollbarStyle( + minimalHeight = style.metrics.minThumbLength, + thickness = style.metrics.thumbThickness, + shape = shape, + hoverDurationMillis = hoverDurationMillis.toInt(), + unhoverColor = style.colors.thumbBackground, + hoverColor = style.colors.thumbBackgroundHovered, + ) + + CompositionLocalProvider(LocalScrollbarStyle provides composeScrollbarStyle) { VerticalScrollbar( adapter = adapter, modifier = modifier.padding(style.metrics.trackPadding), @@ -65,17 +64,15 @@ public fun HorizontalScrollbar( mutableStateOf(style.hoverDuration.toInt(DurationUnit.MILLISECONDS)) } - CompositionLocalProvider( - LocalScrollbarStyle provides - ComposeScrollbarStyle( - minimalHeight = style.metrics.minThumbLength, - thickness = style.metrics.thumbThickness, - shape = shape, - hoverDurationMillis = hoverDurationMillis, - unhoverColor = style.colors.thumbBackground, - hoverColor = style.colors.thumbBackgroundHovered, - ), - ) { + val composeScrollbarStyle = ComposeScrollbarStyle( + minimalHeight = style.metrics.minThumbLength, + thickness = style.metrics.thumbThickness, + shape = shape, + hoverDurationMillis = hoverDurationMillis, + unhoverColor = style.colors.thumbBackground, + hoverColor = style.colors.thumbBackgroundHovered, + ) + CompositionLocalProvider(LocalScrollbarStyle provides composeScrollbarStyle) { HorizontalScrollbar( adapter = adapter, modifier = modifier.padding(style.metrics.trackPadding), @@ -99,17 +96,15 @@ public fun TabStripHorizontalScrollbar( mutableStateOf(style.hoverDuration.inWholeMilliseconds.toInt()) } - CompositionLocalProvider( - LocalScrollbarStyle provides - ComposeScrollbarStyle( - minimalHeight = style.metrics.minThumbLength, - thickness = 3.dp, - shape = shape, - hoverDurationMillis = hoverDurationMillis, - unhoverColor = style.colors.thumbBackground, - hoverColor = style.colors.thumbBackgroundHovered, - ), - ) { + val composeScrollbarStyle = ComposeScrollbarStyle( + minimalHeight = style.metrics.minThumbLength, + thickness = 3.dp, + shape = shape, + hoverDurationMillis = hoverDurationMillis, + unhoverColor = style.colors.thumbBackground, + hoverColor = style.colors.thumbBackgroundHovered, + ) + CompositionLocalProvider(LocalScrollbarStyle provides composeScrollbarStyle) { HorizontalScrollbar( adapter = adapter, modifier = modifier.padding(1.dp), diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/SplitLayout.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/SplitLayout.kt index eac4e805a3..eb3706e613 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/SplitLayout.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/SplitLayout.kt @@ -75,13 +75,11 @@ public fun HorizontalSplitLayout( }, ) { measurables, incomingConstraints -> val availableWidth = incomingConstraints.maxWidth - val actualDividerX = - dividerX - .coerceIn(0, availableWidth) - .coerceIn( - (availableWidth * minRatio).roundToInt(), - (availableWidth * maxRatio).roundToInt(), - ) + val actualDividerX = dividerX.coerceIn(0, availableWidth) + .coerceIn( + (availableWidth * minRatio).roundToInt(), + (availableWidth * maxRatio).roundToInt(), + ) val dividerMeasurable = measurables.single { it.layoutId == "divider" } val dividerPlaceable = @@ -91,38 +89,28 @@ public fun HorizontalSplitLayout( val firstComponentConstraints = Constraints.fixed((actualDividerX).coerceAtLeast(0), incomingConstraints.maxHeight) - val firstPlaceable = - ( - measurables.find { it.layoutId == "first" } - ?: error("No first component found. Have you applied the provided Modifier to it?") - ) - .measure(firstComponentConstraints) + val firstPlaceable = measurables.find { it.layoutId == "first" } + ?.measure(firstComponentConstraints) + ?: error("No first component found. Have you applied the provided Modifier to it?") val secondComponentConstraints = Constraints.fixed( - availableWidth - actualDividerX + dividerPlaceable.width, - incomingConstraints.maxHeight, + width = availableWidth - actualDividerX + dividerPlaceable.width, + height = incomingConstraints.maxHeight, ) - val secondPlaceable = - ( - measurables.find { it.layoutId == "second" } - ?: error("No second component found. Have you applied the provided Modifier to it?") - ) - .measure(secondComponentConstraints) + val secondPlaceable = measurables.find { it.layoutId == "second" } + ?.measure(secondComponentConstraints) + ?: error("No second component found. Have you applied the provided Modifier to it?") val dividerHandlePlaceable = - measurables - .single { it.layoutId == "divider-handle" } + measurables.single { it.layoutId == "divider-handle" } .measure(Constraints.fixedHeight(incomingConstraints.maxHeight)) layout(availableWidth, incomingConstraints.maxHeight) { firstPlaceable.placeRelative(0, 0) dividerPlaceable.placeRelative(actualDividerX - dividerPlaceable.width / 2, 0) secondPlaceable.placeRelative(actualDividerX + dividerPlaceable.width, 0) - dividerHandlePlaceable.placeRelative( - actualDividerX - dividerHandlePlaceable.measuredWidth / 2, - 0, - ) + dividerHandlePlaceable.placeRelative(actualDividerX - dividerHandlePlaceable.measuredWidth / 2, 0) } } } @@ -173,13 +161,11 @@ public fun VerticalSplitLayout( }, ) { measurables, incomingConstraints -> val availableHeight = incomingConstraints.maxHeight - val actualDividerY = - dividerY - .coerceIn(0, availableHeight) - .coerceIn( - (availableHeight * minRatio).roundToInt(), - (availableHeight * maxRatio).roundToInt(), - ) + val actualDividerY = dividerY.coerceIn(0, availableHeight) + .coerceIn( + (availableHeight * minRatio).roundToInt(), + (availableHeight * maxRatio).roundToInt(), + ) val dividerMeasurable = measurables.single { it.layoutId == "divider" } val dividerPlaceable = @@ -189,38 +175,27 @@ public fun VerticalSplitLayout( val firstComponentConstraints = Constraints.fixed(incomingConstraints.maxWidth, (actualDividerY - 1).coerceAtLeast(0)) - val firstPlaceable = - ( - measurables.find { it.layoutId == "first" } - ?: error("No first component found. Have you applied the provided Modifier to it?") - ) - .measure(firstComponentConstraints) + val firstPlaceable = measurables.find { it.layoutId == "first" } + ?.measure(firstComponentConstraints) + ?: error("No first component found. Have you applied the provided Modifier to it?") val secondComponentConstraints = Constraints.fixed( - incomingConstraints.maxWidth, - availableHeight - actualDividerY + dividerPlaceable.height, + width = incomingConstraints.maxWidth, + height = availableHeight - actualDividerY + dividerPlaceable.height, ) - val secondPlaceable = - ( - measurables.find { it.layoutId == "second" } - ?: error("No second component found. Have you applied the provided Modifier to it?") - ) - .measure(secondComponentConstraints) + val secondPlaceable = measurables.find { it.layoutId == "second" } + ?.measure(secondComponentConstraints) + ?: error("No second component found. Have you applied the provided Modifier to it?") - val dividerHandlePlaceable = - measurables - .single { it.layoutId == "divider-handle" } - .measure(Constraints.fixedWidth(incomingConstraints.maxWidth)) + val dividerHandlePlaceable = measurables.single { it.layoutId == "divider-handle" } + .measure(Constraints.fixedWidth(incomingConstraints.maxWidth)) layout(incomingConstraints.maxWidth, availableHeight) { firstPlaceable.placeRelative(0, 0) dividerPlaceable.placeRelative(0, actualDividerY - dividerPlaceable.height / 2) secondPlaceable.placeRelative(0, actualDividerY + dividerPlaceable.height) - dividerHandlePlaceable.placeRelative( - 0, - actualDividerY - dividerHandlePlaceable.measuredHeight / 2, - ) + dividerHandlePlaceable.placeRelative(0, actualDividerY - dividerHandlePlaceable.measuredHeight / 2) } } } diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/TabStrip.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/TabStrip.kt index d7e6fca492..5b37353139 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/TabStrip.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/TabStrip.kt @@ -19,7 +19,6 @@ import androidx.compose.foundation.rememberScrollbarAdapter import androidx.compose.foundation.selection.selectableGroup import androidx.compose.runtime.Composable import androidx.compose.runtime.Immutable -import androidx.compose.runtime.Stable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -27,6 +26,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.platform.LocalLayoutDirection +import org.jetbrains.jewel.foundation.GenerateDataFunctions import org.jetbrains.jewel.foundation.modifier.onHover import org.jetbrains.jewel.foundation.state.CommonStateBitMask import org.jetbrains.jewel.foundation.state.FocusableComponentState @@ -43,13 +43,11 @@ public fun TabStrip( val scrollState = rememberScrollState() Box( - modifier.focusable(true, remember { MutableInteractionSource() }).onHover { - tabStripState = tabStripState.copy(hovered = it) - }, + modifier.focusable(true, remember { MutableInteractionSource() }) + .onHover { tabStripState = tabStripState.copy(hovered = it) }, ) { Row( - modifier = - Modifier.horizontalScroll(scrollState) + modifier = Modifier.horizontalScroll(scrollState) .scrollable( orientation = Orientation.Vertical, reverseDirection = @@ -65,26 +63,11 @@ public fun TabStrip( ) { tabs.forEach { TabImpl(isActive = tabStripState.isActive, tabData = it) } } + AnimatedVisibility( visible = tabStripState.isHovered, - enter = - fadeIn( - animationSpec = - tween( - durationMillis = 125, - delayMillis = 0, - easing = LinearEasing, - ), - ), - exit = - fadeOut( - animationSpec = - tween( - durationMillis = 125, - delayMillis = 700, - easing = LinearEasing, - ), - ), + enter = fadeIn(tween(durationMillis = 125, delayMillis = 0, easing = LinearEasing)), + exit = fadeOut(tween(durationMillis = 125, delayMillis = 700, easing = LinearEasing)), ) { TabStripHorizontalScrollbar( adapter = rememberScrollbarAdapter(scrollState), @@ -105,6 +88,7 @@ public sealed class TabData { public abstract val onClick: () -> Unit @Immutable + @GenerateDataFunctions public class Default( override val selected: Boolean, override val label: String, @@ -112,36 +96,10 @@ public sealed class TabData { override val closable: Boolean = true, override val onClose: () -> Unit = {}, override val onClick: () -> Unit = {}, - ) : TabData() { - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (javaClass != other?.javaClass) return false - - other as Default - - if (selected != other.selected) return false - if (label != other.label) return false - if (icon != other.icon) return false - if (closable != other.closable) return false - if (onClose != other.onClose) return false - if (onClick != other.onClick) return false - - return true - } - - override fun hashCode(): Int { - var result = selected.hashCode() - result = 31 * result + label.hashCode() - result = 31 * result + (icon?.hashCode() ?: 0) - result = 31 * result + closable.hashCode() - result = 31 * result + onClose.hashCode() - result = 31 * result + onClick.hashCode() - return result - } - } + ) : TabData() @Immutable + @GenerateDataFunctions public class Editor( override val selected: Boolean, override val label: String, @@ -149,57 +107,25 @@ public sealed class TabData { override val closable: Boolean = true, override val onClose: () -> Unit = {}, override val onClick: () -> Unit = {}, - ) : TabData() { - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (javaClass != other?.javaClass) return false - - other as Editor - - if (selected != other.selected) return false - if (label != other.label) return false - if (icon != other.icon) return false - if (closable != other.closable) return false - if (onClose != other.onClose) return false - if (onClick != other.onClick) return false - - return true - } - - override fun hashCode(): Int { - var result = selected.hashCode() - result = 31 * result + label.hashCode() - result = 31 * result + (icon?.hashCode() ?: 0) - result = 31 * result + closable.hashCode() - result = 31 * result + onClose.hashCode() - result = 31 * result + onClick.hashCode() - return result - } - } + ) : TabData() } @Immutable @JvmInline public value class TabStripState(public val state: ULong) : FocusableComponentState { - @Stable override val isActive: Boolean get() = state and CommonStateBitMask.Active != 0UL - @Stable override val isEnabled: Boolean get() = state and CommonStateBitMask.Enabled != 0UL - @Stable override val isFocused: Boolean get() = state and CommonStateBitMask.Focused != 0UL - @Stable override val isHovered: Boolean get() = state and CommonStateBitMask.Hovered != 0UL - @Stable override val isPressed: Boolean get() = state and CommonStateBitMask.Pressed != 0UL diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Tabs.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Tabs.kt index 092fbba072..41df851fea 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Tabs.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Tabs.kt @@ -1,7 +1,6 @@ package org.jetbrains.jewel.ui.component import androidx.compose.foundation.Image -import androidx.compose.foundation.LocalIndication import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.HoverInteraction @@ -18,7 +17,6 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.Immutable import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.Stable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -77,6 +75,7 @@ internal fun TabImpl( is PressInteraction.Cancel, is PressInteraction.Release, -> tabState = tabState.copy(pressed = false) + is HoverInteraction.Enter -> tabState = tabState.copy(hovered = true) is HoverInteraction.Exit -> tabState = tabState.copy(hovered = false) } @@ -87,17 +86,15 @@ internal fun TabImpl( val lineThickness = tabStyle.metrics.underlineThickness val backgroundColor by tabStyle.colors.backgroundFor(state = tabState) - CompositionLocalProvider( - LocalIndication provides NoIndication, - LocalContentColor provides - tabStyle.colors.contentFor(tabState).value.takeOrElse { LocalContentColor.current }, - ) { + val resolvedContentColor = tabStyle.colors.contentFor(tabState) + .value.takeOrElse { LocalContentColor.current } + + CompositionLocalProvider(LocalContentColor provides resolvedContentColor) { val labelAlpha by tabStyle.contentAlpha.labelFor(tabState) val iconAlpha by tabStyle.contentAlpha.iconFor(tabState) Row( - modifier - .height(tabStyle.metrics.tabHeight) + modifier.height(tabStyle.metrics.tabHeight) .background(backgroundColor) .focusProperties { canFocus = false } .selectable( @@ -140,6 +137,7 @@ internal fun TabImpl( is TabData.Default -> tabData.closable is TabData.Editor -> tabData.closable && (tabState.isHovered || tabState.isSelected) } + if (showCloseIcon) { val closeActionInteractionSource = remember { MutableInteractionSource() } LaunchedEffect(closeActionInteractionSource) { @@ -156,15 +154,16 @@ internal fun TabImpl( } } } + val closePainter by tabStyle.icons.close.getPainter(Stateful(closeButtonState)) Image( - modifier = - Modifier.clickable( - interactionSource = closeActionInteractionSource, - indication = null, - onClick = tabData.onClose, - role = Role.Button, - ) + modifier = Modifier + .clickable( + interactionSource = closeActionInteractionSource, + indication = null, + onClick = tabData.onClose, + role = Role.Button, + ) .size(16.dp), painter = closePainter, contentDescription = "Close tab ${tabData.label}", @@ -180,23 +179,18 @@ internal fun TabImpl( @JvmInline public value class TabState(public val state: ULong) : SelectableComponentState { - @Stable override val isActive: Boolean get() = state and Active != 0UL - @Stable override val isSelected: Boolean get() = state and Selected != 0UL - @Stable override val isEnabled: Boolean get() = state and Enabled != 0UL - @Stable override val isHovered: Boolean get() = state and Hovered != 0UL - @Stable override val isPressed: Boolean get() = state and Pressed != 0UL diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Text.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Text.kt index 8ea394aabd..083fb53729 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Text.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Text.kt @@ -95,6 +95,7 @@ public fun Text( letterSpacing = letterSpacing, ), ) + BasicText( text, modifier, diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/TextArea.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/TextArea.kt index 201369b4c9..621da462de 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/TextArea.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/TextArea.kt @@ -32,8 +32,8 @@ import org.jetbrains.jewel.ui.component.styling.TextAreaStyle import org.jetbrains.jewel.ui.theme.textAreaStyle /** - * @param placeholder the optional placeholder to be displayed over the component when the [value] - * is empty. + * @param placeholder the optional placeholder to be displayed over the + * component when the [value] is empty. */ @Composable public fun TextArea( @@ -88,8 +88,8 @@ public fun TextArea( } /** - * @param placeholder the optional placeholder to be displayed over the component when the [value] - * is empty. + * @param placeholder the optional placeholder to be displayed over the + * component when the [value] is empty. */ @Composable public fun TextArea( @@ -171,51 +171,29 @@ private fun TextAreaDecorationBox( } }, ) { measurables, incomingConstraints -> - val horizontalPadding = - ( - contentPadding.calculateLeftPadding(layoutDirection) + - contentPadding.calculateRightPadding(layoutDirection) - ) - .roundToPx() - val verticalPadding = - (contentPadding.calculateTopPadding() + contentPadding.calculateBottomPadding()).roundToPx() + val leftPadding = contentPadding.calculateLeftPadding(layoutDirection) + val rightPadding = contentPadding.calculateRightPadding(layoutDirection) + val horizontalPadding = (leftPadding + rightPadding).roundToPx() + val verticalPadding = (contentPadding.calculateTopPadding() + contentPadding.calculateBottomPadding()) + .roundToPx() - val textAreaConstraints = - incomingConstraints - .offset( - horizontal = -horizontalPadding, - vertical = -verticalPadding, - ) - .copy(minHeight = 0) + val textAreaConstraints = incomingConstraints + .offset(horizontal = -horizontalPadding, vertical = -verticalPadding) + .copy(minHeight = 0) - val textAreaPlaceable = - measurables.first { it.layoutId == TEXT_AREA_ID }.measure(textAreaConstraints) + val textAreaPlaceable = measurables.single { it.layoutId == TEXT_AREA_ID } + .measure(textAreaConstraints) // Measure placeholder val placeholderConstraints = textAreaConstraints.copy(minWidth = 0, minHeight = 0) - val placeholderPlaceable = - measurables.find { it.layoutId == PLACEHOLDER_ID }?.measure(placeholderConstraints) + val placeholderPlaceable = measurables.find { it.layoutId == PLACEHOLDER_ID } + ?.measure(placeholderConstraints) - val width = - calculateWidth( - textAreaPlaceable, - placeholderPlaceable, - textAreaConstraints, - ) - val height = - calculateHeight( - textAreaPlaceable, - placeholderPlaceable, - verticalPadding, - textAreaConstraints, - ) + val width = calculateWidth(textAreaPlaceable, placeholderPlaceable, textAreaConstraints) + val height = calculateHeight(textAreaPlaceable, placeholderPlaceable, verticalPadding, textAreaConstraints) layout(width, height) { - place( - height, - textAreaPlaceable, - placeholderPlaceable, - ) + place(height, textAreaPlaceable, placeholderPlaceable) } } } @@ -225,10 +203,7 @@ private fun calculateWidth( placeholderPlaceable: Placeable?, constraints: Constraints, ): Int = - maxOf( - textFieldPlaceable.width, - placeholderPlaceable?.width ?: 0, - ) + maxOf(textFieldPlaceable.width, placeholderPlaceable?.width ?: 0) .coerceAtLeast(constraints.minWidth) private fun calculateHeight( @@ -237,11 +212,7 @@ private fun calculateHeight( verticalPadding: Int, constraints: Constraints, ): Int { - val textAreaHeight = - maxOf( - textFieldPlaceable.height, - placeholderPlaceable?.height ?: 0, - ) + val textAreaHeight = maxOf(textFieldPlaceable.height, placeholderPlaceable?.height ?: 0) return (textAreaHeight + verticalPadding).coerceAtLeast(constraints.minHeight) } @@ -251,16 +222,10 @@ private fun Placeable.PlacementScope.place( placeholderPlaceable: Placeable?, ) { // placed center vertically - textAreaPlaceable.placeRelative( - 0, - Alignment.CenterVertically.align(textAreaPlaceable.height, height), - ) + textAreaPlaceable.placeRelative(0, Alignment.CenterVertically.align(textAreaPlaceable.height, height)) // placed similar to the input text above - placeholderPlaceable?.placeRelative( - 0, - Alignment.CenterVertically.align(placeholderPlaceable.height, height), - ) + placeholderPlaceable?.placeRelative(0, Alignment.CenterVertically.align(placeholderPlaceable.height, height)) } private const val PLACEHOLDER_ID = "Placeholder" diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/TextField.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/TextField.kt index 9d2ee4f6b2..5c49ffb35e 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/TextField.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/TextField.kt @@ -33,8 +33,8 @@ import org.jetbrains.jewel.ui.theme.textFieldStyle import kotlin.math.max /** - * @param placeholder the optional placeholder to be displayed over the component when the [value] - * is empty. + * @param placeholder the optional placeholder to be displayed over the + * component when the [value] is empty. */ @Composable public fun TextField( @@ -89,8 +89,8 @@ public fun TextField( } /** - * @param placeholder the optional placeholder to be displayed over the component when the [value] - * is empty. + * @param placeholder the optional placeholder to be displayed over the + * component when the [value] is empty. */ @Composable public fun TextField( @@ -133,8 +133,7 @@ public fun TextField( val minSize = style.metrics.minSize TextFieldDecorationBox( - modifier = - Modifier.defaultMinSize(minWidth = minSize.width, minHeight = minSize.height) + modifier = Modifier.defaultMinSize(minWidth = minSize.width, minHeight = minSize.height) .padding(style.metrics.contentPadding), innerTextField = innerTextField, textStyle = textStyle, @@ -196,46 +195,33 @@ private fun TextFieldDecorationBox( occupiedSpaceHorizontally += trailingPlaceable?.width ?: 0 occupiedSpaceHorizontally += leadingPlaceable?.width ?: 0 - val textFieldConstraints = - incomingConstraints - .offset( - horizontal = -occupiedSpaceHorizontally, - ) - .copy(minHeight = 0) - val textFieldPlaceable = - measurables.first { it.layoutId == TEXT_FIELD_ID }.measure(textFieldConstraints) + val textFieldConstraints = incomingConstraints.offset(horizontal = -occupiedSpaceHorizontally) + .copy(minHeight = 0) + val textFieldPlaceable = measurables.single { it.layoutId == TEXT_FIELD_ID } + .measure(textFieldConstraints) // measure placeholder val placeholderConstraints = textFieldConstraints.copy(minWidth = 0) - val placeholderPlaceable = - measurables.find { it.layoutId == PLACEHOLDER_ID }?.measure(placeholderConstraints) + val placeholderPlaceable = measurables.find { it.layoutId == PLACEHOLDER_ID } + ?.measure(placeholderConstraints) - val width = - calculateWidth( - trailingPlaceable, - leadingPlaceable, - textFieldPlaceable, - placeholderPlaceable, - incomingConstraints, - ) - val height = - calculateHeight( - trailingPlaceable, - leadingPlaceable, - textFieldPlaceable, - placeholderPlaceable, - incomingConstraints, - ) + val width = calculateWidth( + trailingPlaceable, + leadingPlaceable, + textFieldPlaceable, + placeholderPlaceable, + incomingConstraints, + ) + val height = calculateHeight( + trailingPlaceable, + leadingPlaceable, + textFieldPlaceable, + placeholderPlaceable, + incomingConstraints, + ) layout(width, height) { - place( - height, - width, - trailingPlaceable, - leadingPlaceable, - textFieldPlaceable, - placeholderPlaceable, - ) + place(height, width, trailingPlaceable, leadingPlaceable, textFieldPlaceable, placeholderPlaceable) } } } @@ -248,10 +234,7 @@ private fun calculateWidth( constraints: Constraints, ): Int { val middleSection = - maxOf( - textFieldPlaceable.width, - placeholderPlaceable?.width ?: 0, - ) + maxOf(textFieldPlaceable.width, placeholderPlaceable?.width ?: 0) val wrappedWidth = middleSection + (trailingPlaceable?.width ?: 0) + (leadingPlaceable?.width ?: 0) return max(wrappedWidth, constraints.minWidth) diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Tooltip.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Tooltip.kt index fe9b02c9c1..5fd315955d 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Tooltip.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/component/Tooltip.kt @@ -37,12 +37,11 @@ public fun Tooltip( tooltip: @Composable () -> Unit, modifier: Modifier = Modifier, style: TooltipStyle = JewelTheme.tooltipStyle, - tooltipPlacement: TooltipPlacement = - TooltipPlacement( - contentOffset = style.metrics.tooltipOffset, - alignment = style.metrics.tooltipAlignment, - density = LocalDensity.current, - ), + tooltipPlacement: TooltipPlacement = TooltipPlacement( + contentOffset = style.metrics.tooltipOffset, + alignment = style.metrics.tooltipAlignment, + density = LocalDensity.current, + ), content: @Composable () -> Unit, ) { TooltipArea( @@ -51,13 +50,13 @@ public fun Tooltip( LocalContentColor provides style.colors.content, ) { Box( - modifier = - Modifier.shadow( - elevation = style.metrics.shadowSize, - shape = RoundedCornerShape(style.metrics.cornerSize), - ambientColor = style.colors.shadow, - spotColor = Color.Transparent, - ) + modifier = Modifier + .shadow( + elevation = style.metrics.shadowSize, + shape = RoundedCornerShape(style.metrics.cornerSize), + ambientColor = style.colors.shadow, + spotColor = Color.Transparent, + ) .background( color = style.colors.background, shape = RoundedCornerShape(style.metrics.cornerSize), @@ -69,7 +68,9 @@ public fun Tooltip( ) .padding(style.metrics.contentPadding), ) { - OverrideDarkMode(style.colors.background.isDark()) { tooltip() } + OverrideDarkMode(style.colors.background.isDark()) { + tooltip() + } } } }, @@ -112,12 +113,7 @@ private fun rememberTooltipPositionProvider( density: Density, windowMargin: Dp = 4.dp, ) = - remember( - contentOffset, - alignment, - density, - windowMargin, - ) { + remember(contentOffset, alignment, density, windowMargin) { TooltipPositionProvider( cursorPosition = cursorPosition, contentOffset = contentOffset, @@ -142,13 +138,12 @@ private class TooltipPositionProvider( popupContentSize: IntSize, ): IntOffset = with(density) { - val windowSpaceBounds = - IntRect( - left = windowMargin.roundToPx(), - top = windowMargin.roundToPx(), - right = windowSize.width - windowMargin.roundToPx(), - bottom = windowSize.height - windowMargin.roundToPx(), - ) + val windowSpaceBounds = IntRect( + left = windowMargin.roundToPx(), + top = windowMargin.roundToPx(), + right = windowSize.width - windowMargin.roundToPx(), + bottom = windowSize.height - windowMargin.roundToPx(), + ) val contentOffsetX = contentOffset.x.roundToPx() val contentOffsetY = contentOffset.y.roundToPx() diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/BadgePainter.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/BadgePainter.kt index 8fbee19767..66c229f36e 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/BadgePainter.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/BadgePainter.kt @@ -22,13 +22,17 @@ public class BadgePainter( ) : DelegatePainter(source) { /** - * Optional [Paint] used to draw contents into an offscreen layer in order to apply alpha or - * [ColorFilter] parameters accordingly. If no alpha or [ColorFilter] is provided or the [Painter] - * implementation implements [applyAlpha] and [applyColorFilter] then this paint is not used + * Optional [Paint] used to draw contents into an offscreen layer to + * apply alpha or [ColorFilter] parameters accordingly. If no alpha or + * [ColorFilter] is provided or the [Painter] implementation implements + * [applyAlpha] and [applyColorFilter] then this paint is not used. */ private var layerPaint: Paint? = null - /** Lazily create a [Paint] object or return the existing instance if it is already allocated */ + /** + * Lazily create a [Paint] object or return the existing instance if it is + * already allocated. + */ private fun obtainPaint(): Paint { var target = layerPaint if (target == null) { diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/PainterHint.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/PainterHint.kt index ff40197f58..503dc34895 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/PainterHint.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/PainterHint.kt @@ -6,9 +6,10 @@ import org.w3c.dom.Element /** * A [PainterHint] is a hint for [PainterProvider] on how to load a - * [Painter][androidx.compose.ui.graphics.painter.Painter]. It can used to patch the path of the - * resource being loaded (e.g., for New UI icon path mapping, and handling the dark theme variants), - * replace colors in an SVG based on the theme palette, etc. + * [Painter][androidx.compose.ui.graphics.painter.Painter]. It can used to + * patch the path of the resource being loaded (e.g., for New UI icon path + * mapping, and handling the dark theme variants), replace colors in an SVG + * based on the theme palette, etc. * * Custom implementations are not allowed. There are two types of hints: * * [PainterPathHint] modifies the path of the resource to load @@ -22,7 +23,9 @@ public sealed interface PainterHint { public fun PainterProviderScope.canApply(): Boolean = true - /** An empty [PainterHint], it will be ignored. */ + /** + * An empty [PainterHint], it will be ignored. + */ public companion object None : PainterHint { override fun PainterProviderScope.canApply(): Boolean = false @@ -31,7 +34,9 @@ public sealed interface PainterHint { } } -/** Mark this [PainterHint] just available with SVG images. */ +/** + * Mark this [PainterHint] just available with SVG images. + */ @Immutable public interface SvgPainterHint : PainterHint { @@ -39,20 +44,22 @@ public interface SvgPainterHint : PainterHint { path.substringAfterLast('.').lowercase() == "svg" } -/** Mark this [PainterHint] just available with Bitmap images. */ +/** + * Mark this [PainterHint] just available with Bitmap images. + */ @Immutable public interface BitmapPainterHint : PainterHint { override fun PainterProviderScope.canApply(): Boolean = when (path.substringAfterLast('.').lowercase()) { - "svg", - "xml", - -> false + "svg", "xml" -> false else -> true } } -/** Mark this [PainterHint] just available with XML images. */ +/** + * Mark this [PainterHint] just available with XML images. + */ @Immutable public interface XmlPainterHint : PainterHint { @@ -61,8 +68,9 @@ public interface XmlPainterHint : PainterHint { } /** - * A [PainterHint] that modifies the path of the resource being loaded. Usage examples are applying - * the New UI icon mappings, or picking up dark theme variants of icons. + * A [PainterHint] that modifies the path of the resource being loaded. + * Usage examples are applying the New UI icon mappings, or picking up dark + * theme variants of icons. */ @Immutable public interface PainterPathHint : PainterHint { @@ -74,13 +82,15 @@ public interface PainterPathHint : PainterHint { } /** - * A [PainterHint] that patches the content of SVG resources. It is only applied to SVG resources; - * it doesn't affect other types of resources. + * A [PainterHint] that patches the content of SVG resources. It is only + * applied to SVG resources; it doesn't affect other types of resources. */ @Immutable public interface PainterSvgPatchHint : SvgPainterHint { - /** Patch the SVG content. */ + /** + * Patch the SVG content. + */ public fun PainterProviderScope.patch(element: Element) } @@ -91,9 +101,10 @@ public interface PainterWrapperHint : PainterHint { } /** - * A [PainterHint] that adds a prefix to a resource file name, without changing the rest of the - * path. For example, if the original path is `icons/MyIcon.svg`, and the prefix is `Dark`, the - * patched path will be `icons/DarkMyIcon.svg`. + * A [PainterHint] that adds a prefix to a resource file name, without + * changing the rest of the path. For example, if the original path is + * `icons/MyIcon.svg`, and the prefix is `Dark`, the patched path will be + * `icons/DarkMyIcon.svg`. */ @Immutable public abstract class PainterPrefixHint : PainterPathHint { @@ -112,9 +123,10 @@ public abstract class PainterPrefixHint : PainterPathHint { } /** - * A [PainterHint] that adds a suffix to a resource file name, without changing the rest of the path - * nor the extension. For example, if the original path is `icons/MyIcon.svg`, and the suffix is - * `_dark`, the patched path will be `icons/MyIcon_dark.svg`. + * A [PainterHint] that adds a suffix to a resource file name, without + * changing the rest of the path nor the extension. For example, if the + * original path is `icons/MyIcon.svg`, and the suffix is `_dark`, the + * patched path will be `icons/MyIcon_dark.svg`. */ @Immutable public abstract class PainterSuffixHint : PainterPathHint { diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/PainterHintsProvider.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/PainterHintsProvider.kt index bea3c9a899..5a12ac80a6 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/PainterHintsProvider.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/PainterHintsProvider.kt @@ -19,21 +19,22 @@ import org.jetbrains.jewel.ui.painter.hints.HiDpi public interface PainterHintsProvider { /** - * These hints will be consumed before the hints which are passed as a parameter to - * [PainterProvider.getPainter]. + * These hints will be consumed before the hints which are passed as a + * parameter to [PainterProvider.getPainter]. */ @Composable public fun priorityHints(path: String): List = emptyList() /** - * These hints will be consumed after the hints which are passed as a parameter to - * [PainterProvider.getPainter]. + * These hints will be consumed after the hints which are passed as a + * parameter to [PainterProvider.getPainter]. */ @Composable public fun hints(path: String): List } /** - * The default [PainterHintsProvider] to load dark theme icon variants. It will provide the [Dark] - * hint when [LocalIsDarkTheme][org.jetbrains.jewel.LocalIsDarkTheme] is true. + * The default [PainterHintsProvider] to load dark theme + * icon variants. It will provide the [Dark] hint when + * [LocalIsDarkTheme][org.jetbrains.jewel.LocalIsDarkTheme] is true. */ public object CommonPainterHintsProvider : PainterHintsProvider { @@ -43,4 +44,4 @@ public object CommonPainterHintsProvider : PainterHintsProvider { } public val LocalPainterHintsProvider: ProvidableCompositionLocal = - staticCompositionLocalOf { CommonPainterHintsProvider } + staticCompositionLocalOf { CommonPainterHintsProvider } diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/PainterProvider.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/PainterProvider.kt index 81aca1619d..6ff1972187 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/PainterProvider.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/PainterProvider.kt @@ -6,21 +6,25 @@ import androidx.compose.runtime.State import androidx.compose.ui.graphics.painter.Painter /** - * Provides a [Painter] for an image, which may be transformed by the provided hints. + * Provides a [Painter] for an image, which may be transformed by the + * provided hints. * - * Note: implementations of this interface should handle the passed [PainterHint]s correctly. For - * now, this means calling [PainterPathHint.patch] and [PainterSvgPatchHint.patch]. Most likely, a - * [PainterProvider] should also hold the resource path and [ClassLoader] references. + * Note: implementations of this interface should handle the + * passed [PainterHint]s correctly. For now, this means calling + * [PainterPathHint.patch] and [PainterSvgPatchHint.patch]. Most likely, a + * [PainterProvider] should also hold the resource path and [ClassLoader] + * references. */ @Immutable public interface PainterProvider { /** - * Provides a [Painter] using the specified [PainterHint]s. The painters are - * [remember][androidx.compose.runtime.remember]ed and this function can be called multiple times - * for the same data. + * Provides a [Painter] using the specified [PainterHint]s. The painters + * are [remember][androidx.compose.runtime.remember]ed and this function + * can be called multiple times for the same data. * - * Depending on the implementation, errors may be suppressed and a replacement painter provided. + * Depending on the implementation, errors may be suppressed and a + * replacement painter provided. */ @Composable public fun getPainter(vararg hints: PainterHint): State } diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/ResizedPainter.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/ResizedPainter.kt index 9af2d6b972..3204b08aff 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/ResizedPainter.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/ResizedPainter.kt @@ -4,7 +4,7 @@ import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.drawscope.DrawScope import androidx.compose.ui.graphics.painter.Painter -public class ResizedPainter(private val delegate: Painter, private val size: Size) : DelegatePainter(delegate) { +public class ResizedPainter(delegate: Painter, private val size: Size) : DelegatePainter(delegate) { override val intrinsicSize: Size get() = size diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/ResourcePainterProvider.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/ResourcePainterProvider.kt index 1f3525ca4e..c11b2a2a1a 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/ResourcePainterProvider.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/ResourcePainterProvider.kt @@ -35,14 +35,15 @@ import javax.xml.transform.stream.StreamResult private val errorPainter = ColorPainter(Color.Magenta) /** - * Provide [Painter] by resources in the module and jars, it use the ResourceResolver to load - * resources. + * Provide [Painter] by resources in the module and jars, it use the + * ResourceResolver to load resources. * - * It will cache the painter by [PainterHint]s, so it is safe to call [getPainter] multiple times. + * It will cache the painter by [PainterHint]s, so it is safe to call + * [getPainter] multiple times. * - * If a resource fails to load, it will be silently replaced by a magenta color painter, and the - * exception logged. If Jewel is in [debug mode][inDebugMode], however, exceptions will not be - * suppressed. + * If a resource fails to load, it will be silently replaced by a + * magenta color painter, and the exception logged. If Jewel is in + * [debug mode][inDebugMode], however, exceptions will not be suppressed. */ @Immutable public class ResourcePainterProvider( diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/badge/BadgeShape.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/badge/BadgeShape.kt index cb59d4501f..c3b29038a0 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/badge/BadgeShape.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/badge/BadgeShape.kt @@ -1,5 +1,6 @@ package org.jetbrains.jewel.ui.painter.badge +import androidx.compose.runtime.Immutable import androidx.compose.ui.geometry.Rect import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.Outline @@ -7,13 +8,10 @@ import androidx.compose.ui.graphics.Shape import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.LayoutDirection +@Immutable public interface BadgeShape : Shape { - public fun createHoleOutline( - size: Size, - layoutDirection: LayoutDirection, - density: Density, - ): Outline + public fun createHoleOutline(size: Size, layoutDirection: LayoutDirection, density: Density): Outline } internal val emptyOutline = Outline.Rectangle(Rect.Zero) diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/badge/DotBadgeShape.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/badge/DotBadgeShape.kt index 77b15b7c71..74ce8162ed 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/badge/DotBadgeShape.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/badge/DotBadgeShape.kt @@ -1,5 +1,6 @@ package org.jetbrains.jewel.ui.painter.badge +import androidx.compose.runtime.Immutable import androidx.compose.ui.geometry.CornerRadius import androidx.compose.ui.geometry.RoundRect import androidx.compose.ui.geometry.Size @@ -8,7 +9,10 @@ import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.LayoutDirection import org.jetbrains.jewel.foundation.GenerateDataFunctions -/** @see com.intellij.ui.BadgeDotProvider */ +/** + * @see com.intellij.ui.BadgeDotProvider + */ +@Immutable @GenerateDataFunctions public class DotBadgeShape( public val x: Float = 16.5f / 20, diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/hints/Badge.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/hints/Badge.kt index 1ea132ac8c..eda3c14bf2 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/hints/Badge.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/hints/Badge.kt @@ -3,39 +3,21 @@ package org.jetbrains.jewel.ui.painter.hints import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.isSpecified import androidx.compose.ui.graphics.painter.Painter +import org.jetbrains.jewel.foundation.GenerateDataFunctions import org.jetbrains.jewel.ui.painter.BadgePainter import org.jetbrains.jewel.ui.painter.PainterHint import org.jetbrains.jewel.ui.painter.PainterProviderScope import org.jetbrains.jewel.ui.painter.PainterWrapperHint import org.jetbrains.jewel.ui.painter.badge.BadgeShape -private class BadgeImpl(private val color: Color, private val shape: BadgeShape) : - PainterWrapperHint { +@GenerateDataFunctions +private class BadgeImpl( + private val color: Color, + private val shape: BadgeShape, +) : PainterWrapperHint { override fun PainterProviderScope.wrap(painter: Painter): Painter = BadgePainter(painter, color, shape) - - override fun toString(): String = "Badge(color=$color, shape=$shape)" - - override fun hashCode(): Int { - var result = color.hashCode() - result = 31 * result + shape.hashCode() - return result - } - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is BadgeImpl) return false - - if (color != other.color) return false - if (shape != other.shape) return false - - return true - } } public fun Badge(color: Color, shape: BadgeShape): PainterHint = - if (color.isSpecified) { - BadgeImpl(color, shape) - } else { - PainterHint.None - } + if (color.isSpecified) BadgeImpl(color, shape) else PainterHint.None diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/hints/DarkOrStroke.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/hints/DarkOrStroke.kt index 9d2c956c71..a1721c498f 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/hints/DarkOrStroke.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/hints/DarkOrStroke.kt @@ -3,6 +3,7 @@ package org.jetbrains.jewel.ui.painter.hints import androidx.compose.runtime.Immutable import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.isSpecified +import org.jetbrains.jewel.foundation.GenerateDataFunctions import org.jetbrains.jewel.ui.painter.PainterHint import org.jetbrains.jewel.ui.painter.PainterProviderScope import org.jetbrains.jewel.ui.painter.PainterSuffixHint @@ -20,6 +21,7 @@ private object DarkImpl : PainterSuffixHint() { } @Immutable +@GenerateDataFunctions private class StrokeImpl(private val color: Color) : PainterSuffixHint(), PainterSvgPatchHint { override fun PainterProviderScope.suffix(): String = "_stroke" @@ -32,19 +34,6 @@ private class StrokeImpl(private val color: Color) : PainterSuffixHint(), Painte override fun PainterProviderScope.canApply(): Boolean = true - override fun toString(): String = "Stroke(color=$color)" - - override fun hashCode(): Int = color.hashCode() - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is StrokeImpl) return false - - if (color != other.color) return false - - return true - } - private val backgroundPalette = listOf( Color(0xFFEBECF0), Color(0xFFE7EFFD), @@ -74,15 +63,7 @@ private class StrokeImpl(private val color: Color) : PainterSuffixHint(), Painte } public fun Stroke(color: Color): PainterHint = - if (color.isSpecified) { - StrokeImpl(color) - } else { - PainterHint.None - } + if (color.isSpecified) StrokeImpl(color) else PainterHint.None public fun Dark(isDark: Boolean = true): PainterHint = - if (isDark) { - DarkImpl - } else { - PainterHint.None - } + if (isDark) DarkImpl else PainterHint.None diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/hints/Override.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/hints/Override.kt index 9b136b1ba9..e9b82493df 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/hints/Override.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/hints/Override.kt @@ -1,25 +1,16 @@ package org.jetbrains.jewel.ui.painter.hints +import androidx.compose.runtime.Immutable +import org.jetbrains.jewel.foundation.GenerateDataFunctions import org.jetbrains.jewel.ui.painter.PainterHint import org.jetbrains.jewel.ui.painter.PainterPathHint import org.jetbrains.jewel.ui.painter.PainterProviderScope +@Immutable +@GenerateDataFunctions private class OverrideImpl(private val iconOverride: Map) : PainterPathHint { override fun PainterProviderScope.patch(): String = iconOverride[path] ?: path - - override fun toString(): String = "Override(${iconOverride.hashCode()})" - - override fun hashCode(): Int = iconOverride.hashCode() - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is OverrideImpl) return false - - if (iconOverride != other.iconOverride) return false - - return true - } } public fun Override(override: Map): PainterHint = diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/hints/Palette.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/hints/Palette.kt index 175fb5e788..4eb40b6990 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/hints/Palette.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/hints/Palette.kt @@ -2,6 +2,7 @@ package org.jetbrains.jewel.ui.painter.hints import androidx.compose.runtime.Immutable import androidx.compose.ui.graphics.Color +import org.jetbrains.jewel.foundation.GenerateDataFunctions import org.jetbrains.jewel.ui.painter.PainterHint import org.jetbrains.jewel.ui.painter.PainterProviderScope import org.jetbrains.jewel.ui.painter.PainterSvgPatchHint @@ -10,24 +11,12 @@ import org.w3c.dom.Element import kotlin.math.roundToInt @Immutable +@GenerateDataFunctions private class PaletteImpl(val map: Map) : PainterSvgPatchHint { override fun PainterProviderScope.patch(element: Element) { element.patchPalette(map) } - - override fun toString(): String = "Palette(${map.hashCode()})" - - override fun hashCode(): Int = map.hashCode() - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is PaletteImpl) return false - - if (map != other.map) return false - - return true - } } internal fun Element.patchPalette(fill: Map, stroke: Map = fill) { @@ -73,34 +62,34 @@ private fun fromHexOrNull(rawColor: String, alpha: Float): Color? { val alphaOverride = alpha.takeIf { it != 1.0f }?.let { (it * 255).roundToInt() } return when (length) { - 3 -> - Color( - red = rawColor.substring(startPos, startPos + 1).toInt(16), - green = rawColor.substring(startPos + 1, startPos + 2).toInt(16), - blue = rawColor.substring(startPos + 2, startPos + 3).toInt(16), - alpha = alphaOverride ?: 255, - ) - 4 -> - Color( - red = rawColor.substring(startPos, startPos + 1).toInt(16), - green = rawColor.substring(startPos + 1, startPos + 2).toInt(16), - blue = rawColor.substring(startPos + 2, startPos + 3).toInt(16), - alpha = alphaOverride ?: rawColor.substring(startPos + 3, startPos + 4).toInt(16), - ) - 6 -> - Color( - red = rawColor.substring(startPos, startPos + 2).toInt(16), - green = rawColor.substring(startPos + 2, startPos + 4).toInt(16), - blue = rawColor.substring(startPos + 4, startPos + 6).toInt(16), - alpha = alphaOverride ?: 255, - ) - 8 -> - Color( - red = rawColor.substring(startPos, startPos + 2).toInt(16), - green = rawColor.substring(startPos + 2, startPos + 4).toInt(16), - blue = rawColor.substring(startPos + 4, startPos + 6).toInt(16), - alpha = alphaOverride ?: rawColor.substring(startPos + 6, startPos + 8).toInt(16), - ) + 3 -> Color( + red = rawColor.substring(startPos, startPos + 1).toInt(16), + green = rawColor.substring(startPos + 1, startPos + 2).toInt(16), + blue = rawColor.substring(startPos + 2, startPos + 3).toInt(16), + alpha = alphaOverride ?: 255, + ) + + 4 -> Color( + red = rawColor.substring(startPos, startPos + 1).toInt(16), + green = rawColor.substring(startPos + 1, startPos + 2).toInt(16), + blue = rawColor.substring(startPos + 2, startPos + 3).toInt(16), + alpha = alphaOverride ?: rawColor.substring(startPos + 3, startPos + 4).toInt(16), + ) + + 6 -> Color( + red = rawColor.substring(startPos, startPos + 2).toInt(16), + green = rawColor.substring(startPos + 2, startPos + 4).toInt(16), + blue = rawColor.substring(startPos + 4, startPos + 6).toInt(16), + alpha = alphaOverride ?: 255, + ) + + 8 -> Color( + red = rawColor.substring(startPos, startPos + 2).toInt(16), + green = rawColor.substring(startPos + 2, startPos + 4).toInt(16), + blue = rawColor.substring(startPos + 4, startPos + 6).toInt(16), + alpha = alphaOverride ?: rawColor.substring(startPos + 6, startPos + 8).toInt(16), + ) + else -> null } } diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/hints/Selected.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/hints/Selected.kt index 1715a2bcae..938afd5a2a 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/hints/Selected.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/hints/Selected.kt @@ -15,10 +15,6 @@ private object SelectedImpl : PainterSuffixHint() { } public fun Selected(selected: Boolean = true): PainterHint = - if (selected) { - SelectedImpl - } else { - PainterHint.None - } + if (selected) SelectedImpl else PainterHint.None public fun Selected(state: SelectableComponentState): PainterHint = Selected(state.isSelected) diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/hints/Size.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/hints/Size.kt index c29f2003ae..fdf713c237 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/hints/Size.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/hints/Size.kt @@ -3,6 +3,7 @@ package org.jetbrains.jewel.ui.painter.hints import androidx.compose.runtime.Immutable import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.unit.dp +import org.jetbrains.jewel.foundation.GenerateDataFunctions import org.jetbrains.jewel.ui.painter.PainterHint import org.jetbrains.jewel.ui.painter.PainterProviderScope import org.jetbrains.jewel.ui.painter.PainterSuffixHint @@ -11,6 +12,7 @@ import org.jetbrains.jewel.ui.painter.ResizedPainter import org.jetbrains.jewel.ui.painter.SvgPainterHint @Immutable +@GenerateDataFunctions private class SizeImpl( private val width: Int, private val height: Int, @@ -31,24 +33,6 @@ private class SizeImpl( androidx.compose.ui.geometry.Size(width.dp.toPx(), height.dp.toPx()), ) } - - override fun toString(): String = "Size(width=$width, height=$height)" - - override fun hashCode(): Int { - var result = width - result = 31 * result + height - return result - } - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is SizeImpl) return false - - if (width != other.width) return false - if (height != other.height) return false - - return true - } } public fun Size(width: Int, height: Int = width): PainterHint { diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/hints/Stateful.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/hints/Stateful.kt index 1b35cee299..4fb2bbac59 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/hints/Stateful.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/painter/hints/Stateful.kt @@ -1,6 +1,7 @@ package org.jetbrains.jewel.ui.painter.hints import androidx.compose.runtime.Immutable +import org.jetbrains.jewel.foundation.GenerateDataFunctions import org.jetbrains.jewel.foundation.state.FocusableComponentState import org.jetbrains.jewel.foundation.state.InteractiveComponentState import org.jetbrains.jewel.ui.painter.PainterHint @@ -8,6 +9,7 @@ import org.jetbrains.jewel.ui.painter.PainterProviderScope import org.jetbrains.jewel.ui.painter.PainterSuffixHint @Immutable +@GenerateDataFunctions private class StatefulImpl(private val state: InteractiveComponentState) : PainterSuffixHint() { override fun PainterProviderScope.suffix(): String = buildString { @@ -21,19 +23,6 @@ private class StatefulImpl(private val state: InteractiveComponentState) : Paint append("Disabled") } } - - override fun toString(): String = "Stateful(state=$state)" - - override fun hashCode(): Int = state.hashCode() - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is StatefulImpl) return false - - if (state != other.state) return false - - return true - } } public fun Stateful(state: InteractiveComponentState): PainterHint = StatefulImpl(state) diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/util/ColorExtensions.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/util/ColorExtensions.kt index 5968d4380d..b43e1f8aad 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/util/ColorExtensions.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/util/ColorExtensions.kt @@ -4,7 +4,10 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.luminance import kotlin.math.roundToInt -/** Converts a [Color] to a RGBA formatted color('#RRGGBBAA') hex string, etc. #FFFFFF1A. */ +/** + * Converts a [Color] to a RGBA formatted color `#RRGGBBAA` hex string; + * e.g., `#FFFFFF1A` (a translucent white). + */ public fun Color.toRgbaHexString(): String { val r = Integer.toHexString((red * 255).roundToInt()) val g = Integer.toHexString((green * 255).roundToInt()) @@ -23,7 +26,10 @@ public fun Color.toRgbaHexString(): String { } } -/** Converts a RGBA formatted color('#RRGGBBAA') hex string to a [Color], etc. #FFFFFF1A. */ +/** + * Converts a RGBA formatted color `#RRGGBBAA` hex string to a [Color]; + * e.g., `#FFFFFF1A` (a translucent white). + */ public fun Color.Companion.fromRGBAHexStringOrNull(rgba: String): Color? = rgba .lowercase() @@ -40,4 +46,8 @@ public fun Color.Companion.fromRGBAHexStringOrNull(rgba: String): Color? = ?.toLongOrNull(radix = 16) ?.let { Color(it) } -public fun Color.isDark(): Boolean = (luminance() + 0.05) / 0.05 < 4.5 +/** + * Heuristically determines if the color can be thought of as "dark". + */ +public fun Color.isDark(): Boolean = + (luminance() + 0.05) / 0.05 < 4.5 diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/util/Debug.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/util/Debug.kt index bf73e4fdea..1dd91b0cd3 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/util/Debug.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/util/Debug.kt @@ -3,8 +3,8 @@ package org.jetbrains.jewel.ui.util import org.jetbrains.jewel.foundation.InternalJewelApi /** - * Determines whether we're in debug mode. This should not be used in the bridge for logging; - * instead, you should use the IDE logger. + * Determines whether we're in debug mode. This should not be used in the + * bridge for logging; instead, you should use the IDE logger. */ @InternalJewelApi public val inDebugMode: Boolean by lazy { diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/util/ModifierExtensions.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/util/ModifierExtensions.kt index 3407967a96..61208e6f0e 100644 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/util/ModifierExtensions.kt +++ b/ui/src/main/kotlin/org/jetbrains/jewel/ui/util/ModifierExtensions.kt @@ -2,15 +2,10 @@ package org.jetbrains.jewel.ui.util import androidx.compose.ui.Modifier -@Deprecated( - "Use thenIf instead", - ReplaceWith("thenIf(precondition, action)"), -) -public inline fun Modifier.appendIf( - precondition: Boolean, - action: Modifier.() -> Modifier, -): Modifier = thenIf(precondition, action) - +/** + * Conditionally applies the [action] to the receiver [Modifier], if + * [precondition] is true. Returns the receiver as-is otherwise. + */ public inline fun Modifier.thenIf( precondition: Boolean, action: Modifier.() -> Modifier, diff --git a/ui/src/main/kotlin/org/jetbrains/jewel/ui/util/SpinnerProgressIconGenerator.kt b/ui/src/main/kotlin/org/jetbrains/jewel/ui/util/SpinnerProgressIconGenerator.kt deleted file mode 100644 index bcc7c57af7..0000000000 --- a/ui/src/main/kotlin/org/jetbrains/jewel/ui/util/SpinnerProgressIconGenerator.kt +++ /dev/null @@ -1,107 +0,0 @@ -package org.jetbrains.jewel.ui.util - -public object SpinnerProgressIconGenerator { - - private val opacityList = listOf(1.0f, 0.93f, 0.78f, 0.69f, 0.62f, 0.48f, 0.38f, 0.0f) - - private val rotations = listOf(0, -45, 0, 45, 0, -45, 0, 45) - - // for a 16x16 icon - internal val points = - listOf( - 7f to 1f, - 2.34961f to 3.76416f, - 1f to 7f, - 5.17871f to 9.40991f, - 7f to 11f, - 9.41016f to 10.8242f, - 11f to 7f, - 12.2383f to 2.34961f, - ) - - private fun StringBuilder.closeTag() = append("") - - private fun StringBuilder.openTag(sizePx: Int) = - append( - "", - ) - - private fun getSvgPlainTextIcon( - step: Int, - pointList: List>, - colorHex: String, - thickness: Int = 2, - length: Int = 4, - cornerRadius: Int = 1, - ) = buildString { - openTag(16) - appendLine() - for (index in 0..opacityList.lastIndex) { - val currentIndex = (index + step + 1) % opacityList.size - val currentOpacity = opacityList[currentIndex] - if (currentOpacity == 0.0f) continue - drawElement( - colorHex = colorHex, - opacity = currentOpacity, - x = pointList[index].first, - y = pointList[index].second, - width = thickness, - height = length, - rx = cornerRadius, - rotation = rotations[index], - ) - } - closeTag() - appendLine() - } - - private fun StringBuilder.drawElement( - colorHex: String, - opacity: Float, - x: Float, - y: Float, - width: Int, - height: Int, - rx: Int, - rotation: Int, - ) { - append( - "\n") - } - - internal fun getPlainTextSvgList(colorHex: String, size: Int) = buildList { - val scaleFactor = size / 16f - for (index in 0..opacityList.lastIndex) { - if (size == 16) { - add(getSvgPlainTextIcon(index, points, colorHex)) - } else { - add( - getSvgPlainTextIcon( - index, - points.map { it.first * scaleFactor to it.second * scaleFactor }, - colorHex, - thickness = (2 * scaleFactor).toInt().coerceAtLeast(1), - length = (4 * scaleFactor).toInt().coerceAtLeast(1), - cornerRadius = (2 * scaleFactor).toInt().coerceAtLeast(1), - ), - ) - } - } - } - - public object Small { - - public fun generateRawSvg(colorHex: String): List = - getPlainTextSvgList(colorHex = colorHex, size = 16) - } - - public object Big { - - public fun generateRawSvg(colorHex: String): List = - getPlainTextSvgList(colorHex = colorHex, size = 32) - } -} diff --git a/ui/src/test/kotlin/org/jetbrains/jewel/BasicJewelUiTest.kt b/ui/src/test/kotlin/org/jetbrains/jewel/BasicJewelUiTest.kt index 6a120860ff..e8bde5213b 100644 --- a/ui/src/test/kotlin/org/jetbrains/jewel/BasicJewelUiTest.kt +++ b/ui/src/test/kotlin/org/jetbrains/jewel/BasicJewelUiTest.kt @@ -9,7 +9,8 @@ import org.junit.Rule open class BasicJewelUiTest { - @get:Rule val composeRule = createComposeRule() + @get:Rule + val composeRule = createComposeRule() @Suppress("ImplicitUnitReturnType") protected fun runComposeTest(