diff --git a/platform/platform-api/src/com/intellij/ide/ui/UITheme.java b/platform/platform-api/src/com/intellij/ide/ui/UITheme.java index 0d8944ae703c..bdbfe481ec68 100644 --- a/platform/platform-api/src/com/intellij/ide/ui/UITheme.java +++ b/platform/platform-api/src/com/intellij/ide/ui/UITheme.java @@ -33,6 +33,7 @@ import java.lang.reflect.Constructor; import java.util.List; import java.util.*; import java.util.function.Function; +import java.util.function.Supplier; /** * @author Konstantin Bulenkov @@ -85,21 +86,25 @@ public final class UITheme { } public static @NotNull UITheme loadFromJson(@Nullable UITheme parentTheme, - byte[] data, + byte @NotNull [] data, @NotNull @NonNls String themeId, @Nullable ClassLoader provider, @NotNull Function iconsMapper, - @Nullable UITheme defaultDarkParent, - @Nullable UITheme defaultLightParent) throws IOException { + @Nullable Supplier defaultDarkParent, + @Nullable Supplier defaultLightParent) throws IOException { UIThemeBean theme = UIThemeBean.Companion.readTheme(new JsonFactory().createParser(data)); theme.id = themeId; - if (theme.dark && parentTheme == null) { - return postProcessTheme(theme, defaultDarkParent, provider, iconsMapper); + if (parentTheme == null) { + if (theme.dark) { + return postProcessTheme(theme, defaultDarkParent == null ? null : defaultDarkParent.get(), provider, iconsMapper); + } + else { + return postProcessTheme(theme, defaultLightParent == null ? null : defaultLightParent.get(), provider, iconsMapper); + } } - if (!theme.dark && parentTheme == null) { - return postProcessTheme(theme, defaultLightParent, provider, iconsMapper); + else { + return postProcessTheme(theme, parentTheme, provider, iconsMapper); } - return postProcessTheme(theme, parentTheme, provider, iconsMapper); } private static @NotNull UITheme postProcessTheme(@NotNull UIThemeBean theme, @@ -451,15 +456,6 @@ public final class UITheme { } } - private static @NotNull String createUIKey(String key, String propertyName) { - if ("UI".equals(propertyName)) { - return key + propertyName; - } - else { - return key + "." + propertyName; - } - } - @SuppressWarnings("unchecked") private static void addPattern(String key, Object value, UIDefaults defaults) { Object o = defaults.get("*"); diff --git a/platform/platform-impl/src/com/intellij/ide/ui/UIThemeProvider.kt b/platform/platform-impl/src/com/intellij/ide/ui/UIThemeProvider.kt index 0231cce88fac..08074eb5c783 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/UIThemeProvider.kt +++ b/platform/platform-impl/src/com/intellij/ide/ui/UIThemeProvider.kt @@ -2,6 +2,7 @@ package com.intellij.ide.ui import com.intellij.diagnostic.PluginException +import com.intellij.ide.ui.laf.UiThemeProviderListManager import com.intellij.openapi.diagnostic.thisLogger import com.intellij.openapi.extensions.ExtensionPointName import com.intellij.openapi.extensions.PluginAware @@ -12,6 +13,7 @@ import com.intellij.util.xmlb.annotations.Attribute import org.jetbrains.annotations.ApiStatus.Internal import java.io.IOException import java.util.function.Function +import java.util.function.Supplier /** * Extension point for adding UI themes. @@ -53,37 +55,48 @@ class UIThemeProvider : PluginAware { @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()) + return ResourceUtil.getResourceAsBytes((path ?: return null).removePrefix("/"), pluginDescriptor!!.getClassLoader()) } - fun createTheme(parentTheme: UITheme?, defaultDarkParent: UITheme?, defaultLightParent: UITheme?): UITheme? { - if (defaultDarkParent != null && defaultDarkParent.id == id) { - return defaultDarkParent + internal fun createTheme(parentTheme: UITheme?, + defaultDarkParent: Supplier?, + defaultLightParent: Supplier?): UITheme? { + if (defaultDarkParent != null && id == UiThemeProviderListManager.DEFAULT_DARK_PARENT_THEME) { + val result = defaultDarkParent.get() + if (result?.id == UiThemeProviderListManager.DEFAULT_DARK_PARENT_THEME) { + return result + } } - if (defaultLightParent != null && defaultLightParent.id == id) { - return defaultLightParent + if (defaultLightParent != null && id == UiThemeProviderListManager.DEFAULT_LIGHT_PARENT_THEME) { + val result = defaultLightParent.get() + if (result?.id == UiThemeProviderListManager.DEFAULT_LIGHT_PARENT_THEME) { + return result + } } + val pluginDescriptor = pluginDescriptor!! try { - val classLoader = pluginDescriptor!!.getPluginClassLoader() - val stream = getThemeJson() - if (stream == null) { + val classLoader = pluginDescriptor.getPluginClassLoader() + val data = getThemeJson() + if (data == null) { thisLogger().warn(PluginException( - "Cannot find theme resource: $path (classLoader=$classLoader, pluginDescriptor=$pluginDescriptor)", - pluginDescriptor!!.getPluginId() - )) + "Cannot find theme resource (path=$path, classLoader=$classLoader, pluginDescriptor=$pluginDescriptor)", + pluginDescriptor.getPluginId())) return null } - return UITheme.loadFromJson(parentTheme, stream, id!!, classLoader, Function.identity(), defaultDarkParent, defaultLightParent) + + return UITheme.loadFromJson(parentTheme, + data, + id!!, + classLoader, + Function.identity(), + defaultDarkParent, + defaultLightParent) } catch (e: Throwable) { - thisLogger().warn(PluginException( - "error loading UITheme '$path', pluginDescriptor=$pluginDescriptor", - e, - pluginDescriptor!!.getPluginId() - )) + thisLogger().warn(PluginException("Cannot load UI theme (path=$path, pluginDescriptor=$pluginDescriptor)", + e, + pluginDescriptor.getPluginId())) return null } } diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.kt b/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.kt index be6ad3314146..0704c5dd9905 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.kt +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.kt @@ -109,13 +109,6 @@ private const val INTER_SIZE = 13 reportStatistic = false) class LafManagerImpl(private val coroutineScope: CoroutineScope) : LafManager(), PersistentStateComponent { private val eventDispatcher = EventDispatcher.create(LafManagerListener::class.java) - private val lafMap = SynchronizedClearableLazy { - runActivity("compute LaF list") { - UiThemeProviderListManager.getInstance().getLaFsWithUITypes() - } - } - private val lafList: Set - get() = lafMap.value.keys private val defaultDarkTheme = SynchronizedClearableLazy { val name = ApplicationInfoEx.getInstanceEx().defaultDarkLaf @@ -381,9 +374,9 @@ class LafManagerImpl(private val coroutineScope: CoroutineScope) : LafManager(), } } - private fun loadThemeState(element: Element, attrName: @NonNls String): UIThemeLookAndFeelInfo? { - val lafElement = element.getChild(attrName) ?: return null - return lafList.singleOrNull { it.theme.id == lafElement.getAttributeValue(ATTRIBUTE_THEME_NAME) } + private fun loadThemeState(element: Element, attributeName: @NonNls String): UIThemeLookAndFeelInfo? { + val id = element.getChild(attributeName)?.getAttributeValue(ATTRIBUTE_THEME_NAME) ?: return null + return UiThemeProviderListManager.getInstance().findThemeById(id) } override fun noStateLoaded() { @@ -395,19 +388,19 @@ class LafManagerImpl(private val coroutineScope: CoroutineScope) : LafManager(), autodetect = false } - override fun getState(): Element? { + override fun getState(): Element { val element = Element("state") if (autodetect) { element.setAttribute(ATTRIBUTE_AUTODETECT, java.lang.Boolean.toString(autodetect)) } if (currentTheme?.theme?.id != defaultThemeId) { - getThemeState(element, ELEMENT_LAF, currentUIThemeLookAndFeel) + writeThemeState(element, ELEMENT_LAF, currentUIThemeLookAndFeel) } if (preferredLightTheme != null && preferredLightTheme !== defaultLightLaf) { - getThemeState(element, ELEMENT_PREFERRED_LIGHT_LAF, preferredLightTheme) + writeThemeState(element, ELEMENT_PREFERRED_LIGHT_LAF, preferredLightTheme) } if (preferredDarkTheme != null && preferredDarkTheme !== defaultDarkLaf) { - getThemeState(element, ELEMENT_PREFERRED_DARK_LAF, preferredDarkTheme) + writeThemeState(element, ELEMENT_PREFERRED_DARK_LAF, preferredDarkTheme) } if (lafToPreviousScheme.isNotEmpty()) { @@ -422,15 +415,19 @@ class LafManagerImpl(private val coroutineScope: CoroutineScope) : LafManager(), element.addContent(lafsToSchemes) } - return if (element.isEmpty) null else element + return element } - override fun getInstalledLookAndFeels(): Array = lafList.toTypedArray() + override fun getInstalledLookAndFeels(): Array { + return UiThemeProviderListManager.getInstance().getLaFs().toList().toTypedArray() + } override fun getLafComboBoxModel(): CollectionComboBoxModel = lafComboBoxModel.value - fun getThemeListForTargetUI(targetUI: TargetUIType): List { - return lafMap.value.filterValues { it == targetUI }.keys.toList() + fun getThemeListForTargetUI(targetUI: TargetUIType): Sequence { + return UiThemeProviderListManager.getInstance().getLaFsWithUITypes().asSequence() + .filter { it.targetUiType == targetUI } + .mapNotNull { it.theme.get() } } private val allReferences: List @@ -458,7 +455,11 @@ class LafManagerImpl(private val coroutineScope: CoroutineScope) : LafManager(), } override fun findLaf(reference: LafReference): UIThemeLookAndFeelInfo { - return lafList.singleOrNull { it.theme.id == reference.themeId } ?: error("Theme not found for themeId: ${reference.themeId}") + return UiThemeProviderListManager.getInstance().getLaFsWithUITypes() + .singleOrNull { it.id == reference.themeId } + ?.theme + ?.get() + ?: error("Theme not found for themeId: ${reference.themeId}") } @Suppress("removal") @@ -473,18 +474,18 @@ class LafManagerImpl(private val coroutineScope: CoroutineScope) : LafManager(), override fun getSettingsToolbar(): JComponent = settingsToolbar.value.component private fun loadDefaultTheme(): UIThemeLookAndFeelInfo { - // Use HighContrast theme for IDE in Windows if HighContrast desktop mode is set. + // use HighContrast theme for IDE in Windows if HighContrast desktop mode is set if (SystemInfoRt.isWindows && Toolkit.getDefaultToolkit().getDesktopProperty("win.highContrast.on") == true) { - for (laf in lafList) { - if (HIGH_CONTRAST_THEME_ID == laf.theme.id) { - return laf - } + UiThemeProviderListManager.getInstance().findThemeById(HIGH_CONTRAST_THEME_ID)?.let { + return it } } return defaultDarkLaf } - private fun findLafByName(name: String): UIThemeLookAndFeelInfo? = installedLookAndFeels.firstOrNull { name == it.name } + private fun findLafByName(name: String): UIThemeLookAndFeelInfo? { + return UiThemeProviderListManager.getInstance().findThemeByName(name) + } /** * Sets current LAF. The method doesn't update component hierarchy. @@ -829,22 +830,17 @@ class LafManagerImpl(private val coroutineScope: CoroutineScope) : LafManager(), private inner class UiThemeEpListener : ExtensionPointListener { override fun extensionAdded(extension: UIThemeProvider, pluginDescriptor: PluginDescriptor) { - val newLaF = UiThemeProviderListManager.getInstance().themeProviderAdded(extension) ?: return - val oldLaFsMap = lafMap.value - val newLaFsMap = mutableMapOf() - newLaFsMap.putAll(oldLaFsMap) - newLaFsMap.put(newLaF, extension.targetUI) - lafMap.value = newLaFsMap + val uiThemeProviderListManager = UiThemeProviderListManager.getInstance() + val newLaF = uiThemeProviderListManager.themeProviderAdded(extension) ?: return updateLafComboboxModel() // when updating a theme plugin that doesn't provide the current theme, don't select any of its themes as current val newTheme = newLaF.theme - val pluginClassLoader = pluginDescriptor.pluginClassLoader - if (pluginClassLoader != null) { - newTheme.setProviderClassLoader(pluginClassLoader) + pluginDescriptor.pluginClassLoader?.let { + newTheme.setProviderClassLoader(it) } if (!autodetect && (!isUpdatingPlugin || newTheme.id == themeIdBeforePluginUpdate)) { - setLookAndFeelImpl(newLaF, true, false) + setLookAndFeelImpl(lookAndFeelInfo = newLaF, installEditorScheme = true, processChangeSynchronously = false) JBColor.setDark(newTheme.isDark) updateUI() } @@ -861,16 +857,9 @@ class LafManagerImpl(private val coroutineScope: CoroutineScope) : LafManager(), else { null } - val newLaFs = mutableMapOf() - for (laf in lafMap.value) { - if (laf.key !== oldLaF) { - newLaFs.put(laf.key, laf.value) - } - } - lafMap.value = newLaFs updateLafComboboxModel() if (defaultLaF != null) { - setLookAndFeelImpl(defaultLaF, true, true) + setLookAndFeelImpl(lookAndFeelInfo = defaultLaF, installEditorScheme = true, processChangeSynchronously = true) if (ExperimentalUI.isNewUI()) { JBColor.setDark(defaultDarkTheme.isInitialized() && isDark) } @@ -1131,8 +1120,8 @@ private class OurPopupFactory(private val delegate: PopupFactory) : PopupFactory } } -private fun getThemeState(element: Element, attributeName: @NonNls String?, suggestedLaf: UIThemeLookAndFeelInfo?) { - val laf = (if (suggestedLaf is TempUIThemeLookAndFeelInfo) suggestedLaf.previousLaf else null) ?: return +private fun writeThemeState(element: Element, attributeName: @NonNls String?, suggestedLaf: UIThemeLookAndFeelInfo?) { + val laf = (if (suggestedLaf is TempUIThemeLookAndFeelInfo) suggestedLaf.previousLaf else suggestedLaf) ?: return val child = Element(attributeName) child.setAttribute(ATTRIBUTE_THEME_NAME, laf.theme.id) element.addContent(child) diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/ThemeListProviderImpl.kt b/platform/platform-impl/src/com/intellij/ide/ui/laf/ThemeListProviderImpl.kt index 3eca936d8783..742b4f3aa5e3 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/ThemeListProviderImpl.kt +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/ThemeListProviderImpl.kt @@ -11,10 +11,10 @@ private class ThemeListProviderImpl : ThemeListProvider { val lafManager = LafManager.getInstance() as? LafManagerImpl ?: return emptyList() val result = mutableListOf>() if (ExperimentalUI.isNewUI()) { - result.add(lafManager.getThemeListForTargetUI(TargetUIType.NEW).sortedBy { it.name }) + result.add(lafManager.getThemeListForTargetUI(TargetUIType.NEW).sortedBy { it.name }.toList()) } result.add((lafManager.getThemeListForTargetUI(TargetUIType.CLASSIC).filterNot { it.theme.id == "IntelliJ" } - + lafManager.getThemeListForTargetUI(TargetUIType.UNSPECIFIED)).sortedBy { it.name }) + + lafManager.getThemeListForTargetUI(TargetUIType.UNSPECIFIED)).sortedBy { it.name }.toList()) return result } } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/UiThemeProviderListManager.kt b/platform/platform-impl/src/com/intellij/ide/ui/laf/UiThemeProviderListManager.kt index b39a67c3d594..6e2d410cb896 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/UiThemeProviderListManager.kt +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/UiThemeProviderListManager.kt @@ -3,6 +3,7 @@ package com.intellij.ide.ui.laf +import com.intellij.diagnostic.runActivity import com.intellij.ide.ui.TargetUIType import com.intellij.ide.ui.UITheme import com.intellij.ide.ui.UIThemeProvider @@ -10,8 +11,8 @@ import com.intellij.openapi.components.Service import com.intellij.openapi.components.service import com.intellij.openapi.editor.colors.EditorColorsManager import com.intellij.openapi.editor.colors.impl.EditorColorsManagerImpl -import com.intellij.util.graph.DFSTBuilder -import com.intellij.util.graph.OutboundSemiGraph +import com.intellij.util.concurrency.SynchronizedClearableLazy +import java.util.function.Supplier // separate service to avoid using LafManager in the EditorColorsManagerImpl initialization @Service(Service.Level.APP) @@ -24,16 +25,21 @@ internal class UiThemeProviderListManager { } @Volatile - private var lafMap: Map = computeMap() + private var themeDescriptors: List = computeMap() - private val lafList: Set - get() = lafMap.keys + fun getLaFs(): Sequence = themeDescriptors.asSequence().mapNotNull { it.theme.get() } - fun getLaFs(): List = lafList.toList() + fun findThemeByName(name: String): UIThemeLookAndFeelInfo? { + return getLaFs().firstOrNull { it.theme.name == name } + } - fun getLaFsWithUITypes(): Map = lafMap + fun findThemeById(id: String): UIThemeLookAndFeelInfo? { + return themeDescriptors.firstOrNull { it.id == id }?.theme?.get() + } - fun findJetBrainsLightTheme(): UIThemeLookAndFeelInfo? = findLaFById(DEFAULT_LIGHT_THEME_ID) + fun getLaFsWithUITypes(): List = themeDescriptors + + fun findJetBrainsLightTheme(): UIThemeLookAndFeelInfo? = findLaFById(DEFAULT_LIGHT_THEME_ID)?.theme?.get() fun themeProviderAdded(provider: UIThemeProvider): UIThemeLookAndFeelInfo? { if (findLaFByProviderId(provider) != null) { @@ -41,63 +47,71 @@ internal class UiThemeProviderListManager { return null } - val parentTheme = findParentTheme(lafList, provider.parentTheme) + val parentTheme = findParentTheme(themes = themeDescriptors, parentId = provider.parentTheme) 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, + defaultDarkParent = SynchronizedClearableLazy { themeDescriptors.single { it.id == DEFAULT_DARK_PARENT_THEME }.theme.get()?.theme }, + defaultLightParent = SynchronizedClearableLazy { themeDescriptors.single { it.id == DEFAULT_LIGHT_PARENT_THEME }.theme.get()?.theme }, ) ?: return null editorColorManager.handleThemeAdded(theme) val newLaF = UIThemeLookAndFeelInfoImpl(theme) - lafMap = lafMap + Pair(newLaF, provider.targetUI) + themeDescriptors = themeDescriptors + LafEntry(Supplier { newLaF }, provider.targetUI, provider.id!!) return newLaF } fun themeProviderRemoved(provider: UIThemeProvider): UIThemeLookAndFeelInfo? { val oldLaF = findLaFByProviderId(provider) ?: return null - lafMap = lafMap - oldLaF - editorColorManager.handleThemeRemoved(oldLaF.theme) - return oldLaF + themeDescriptors = themeDescriptors - oldLaF + val theme = oldLaF.theme.get() ?: return null + editorColorManager.handleThemeRemoved(theme.theme) + return theme } - private fun findLaFById(id: String) = lafList.firstOrNull { it.theme.id == id } + private fun findLaFById(id: String) = themeDescriptors.firstOrNull { it.id == id } private fun findLaFByProviderId(provider: UIThemeProvider) = provider.id?.let { findLaFById(it) } -} -private fun computeMap(): Map { - val map = LinkedHashMap() - val orderedProviders = sortTopologically(UIThemeProvider.EP_NAME.extensionList, { it.id }, { it.parentTheme }) - 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 = parentTheme, - defaultDarkParent = darcula, - defaultLightParent = intelliJ) ?: continue) - map.put(theme, provider.targetUI) - } - return map -} - -private fun findParentTheme(themes: Collection, parentId: String?): UITheme? { - return if (parentId == null) null else themes.asSequence().map { it.theme }.firstOrNull { it.id == parentId } -} - -private fun sortTopologically(list: List, idFun: (T) -> K, parentIdFun: (T) -> K?): List { - val mapById = list.associateBy(idFun) - val graph = object : OutboundSemiGraph { - override fun getNodes(): Collection = list - - override fun getOut(n: T): Iterator { - val parent = mapById.get(parentIdFun(n)) - return listOfNotNull(parent).iterator() + private fun computeMap(): List { + val result = ArrayList() + runActivity("compute LaF list") { + val darcula = SynchronizedClearableLazy { + UIThemeProvider.EP_NAME.extensionList.single { it.id == DEFAULT_DARK_PARENT_THEME } + .createTheme(parentTheme = null, defaultDarkParent = null, defaultLightParent = null) + } + val intelliJ = SynchronizedClearableLazy { + UIThemeProvider.EP_NAME.extensionList.single { it.id == DEFAULT_LIGHT_PARENT_THEME } + .createTheme(parentTheme = darcula.value, defaultDarkParent = null, defaultLightParent = null) + } + for (provider in UIThemeProvider.EP_NAME.extensionList) { + result.add(LafEntry( + theme = SynchronizedClearableLazy { + val theme = when (provider.id) { + DEFAULT_DARK_PARENT_THEME -> darcula.value + DEFAULT_LIGHT_THEME_ID -> intelliJ.value + else -> { + val parentTheme = findParentTheme(themes = themeDescriptors, parentId = provider.parentTheme) + provider.createTheme(parentTheme = parentTheme, defaultDarkParent = darcula, defaultLightParent = intelliJ) + } + } + theme?.let { UIThemeLookAndFeelInfoImpl(it) } + }, + targetUiType = provider.targetUI, + id = provider.id!!, + )) + } } + return java.util.List.copyOf(result) } +} - return DFSTBuilder(graph).sortedNodes.reversed() +internal data class LafEntry( + @JvmField val theme: Supplier, + @JvmField val targetUiType: TargetUIType, + @JvmField val id: String, +) + +private fun findParentTheme(themes: Collection, parentId: String?): UITheme? { + return if (parentId == null) null else themes.firstOrNull { it.id == parentId }?.theme?.get()?.theme } private const val DEFAULT_LIGHT_THEME_ID = "JetBrainsLightTheme" diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java index e1126459b568..e413053d924d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java @@ -66,6 +66,7 @@ import com.intellij.util.messages.MessageBusConnection; import com.intellij.util.ui.StartupUiUtil; import com.intellij.util.xmlb.annotations.OptionTag; import kotlin.jvm.functions.Function1; +import kotlin.sequences.SequencesKt; import org.jdom.Element; import org.jetbrains.annotations.*; @@ -284,18 +285,15 @@ public final class EditorColorsManagerImpl extends EditorColorsManager implement @TestOnly public @Nullable EditorColorsScheme loadBundledScheme(@NotNull String themeName) { assert ApplicationManager.getApplication().isUnitTestMode() : "Test-only method"; - for (UIThemeLookAndFeelInfo laf : UiThemeProviderListManager.Companion.getInstance().getLaFs()) { - UITheme theme = laf.getTheme(); - if (themeName.equals(theme.getName())) { - String scheme = theme.getEditorScheme(); - if (scheme != null) { - EditorColorsScheme bundledScheme = loadBundledScheme(scheme, theme, null); - initEditableBundledSchemesCopies(); - return bundledScheme; - } - } + UIThemeLookAndFeelInfo theme = UiThemeProviderListManager.Companion.getInstance().findThemeByName(themeName); + String scheme = theme == null ? null : theme.getTheme().getEditorScheme(); + if (scheme == null) { + return null; } - return null; + + EditorColorsScheme bundledScheme = loadBundledScheme(scheme, theme, null); + initEditableBundledSchemesCopies(); + return bundledScheme; } @TestOnly @@ -317,7 +315,7 @@ public final class EditorColorsManagerImpl extends EditorColorsManager implement return; } - for (UIThemeLookAndFeelInfo laf : UiThemeProviderListManager.Companion.getInstance().getLaFs()) { + for (UIThemeLookAndFeelInfo laf : SequencesKt.asIterable(UiThemeProviderListManager.Companion.getInstance().getLaFs())) { UITheme theme = laf.getTheme(); List schemes = theme.getAdditionalEditorSchemes(); PluginDescriptor pluginDescriptor = getPluginDescriptor(theme); @@ -764,25 +762,18 @@ public final class EditorColorsManagerImpl extends EditorColorsManager implement boolean isDark = ColorUtil.isDark(scheme.getDefaultBackground()); String neededThemeName = isDark ? "Solarized Dark" : "Solarized Light"; - UIThemeLookAndFeelInfo neededTheme = null; - for (UIThemeLookAndFeelInfo theme : UiThemeProviderListManager.Companion.getInstance().getLaFs()) { - if (theme.getName().equals(neededThemeName)) { - neededTheme = theme; - break; - } - } + UIThemeLookAndFeelInfo neededTheme = UiThemeProviderListManager.Companion.getInstance().findThemeByName(neededThemeName); Notification notification = new Notification("ColorSchemeDeprecation", IdeBundle.message("notification.title.solarized.color.scheme.deprecation"), "", NotificationType.ERROR); if (neededTheme != null) { notification.setContent(IdeBundle.message("notification.content.solarized.color.scheme.deprecation.enable", name, neededThemeName)); - UIThemeLookAndFeelInfo finalNeededTheme = neededTheme; notification.addAction(new NotificationAction(IdeBundle.message("notification.title.enable.action.solarized.color.scheme.deprecation", neededThemeName)) { @Override public void actionPerformed(@NotNull AnActionEvent e, @NotNull Notification notification) { LafManager lafManager = LafManager.getInstance(); - lafManager.setCurrentLookAndFeel(finalNeededTheme, false); + lafManager.setCurrentLookAndFeel(neededTheme, false); lafManager.updateUI(); notification.expire(); }