IDEA-330211 convert UIThemeProvider from Java to Kotlin

GitOrigin-RevId: f45761263f910e7e1e9da9d31df840b58c0d44c7
This commit is contained in:
Vladimir Krivosheev
2023-09-03 23:39:31 +00:00
committed by intellij-monorepo-bot
parent 0eff8628d1
commit e1e77bdf4f
3 changed files with 79 additions and 74 deletions
@@ -1,92 +1,94 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.ide.ui;
package com.intellij.ide.ui
import com.intellij.diagnostic.PluginException;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.extensions.PluginAware;
import com.intellij.openapi.extensions.PluginDescriptor;
import com.intellij.openapi.extensions.RequiredElement;
import com.intellij.util.ResourceUtil;
import com.intellij.util.xmlb.annotations.Attribute;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.util.function.Function;
import com.intellij.diagnostic.PluginException
import com.intellij.openapi.diagnostic.thisLogger
import com.intellij.openapi.extensions.ExtensionPointName
import com.intellij.openapi.extensions.PluginAware
import com.intellij.openapi.extensions.PluginDescriptor
import com.intellij.openapi.extensions.RequiredElement
import com.intellij.util.ResourceUtil
import com.intellij.util.xmlb.annotations.Attribute
import org.jetbrains.annotations.ApiStatus.Internal
import java.io.IOException
import java.util.function.Function
/**
* Extension point for adding UI themes.
* <br/>
* Read more about <a href=https://plugins.jetbrains.com/docs/intellij/theme-structure.html>themes development</a>.
* Read more about [themes development](https://plugins.jetbrains.com/docs/intellij/theme-structure.html).
*
* @author Konstantin Bulenkov
*/
public final class UIThemeProvider implements PluginAware {
public static final ExtensionPointName<UIThemeProvider> EP_NAME = new ExtensionPointName<>("com.intellij.themeProvider");
private PluginDescriptor pluginDescriptor;
class UIThemeProvider : PluginAware {
companion object {
@JvmField
val EP_NAME: ExtensionPointName<UIThemeProvider> = ExtensionPointName("com.intellij.themeProvider")
}
private var pluginDescriptor: PluginDescriptor? = null
/**
* Path to {@code *.theme.json} file
* Path to `*.theme.json` file
*/
@Attribute("path")
@RequiredElement
public String path;
@JvmField
var path: String? = null
/**
* Unique theme identifier. For example, MyTheme123
*/
@Attribute("id")
@RequiredElement
public String id;
@JvmField
var id: String? = null
@Attribute("parentTheme")
public @Nullable String parentTheme;
var parentTheme: String? = null
@Attribute("targetUi") public @NotNull TargetUIType targetUI = TargetUIType.UNSPECIFIED;
@Attribute("targetUi")
@JvmField
var targetUI: TargetUIType = TargetUIType.UNSPECIFIED
@ApiStatus.Internal
public byte[] getThemeJson() throws IOException {
String path = this.path;
path = path.charAt(0) == '/' ? path.substring(1) : path;
return ResourceUtil.getResourceAsBytes(path, pluginDescriptor.getClassLoader());
@Throws(IOException::class)
@Internal
fun getThemeJson(): ByteArray? {
var path = path!!
path = if (path[0] == '/') path.substring(1) else path
return ResourceUtil.getResourceAsBytes(path, pluginDescriptor!!.getClassLoader())
}
public @Nullable UITheme createTheme(
@Nullable UITheme parentTheme,
@Nullable UITheme defaultDarkParent,
@Nullable UITheme defaultLightParent) {
if (defaultDarkParent != null && defaultDarkParent.getId().equals(id)) {
return defaultDarkParent;
fun createTheme(parentTheme: UITheme?, defaultDarkParent: UITheme?, defaultLightParent: UITheme?): UITheme? {
if (defaultDarkParent != null && defaultDarkParent.id == id) {
return defaultDarkParent
}
if (defaultLightParent != null && defaultLightParent.getId().equals(id)) {
return defaultLightParent;
if (defaultLightParent != null && defaultLightParent.id == id) {
return defaultLightParent
}
try {
ClassLoader classLoader = pluginDescriptor.getPluginClassLoader();
byte[] stream = getThemeJson();
val classLoader = pluginDescriptor!!.getPluginClassLoader()
val stream = getThemeJson()
if (stream == null) {
Logger.getInstance(getClass()).warn(new PluginException(
"Cannot find theme resource: " + path + " (classLoader=" + classLoader + ", pluginDescriptor=" + pluginDescriptor + ")",
pluginDescriptor.getPluginId()
));
return null;
thisLogger().warn(PluginException(
"Cannot find theme resource: $path (classLoader=$classLoader, pluginDescriptor=$pluginDescriptor)",
pluginDescriptor!!.getPluginId()
))
return null
}
return UITheme.loadFromJson(parentTheme, stream, id, classLoader, Function.identity(), defaultDarkParent, defaultLightParent);
return UITheme.loadFromJson(parentTheme, stream, id!!, classLoader, Function.identity(), defaultDarkParent, defaultLightParent)
}
catch (Throwable e) {
Logger.getInstance(getClass()).warn(new PluginException(
"error loading UITheme '" + path + "', pluginDescriptor=" + pluginDescriptor,
catch (e: Throwable) {
thisLogger().warn(PluginException(
"error loading UITheme '$path', pluginDescriptor=$pluginDescriptor",
e,
pluginDescriptor.getPluginId()
));
return null;
pluginDescriptor!!.getPluginId()
))
return null
}
}
@Override
public void setPluginDescriptor(@NotNull PluginDescriptor pluginDescriptor) {
this.pluginDescriptor = pluginDescriptor;
override fun setPluginDescriptor(pluginDescriptor: PluginDescriptor) {
this.pluginDescriptor = pluginDescriptor
}
}
@@ -18,6 +18,7 @@ import com.intellij.util.graph.OutboundSemiGraph
internal class UiThemeProviderListManager {
companion object {
fun getInstance(): UiThemeProviderListManager = service()
internal const val DEFAULT_DARK_PARENT_THEME = "Darcula"
internal const val DEFAULT_LIGHT_PARENT_THEME = "IntelliJ"
}
@@ -41,10 +42,12 @@ internal class UiThemeProviderListManager {
}
val parentTheme = findParentTheme(lafList, provider.parentTheme)
val theme = provider.createTheme(parentTheme,
lafMap.keys.single { it.theme.id == DEFAULT_DARK_PARENT_THEME }.theme,
lafMap.keys.single { it.theme.id == DEFAULT_LIGHT_PARENT_THEME }.theme) ?: return null
editorColorManager().handleThemeAdded(theme)
val theme = provider.createTheme(
parentTheme = parentTheme,
defaultDarkParent = lafMap.keys.single { it.theme.id == DEFAULT_DARK_PARENT_THEME }.theme,
defaultLightParent = lafMap.keys.single { it.theme.id == DEFAULT_LIGHT_PARENT_THEME }.theme,
) ?: return null
editorColorManager.handleThemeAdded(theme)
val newLaF = UIThemeLookAndFeelInfoImpl(theme)
lafMap = lafMap + Pair(newLaF, provider.targetUI)
return newLaF
@@ -53,35 +56,34 @@ internal class UiThemeProviderListManager {
fun themeProviderRemoved(provider: UIThemeProvider): UIThemeLookAndFeelInfo? {
val oldLaF = findLaFByProviderId(provider) ?: return null
lafMap = lafMap - oldLaF
editorColorManager().handleThemeRemoved(oldLaF.theme)
editorColorManager.handleThemeRemoved(oldLaF.theme)
return oldLaF
}
private fun findLaFById(id: String) = lafList.find { it.theme.id == id }
private fun findLaFById(id: String) = lafList.firstOrNull { it.theme.id == id }
private fun findLaFByProviderId(provider: UIThemeProvider) = findLaFById(provider.id)
private fun findLaFByProviderId(provider: UIThemeProvider) = provider.id?.let { findLaFById(it) }
}
private fun computeMap(): Map<UIThemeLookAndFeelInfo, TargetUIType> {
val map = LinkedHashMap<UIThemeLookAndFeelInfo, TargetUIType>()
val orderedProviders = sortTopologically(UIThemeProvider.EP_NAME.extensionList, { it.id }, { it.parentTheme })
val darcula = orderedProviders.single{ it.id == UiThemeProviderListManager.DEFAULT_DARK_PARENT_THEME }
.createTheme(null, null, null)
val intelliJ = orderedProviders.single{ it.id == UiThemeProviderListManager.DEFAULT_LIGHT_PARENT_THEME }
.createTheme(darcula, null, null)
val darcula = orderedProviders.single { it.id == UiThemeProviderListManager.DEFAULT_DARK_PARENT_THEME }
.createTheme(parentTheme = null, defaultDarkParent = null, defaultLightParent = null)
val intelliJ = orderedProviders.single { it.id == UiThemeProviderListManager.DEFAULT_LIGHT_PARENT_THEME }
.createTheme(parentTheme = darcula, defaultDarkParent = null, defaultLightParent = null)
for (provider in orderedProviders) {
val parentTheme = findParentTheme(map.keys, provider.parentTheme)
val theme = UIThemeLookAndFeelInfoImpl(provider.createTheme(parentTheme, darcula, intelliJ) ?: continue)
val theme = UIThemeLookAndFeelInfoImpl(provider.createTheme(parentTheme = parentTheme,
defaultDarkParent = darcula,
defaultLightParent = intelliJ) ?: continue)
map.put(theme, provider.targetUI)
}
return map
}
private fun findParentTheme(themes: Collection<UIThemeLookAndFeelInfo>, parentId: String?): UITheme? {
if (parentId == null) {
return null
}
return themes.asSequence().map { it.theme }.find { it.id == parentId }
return if (parentId == null) null else themes.asSequence().map { it.theme }.firstOrNull { it.id == parentId }
}
private fun <T, K> sortTopologically(list: List<T>, idFun: (T) -> K, parentIdFun: (T) -> K?): List<T> {
@@ -100,4 +102,5 @@ private fun <T, K> sortTopologically(list: List<T>, idFun: (T) -> K, parentIdFun
private const val DEFAULT_LIGHT_THEME_ID = "JetBrainsLightTheme"
private fun editorColorManager() = EditorColorsManager.getInstance() as EditorColorsManagerImpl
private val editorColorManager: EditorColorsManagerImpl
get() = EditorColorsManager.getInstance() as EditorColorsManagerImpl
@@ -1,4 +1,4 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.idea.devkit.themes;
import com.intellij.ide.ui.UIThemeProvider;
@@ -16,7 +16,7 @@ import org.jetbrains.idea.devkit.dom.ExtensionPoint;
import org.jetbrains.idea.devkit.themes.metadata.UIThemeMetadataService;
import org.jetbrains.idea.devkit.util.PsiUtil;
public class ThemeEPPathReferenceContributor extends PsiReferenceContributor {
final class ThemeEPPathReferenceContributor extends PsiReferenceContributor {
@Override
public void registerReferenceProviders(@NotNull PsiReferenceRegistrar registrar) {
registrar.registerReferenceProvider(XmlPatterns.xmlAttributeValue().withLocalName("path"), new PsiReferenceProvider() {