Skip to content

Commit

Permalink
Fix icon loading and errors in bridge for 241
Browse files Browse the repository at this point in the history
  • Loading branch information
rock3r committed Feb 2, 2024
1 parent 003eb1e commit a941970
Show file tree
Hide file tree
Showing 42 changed files with 701 additions and 268 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import org.gradle.api.tasks.TaskAction
import org.gradle.kotlin.dsl.property
import org.gradle.kotlin.dsl.setProperty
import java.io.File
import java.net.URL
import java.net.URI

open class StudioVersionsGenerationExtension(project: Project) {

Expand Down Expand Up @@ -69,7 +69,7 @@ open class AndroidStudioReleasesGeneratorTask : DefaultTask() {
"Registered resources directories:\n" +
lookupDirs.joinToString("\n") { " * ${it.absolutePath}" }
)
val releases = URL(url).openStream()
val releases = URI.create(url).toURL().openStream()
.use { json.decodeFromStream<ApiAndroidStudioReleases>(it) }

val className = ClassName.bestGuess(STUDIO_RELEASES_OUTPUT_CLASS_NAME)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import org.gradle.api.DefaultTask
import org.gradle.api.GradleException
import org.gradle.api.tasks.TaskAction
import java.io.IOException
import java.net.URL
import java.net.URI

open class CheckIdeaVersionTask : DefaultTask() {

Expand Down Expand Up @@ -34,7 +34,7 @@ open class CheckIdeaVersionTask : DefaultTask() {
logger.lifecycle("Fetching IntelliJ Platform releases from $releasesUrl...")
val icReleases =
try {
URL(releasesUrl)
URI.create(releasesUrl).toURL()
.openStream()
.use { json.decodeFromStream<List<ApiIdeaReleasesItem>>(it) }
.first()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import org.gradle.api.tasks.Input
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction
import org.gradle.kotlin.dsl.property
import java.net.URL
import java.net.URI

class ThemeGeneratorContainer(container: NamedDomainObjectContainer<ThemeGeneration>) :
NamedDomainObjectContainer<ThemeGeneration> by container
Expand Down Expand Up @@ -59,7 +59,7 @@ open class IntelliJThemeGeneratorTask : DefaultTask() {
}

logger.lifecycle("Fetching theme descriptor from $url...")
val themeDescriptor = URL(url).openStream()
val themeDescriptor = URI.create(url).toURL().openStream()
.use { json.decodeFromStream<IntellijThemeDescriptor>(it) }

val className = ClassName.bestGuess(themeClassName.get())
Expand Down
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
composeDesktop = "1.6.0-dev1397"
detekt = "1.23.4"
dokka = "1.8.20"
idea = "241.9959.31-EAP-SNAPSHOT"
idea = "241.10840.26-EAP-SNAPSHOT"
ideaGradlePlugin = "1.17.0"
jna = "5.14.0"
kotlin = "1.8.21"
Expand Down
4 changes: 2 additions & 2 deletions ide-laf-bridge/api/ide-laf-bridge.api
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ public final class org/jetbrains/jewel/bridge/BridgeIconDataKt {
public static final fun readFromLaF (Lorg/jetbrains/jewel/foundation/theme/ThemeIconData$Companion;)Lorg/jetbrains/jewel/foundation/theme/ThemeIconData;
}

public final class org/jetbrains/jewel/bridge/BridgePainterHintsProvider : org/jetbrains/jewel/ui/painter/BasePainterHintsProvider {
public final class org/jetbrains/jewel/bridge/BridgePainterHintsProvider : org/jetbrains/jewel/ui/painter/PalettePainterHintsProvider {
public static final field $stable I
public static final field Companion Lorg/jetbrains/jewel/bridge/BridgePainterHintsProvider$Companion;
public synthetic fun <init> (ZLjava/util/Map;Ljava/util/Map;Ljava/util/Map;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun hints (Ljava/lang/String;Landroidx/compose/runtime/Composer;I)Ljava/util/List;
}

public final class org/jetbrains/jewel/bridge/BridgePainterHintsProvider$Companion {
public final fun invoke (Z)Lorg/jetbrains/jewel/ui/painter/BasePainterHintsProvider;
public final fun invoke (Z)Lorg/jetbrains/jewel/ui/painter/PalettePainterHintsProvider;
}

public final class org/jetbrains/jewel/bridge/BridgeResourceResolverKt {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,98 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import com.intellij.ide.ui.UITheme
import com.intellij.openapi.diagnostic.thisLogger
import com.intellij.ui.NewUI
import org.jetbrains.jewel.foundation.InternalJewelApi
import org.jetbrains.jewel.foundation.theme.JewelTheme
import org.jetbrains.jewel.ui.painter.BasePainterHintsProvider
import org.jetbrains.jewel.ui.painter.PainterHint
import org.jetbrains.jewel.ui.painter.PalettePainterHintsProvider
import org.jetbrains.jewel.ui.painter.hints.ColorBasedPaletteReplacement
import org.jetbrains.jewel.ui.painter.hints.Dark
import org.jetbrains.jewel.ui.painter.hints.HiDpi
import org.jetbrains.jewel.ui.painter.hints.KeyBasedPaletteReplacement
import org.jetbrains.jewel.ui.util.inDebugMode

@InternalJewelApi
public class BridgePainterHintsProvider private constructor(
isDark: Boolean,
intellijIconPalette: Map<String, String?> = emptyMap(),
themeIconPalette: Map<String, String?> = emptyMap(),
themeColorPalette: Map<String, Color?> = emptyMap(),
) : BasePainterHintsProvider(isDark, intellijIconPalette, themeIconPalette, themeColorPalette) {
) : PalettePainterHintsProvider(isDark, intellijIconPalette, themeIconPalette, themeColorPalette) {

override val checkBoxPaletteHint: PainterHint
override val treePaletteHint: PainterHint
override val uiPaletteHint: PainterHint

init {
val ui = mutableMapOf<Color, Color>()
val checkBoxes = mutableMapOf<String, Color>()
val trees = mutableMapOf<Color, Color>()

@Suppress("LoopWithTooManyJumpStatements")
for ((key, value) in themeIconPalette) {
if (value == null) continue

// Checkbox (and radio button) entries work differently: the ID field
// for each element that needs patching has a "[fillKey]_[strokeKey]"
// format, starting from IJP 241. This is only enabled for the New UI.
if (key.startsWith("Checkbox.") && NewUI.isEnabled()) {
registerIdBasedReplacement(checkBoxes, key, value)
} else {
val map = selectMap(key, trees, ui) ?: continue
registerColorBasedReplacement(map, key, value)
}
}

checkBoxPaletteHint = KeyBasedPaletteReplacement(checkBoxes)
treePaletteHint = ColorBasedPaletteReplacement(trees)
uiPaletteHint = ColorBasedPaletteReplacement(ui)
}

private fun selectMap(
key: String,
trees: MutableMap<Color, Color>,
ui: MutableMap<Color, Color>,
) =
when {
key.startsWith("Tree.iconColor.") -> trees
key.startsWith("Objects.") || key.startsWith("Actions.") || key.startsWith("#") -> ui
else -> null
}

private fun registerColorBasedReplacement(map: MutableMap<Color, Color>, key: String, value: String) {
// If either the key or the resolved value aren't valid colors, ignore the entry
val keyAsColor = resolveKeyColor(key, intellijIconPalette, isDark) ?: return
val resolvedColor = resolveColor(value) ?: return

// Save the new entry (oldColor -> newColor) in the map
map[keyAsColor] = resolvedColor
}

private fun registerIdBasedReplacement(map: MutableMap<String, Color>, key: String, value: String) {
val adjustedKey = if (isDark) key.removeSuffix(".Dark") else key

if (adjustedKey !in supportedCheckboxKeys) {
if (inDebugMode) {
logger.warn("${if (isDark) "Dark" else "Light"} theme: color key $key is not supported, will be ignored")
}
return
}

if (adjustedKey != key && inDebugMode) {
logger.warn("${if (isDark) "Dark" else "Light"} theme: color key $key is deprecated, use $adjustedKey instead")
}

val parsedValue = resolveColor(value)
if (parsedValue == null) {
if (inDebugMode) {
logger.warn("${if (isDark) "Dark" else "Light"} theme: color key $key has invalid value: '$value'")
}
return
}

map[adjustedKey] = parsedValue
}

@Composable
override fun hints(path: String): List<PainterHint> = buildList {
Expand All @@ -32,7 +110,7 @@ public class BridgePainterHintsProvider private constructor(
private val logger = thisLogger()

@Suppress("UnstableApiUsage") // We need to call @Internal APIs
public operator fun invoke(isDark: Boolean): BasePainterHintsProvider {
public operator fun invoke(isDark: Boolean): PalettePainterHintsProvider {
val uiTheme = currentUiThemeOrNull() ?: return BridgePainterHintsProvider(isDark)
logger.info("Parsing theme info from theme ${uiTheme.name} (id: ${uiTheme.id}, isDark: ${uiTheme.isDark})")

Expand All @@ -49,5 +127,17 @@ public class BridgePainterHintsProvider private constructor(

return BridgePainterHintsProvider(isDark, keyPalette, iconColorPalette, themeColors)
}

private val supportedCheckboxKeys: Set<String> = setOf(
"Checkbox.Background.Default",
"Checkbox.Border.Default",
"Checkbox.Foreground.Selected",
"Checkbox.Background.Selected",
"Checkbox.Border.Selected",
"Checkbox.Focus.Wide",
"Checkbox.Foreground.Disabled",
"Checkbox.Background.Disabled",
"Checkbox.Border.Disabled",
)
}
}
Loading

0 comments on commit a941970

Please sign in to comment.