Skip to content

Commit

Permalink
Fix icon loading in IDE (#112)
Browse files Browse the repository at this point in the history
* Fix icon loading in IDE

* Fix icon loading in standalone modules

* Fix static analysis

* SwingBridgeService will now wait 20 milliseconds before reading the theme and then will retry due to Swing possible race conditions.

* Fixed SLC focus system, added right color for unfocused selected items in the LazyTree.

* Partially fix icon mapping

Something still isn't working well — icon states may need to be applied
_after_ mapping, need to check as it breaks in those cases.

Checkboxes and radio buttons also use the old UI icons, not sure why
they don't get mapped.

* Add fallback path for icon loading

* Update project settings

* Also load iconColorsOnSelection from theme

* Fix crash in standalone sample

* Clean up painter provider usage

* Re-do icon tinting logic, better match Swing

* Fix tree crashing in sample (see #114)

Also reformat/cleanup after rebase on main

---------

Co-authored-by: Lamberto Basti <[email protected]>
  • Loading branch information
rock3r and lamba92 authored Sep 15, 2023
1 parent 0ecd7fd commit 0cdfaa1
Show file tree
Hide file tree
Showing 48 changed files with 1,123 additions and 604 deletions.
2 changes: 2 additions & 0 deletions .idea/detekt.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions .idea/externalDependencies.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions buildSrc/src/main/kotlin/jewel.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
@file:Suppress("UnstableApiUsage")

import io.gitlab.arturbosch.detekt.Detekt
import org.gradle.api.attributes.Usage
import org.jmailen.gradle.kotlinter.tasks.LintTask

plugins {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ internal object IntUiThemeDescriptorReader {
) =
FileSpec.builder(className).apply {
indent(" ")
this.
addFileComment("Generated by the Jewel Int UI Palette Generator\n")
this.addFileComment("Generated by the Jewel Int UI Palette Generator\n")
addFileComment("Generated from the IntelliJ Platform version $ideaVersion\n")
addFileComment("Source: $descriptorUrl")

Expand Down Expand Up @@ -78,6 +77,23 @@ internal object IntUiThemeDescriptorReader {
}.forEach { (group, colors) ->
readColorGroup(className, group, colors)
}

val rawMapProperty = PropertySpec
.builder(
"rawMap",
Map::class.asClassName().parameterizedBy(String::class.asClassName(), colorClassName),
KModifier.OVERRIDE
)
.initializer(
colors
.map { (key, value) ->
val colorHexString = value.replace("#", "0xFF")
CodeBlock.of("%S to Color(%L)", key, colorHexString)
}
.joinToCode(prefix = "mapOf(", separator = ",\n", suffix = ")")
)
.build()
addProperty(rawMapProperty)
}.build())

addProperty(
Expand Down Expand Up @@ -159,6 +175,7 @@ internal object IntUiThemeDescriptorReader {
}

addProperty(createOverrideStringMapProperty("iconOverrides", iconOverrides))
addProperty(createOverrideStringMapProperty("selectionColorPalette", theme.iconColorsOnSelection))
}.build())

addProperty(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction
Expand All @@ -27,30 +28,32 @@ import java.net.URL

abstract class IntelliJThemeGeneratorPlugin : Plugin<Project> {

final override fun apply(target: Project): Unit = with(target) {
val extension = ThemeGeneratorContainer(container<ThemeGeneration> { ThemeGeneration(it, project) })
extensions.add("intelliJThemeGenerator", extension)

extension.all {
val task = tasks.register<IntelliJThemeGeneratorTask>("generate${GUtil.toCamelCase(name)}Theme") {
outputFile.set(targetDir.file(this@all.themeClassName.map {
val className = ClassName.bestGuess(it)
className.packageName.replace(".", "/")
.plus("/${className.simpleName}.kt")
}))
themeClassName.set(this@all.themeClassName)
ideaVersion.set(this@all.ideaVersion)
themeFile.set(this@all.themeFile)
}
tasks.withType<BaseKotlinCompile> {
dependsOn(task)
}
tasks.withType<Detekt> {
dependsOn(task)
}
pluginManager.withPlugin("org.jetbrains.kotlin.jvm") {
extensions.getByType<KotlinJvmProjectExtension>().apply {
sourceSets["main"].kotlin.srcDir(targetDir)
final override fun apply(target: Project) {
with(target) {
val extension = ThemeGeneratorContainer(container<ThemeGeneration> { ThemeGeneration(it, project) })
extensions.add("intelliJThemeGenerator", extension)

extension.all {
val task = tasks.register<IntelliJThemeGeneratorTask>("generate${GUtil.toCamelCase(name)}Theme") {
outputFile.set(targetDir.file(this@all.themeClassName.map {
val className = ClassName.bestGuess(it)
className.packageName.replace(".", "/")
.plus("/${className.simpleName}.kt")
}))
themeClassName.set(this@all.themeClassName)
ideaVersion.set(this@all.ideaVersion)
themeFile.set(this@all.themeFile)
}
tasks.withType<BaseKotlinCompile> {
dependsOn(task)
}
tasks.withType<Detekt> {
dependsOn(task)
}
pluginManager.withPlugin("org.jetbrains.kotlin.jvm") {
extensions.getByType<KotlinJvmProjectExtension>().apply {
sourceSets["main"].kotlin.srcDir(targetDir)
}
}
}
}
Expand All @@ -60,6 +63,7 @@ abstract class IntelliJThemeGeneratorPlugin : Plugin<Project> {
class ThemeGeneratorContainer(container: NamedDomainObjectContainer<ThemeGeneration>) : NamedDomainObjectContainer<ThemeGeneration> by container

class ThemeGeneration(val name: String, project: Project) {

val targetDir: DirectoryProperty = project.objects.directoryProperty()
.convention(project.layout.buildDirectory.dir("generated/theme"))
val ideaVersion = project.objects.property<String>()
Expand All @@ -71,7 +75,7 @@ class ThemeGeneration(val name: String, project: Project) {
open class IntelliJThemeGeneratorTask : DefaultTask() {

@get:OutputFile
val outputFile = project.objects.fileProperty()
val outputFile: RegularFileProperty = project.objects.fileProperty()

@get:Input
val ideaVersion = project.objects.property<String>()
Expand Down Expand Up @@ -120,4 +124,5 @@ data class IntellijThemeDescriptor(
val colors: Map<String, String> = emptyMap(),
val ui: Map<String, JsonElement> = emptyMap(),
val icons: Map<String, JsonElement> = emptyMap(),
val iconColorsOnSelection: Map<String, String> = emptyMap(),
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.jetbrains.jewel

interface ClassLoaderProvider {

val classLoaders: List<ClassLoader>
}
119 changes: 0 additions & 119 deletions core/src/main/kotlin/org/jetbrains/jewel/IntelliJSvgLoader.kt

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ import androidx.compose.ui.graphics.Color
@Stable
interface IntelliJThemeColorPalette {

fun lookup(colorKey: String): Color?
fun lookup(colorKey: String): Color? = rawMap[colorKey]

val rawMap: Map<String, Color>
}

@Immutable
object EmptyThemeColorPalette : IntelliJThemeColorPalette {

override fun lookup(colorKey: String): Color? = null
override val rawMap: Map<String, Color> = emptyMap()
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,48 @@
package org.jetbrains.jewel

import androidx.compose.runtime.Immutable
import androidx.compose.ui.graphics.Color

@Immutable
interface IntelliJThemeIconData {

val iconOverrides: Map<String, String>
val colorPalette: Map<String, String>
val selectionColorPalette: Map<String, String>

fun selectionColorMapping() =
selectionColorPalette.mapNotNull { (key, value) ->
val keyColor = key.toColorOrNull() ?: return@mapNotNull null
val valueColor = value.toColorOrNull() ?: return@mapNotNull null
keyColor to valueColor
}.toMap()
}

internal fun String.toColorOrNull() =
lowercase()
.removePrefix("#")
.removePrefix("0x")
.let {
when (it.length) {
3 -> "ff${it[0]}${it[0]}${it[1]}${it[1]}${it[2]}${it[2]}"
4 -> "${it[0]}${it[0]}${it[1]}${it[1]}${it[2]}${it[2]}${it[3]}${it[3]}"
6 -> "ff$it"
8 -> it
else -> null
}
}
?.toLongOrNull(radix = 16)
?.let { Color(it) }

@Immutable
object EmptyThemeIconData : IntelliJThemeIconData {

override val iconOverrides: Map<String, String> = emptyMap()

override val colorPalette: Map<String, String> = emptyMap()

override fun toString() = "EmptyThemeIconData(iconOverrides=[], colorPalette=[])"
override val selectionColorPalette: Map<String, String> = emptyMap()

override fun toString() =
"EmptyThemeIconData(iconOverrides=[], colorPalette=[], selectionColorPalette=[])"
}
Loading

0 comments on commit 0cdfaa1

Please sign in to comment.