Skip to content

Commit

Permalink
Also load iconColorsOnSelection from theme
Browse files Browse the repository at this point in the history
  • Loading branch information
rock3r committed Sep 12, 2023
1 parent 5ca9b40 commit eef5112
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 14 deletions.
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 @@ -159,6 +158,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 @@ -60,6 +60,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 Down Expand Up @@ -120,4 +121,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
Expand Up @@ -7,6 +7,7 @@ interface IntelliJThemeIconData {

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

@Immutable
Expand All @@ -16,5 +17,8 @@ object EmptyThemeIconData : IntelliJThemeIconData {

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=[])"
}
28 changes: 21 additions & 7 deletions core/src/main/kotlin/org/jetbrains/jewel/PaletteMapper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,41 @@ import androidx.compose.runtime.Immutable
import androidx.compose.ui.graphics.Color

@Immutable
class PaletteMapper(val colorOverrides: Map<Color, Color>) {

fun mapColor(originalColor: Color): Color =
mapColorOrNull(originalColor) ?: originalColor
class PaletteMapper(
private val colorOverrides: Map<Color, Color>,
private val selectedColorOverrides: Map<Color, Color>,
) {

fun mapColorOrNull(originalColor: Color): Color? {
if (colorOverrides.isEmpty()) return null

return colorOverrides[originalColor]
}

fun mapSelectedColorOrNull(originalColor: Color): Color? {
if (selectedColorOverrides.isEmpty()) return null

return selectedColorOverrides[originalColor]
}

override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false

other as PaletteMapper

return colorOverrides == other.colorOverrides
if (colorOverrides != other.colorOverrides) return false
if (selectedColorOverrides != other.selectedColorOverrides) return false

return true
}

override fun hashCode(): Int = colorOverrides.hashCode()
override fun hashCode(): Int {
var result = colorOverrides.hashCode()
result = 31 * result + selectedColorOverrides.hashCode()
return result
}

override fun toString() = "PaletteMapper(colorOverrides=$colorOverrides)"
override fun toString(): String =
"PaletteMapper(colorOverrides=$colorOverrides, selectedColorOverrides=$selectedColorOverrides)"
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,15 @@ object PaletteMapperFactory {
colorPalette: IntelliJThemeColorPalette,
): PaletteMapper {
val overrides = computeOverrides(isDark, iconData.colorPalette, colorPalette)
return PaletteMapper(overrides)
val selectionOverrides = iconData.selectionColorPalette
.mapNotNull { (key, value) ->
val keyColor = key.toColorOrNull() ?: return@mapNotNull null
val valueColor = value.toColorOrNull() ?: return@mapNotNull null
keyColor to valueColor
}
.toMap()

return PaletteMapper(overrides, selectionOverrides)
}

// 1. Load the icons.ColorPalette map from the theme JSON, if it exists, and for each key:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
package org.jetbrains.jewel.bridge

import androidx.compose.runtime.Immutable
import com.intellij.ide.ui.LafManager
import com.intellij.ide.ui.UITheme
import com.intellij.ide.ui.laf.UIThemeBasedLookAndFeelInfo
import com.intellij.openapi.diagnostic.thisLogger
import org.jetbrains.jewel.IntelliJThemeIconData
import java.lang.reflect.Field

@Immutable
internal class BridgeIconData(
override val iconOverrides: Map<String, String>,
override val colorPalette: Map<String, String>,
override val selectionColorPalette: Map<String, String>,
) : IntelliJThemeIconData {

override fun equals(other: Any?): Boolean {
Expand All @@ -17,22 +23,55 @@ internal class BridgeIconData(

if (iconOverrides != other.iconOverrides) return false
if (colorPalette != other.colorPalette) return false
if (selectionColorPalette != other.selectionColorPalette) return false

return true
}

override fun hashCode(): Int {
var result = iconOverrides.hashCode()
result = 31 * result + colorPalette.hashCode()
result = 31 * result + selectionColorPalette.hashCode()
return result
}

override fun toString(): String =
"BridgeIconData(iconOverrides=$iconOverrides, colorPalette=$colorPalette)"
"BridgeIconData(iconOverrides=$iconOverrides, colorPalette=$colorPalette, " +
"selectionColorPalette=$selectionColorPalette)"

companion object {

// TODO retrieve icon data from Swing
fun readFromLaF() = BridgeIconData(emptyMap(), emptyMap())
fun readFromLaF(): BridgeIconData {
val classUITheme = UITheme::class.java
val iconMap: Map<String, String> = readMapField(classUITheme.getDeclaredField("icons"))
val selectionColorPalette: Map<String, String> =
readMapField(classUITheme.getDeclaredField("selectionColorPalette"))

val colorPalette = UITheme.getColorPalette()
return BridgeIconData(iconMap.filterKeys { it != "ColorPalette" }, colorPalette, selectionColorPalette)
}

private fun readMapField(field: Field): Map<String, String> {
@Suppress("DEPRECATION") // We don't have an alternative API to use
val wasAccessible = field.isAccessible
field.isAccessible = true

val iconMap: Map<String, String> = try {
val laf = LafManager.getInstance().currentLookAndFeel as? UIThemeBasedLookAndFeelInfo

if (laf != null) {
@Suppress("UNCHECKED_CAST")
field.get(laf.theme) as? Map<String, String> ?: emptyMap()
} else {
emptyMap()
}
} catch (e: IllegalAccessException) {
thisLogger().warn("Error while retrieving LaF", e)
emptyMap()
} finally {
field.isAccessible = wasAccessible
}
return iconMap
}
}
}

0 comments on commit eef5112

Please sign in to comment.