mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-16 22:51:17 +07:00
IJPL-189325 Move island themes to the themes list
GitOrigin-RevId: 4c9373b6a7440aec20af5d5c0f4945e0993298b4
This commit is contained in:
committed by
intellij-monorepo-bot
parent
da910a89a5
commit
ea4b14110a
@@ -70,11 +70,15 @@ public abstract class QuickSwitchSchemeAction extends AnAction implements DumbAw
|
||||
}
|
||||
}
|
||||
|
||||
showPopup(e, createPopup(e, group, aid));
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
protected @NotNull ListPopup createPopup(AnActionEvent e, DefaultActionGroup group, JBPopupFactory.ActionSelectionAid aid) {
|
||||
ListPopup popup = JBPopupFactory.getInstance().createActionGroupPopup(
|
||||
getPopupTitle(e), group, e.getDataContext(), aid, true, null, -1,
|
||||
preselectAction(), myActionPlace);
|
||||
|
||||
showPopup(e, popup);
|
||||
return popup;
|
||||
}
|
||||
|
||||
protected @Nullable Condition<? super AnAction> preselectAction() {
|
||||
|
||||
@@ -60,6 +60,10 @@ public abstract class LafManager {
|
||||
|
||||
public abstract void repaintUI();
|
||||
|
||||
@ApiStatus.Internal
|
||||
public void checkRestart() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return if autodetect is supported and enabled
|
||||
*/
|
||||
|
||||
@@ -54,6 +54,9 @@ interface UIThemeLookAndFeelInfo {
|
||||
*/
|
||||
val providerClassLoader: ClassLoader
|
||||
|
||||
@Internal
|
||||
fun isRestartRequired(): Boolean = false
|
||||
|
||||
/**
|
||||
* Installs this theme by applying theme-specific settings to the provided UIDefaults.
|
||||
* This includes setting up icon patchers, SVG color patchers, and background images.
|
||||
|
||||
@@ -11,12 +11,14 @@ import com.intellij.ide.ui.laf.UiThemeProviderListManager;
|
||||
import com.intellij.ide.ui.laf.darcula.DarculaInstaller;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.actionSystem.impl.PresentationFactory;
|
||||
import com.intellij.openapi.actionSystem.remoting.ActionRemoteBehaviorSpecification;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.components.Service;
|
||||
import com.intellij.openapi.editor.colors.Groups;
|
||||
import com.intellij.openapi.project.DumbAwareAction;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.ui.popup.JBPopupListener;
|
||||
import com.intellij.openapi.ui.popup.LightweightWindowEvent;
|
||||
import com.intellij.openapi.ui.popup.ListPopup;
|
||||
@@ -24,7 +26,15 @@ import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.wm.impl.welcomeScreen.WelcomeFrame;
|
||||
import com.intellij.ui.components.panels.NonOpaquePanel;
|
||||
import com.intellij.ui.icons.IconUtilKt;
|
||||
import com.intellij.ui.popup.ActionPopupOptions;
|
||||
import com.intellij.ui.popup.PopupFactoryImpl;
|
||||
import com.intellij.ui.popup.list.PopupListElementRenderer;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
import com.intellij.util.ui.StartupUiUtil;
|
||||
import kotlinx.coroutines.CoroutineScope;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
@@ -32,6 +42,8 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.List;
|
||||
|
||||
public final class QuickChangeLookAndFeel extends QuickSwitchSchemeAction implements ActionRemoteBehaviorSpecification.Frontend {
|
||||
|
||||
@@ -58,6 +70,75 @@ public final class QuickChangeLookAndFeel extends QuickSwitchSchemeAction implem
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull ListPopup createPopup(AnActionEvent e, DefaultActionGroup group, JBPopupFactory.ActionSelectionAid aid) {
|
||||
if (WelcomeFrame.getInstance() == null &&
|
||||
ContainerUtil.exists(group.getChildren(e),
|
||||
action -> action instanceof LafChangeAction lafAction && lafAction.myLookAndFeelInfo.isRestartRequired())) {
|
||||
return new PopupFactoryImpl.ActionGroupPopup(null, getPopupTitle(e), group, e.getDataContext(),
|
||||
myActionPlace == null ? ActionPlaces.POPUP : myActionPlace, new PresentationFactory(),
|
||||
ActionPopupOptions.forAid(aid, true, -1, preselectAction()), null) {
|
||||
@Override
|
||||
protected ListCellRenderer<?> getListElementRenderer() {
|
||||
JLabel icon1 = new JLabel();
|
||||
JLabel icon2 = new JLabel();
|
||||
|
||||
List<Groups.@NotNull GroupInfo<@NotNull UIThemeLookAndFeelInfo>> infos =
|
||||
ThemeListProvider.Companion.getInstance().getShownThemes().getInfos();
|
||||
|
||||
return new PopupListElementRenderer(this) {
|
||||
@Override
|
||||
protected JComponent layoutComponent(JComponent middleItemComponent) {
|
||||
NonOpaquePanel subPanel = new NonOpaquePanel(new BorderLayout());
|
||||
subPanel.add(icon1, BorderLayout.WEST);
|
||||
subPanel.add(icon2, BorderLayout.EAST);
|
||||
icon1.setBorder(JBUI.Borders.emptyLeft(10));
|
||||
icon2.setBorder(JBUI.Borders.emptyLeft(5));
|
||||
|
||||
NonOpaquePanel panel = new NonOpaquePanel(new BorderLayout());
|
||||
panel.add(middleItemComponent);
|
||||
panel.add(subPanel, BorderLayout.EAST);
|
||||
|
||||
return super.layoutComponent(panel);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void customizeComponent(JList list, Object value, boolean isSelected) {
|
||||
super.customizeComponent(list, value, isSelected);
|
||||
|
||||
icon1.setIcon(null);
|
||||
icon2.setIcon(null);
|
||||
myRendererComponent.setToolTipText(null);
|
||||
|
||||
if (value instanceof PopupFactoryImpl.ActionItem item) {
|
||||
AnAction action = item.getAction();
|
||||
if (action instanceof LafChangeAction lafAction) {
|
||||
UIThemeLookAndFeelInfo currentLaf = LafManager.getInstance().getCurrentUIThemeLookAndFeel();
|
||||
|
||||
if (lafAction.myLookAndFeelInfo.isRestartRequired()) {
|
||||
icon1.setIcon(AllIcons.General.Beta);
|
||||
if (!isSelected) {
|
||||
Groups.GroupInfo<@NotNull UIThemeLookAndFeelInfo> group = ContainerUtil.find(infos, info -> ContainerUtil.find(
|
||||
info.getItems(), element -> element.getId().equals(lafAction.myLookAndFeelInfo.getId())) != null);
|
||||
if (group != null &&
|
||||
ContainerUtil.find(group.getItems(), element -> element.getId().equals(currentLaf.getId())) == null) {
|
||||
icon2.setIcon(IconUtilKt.getDisabledIcon(AllIcons.Actions.Restart, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!isSelected && currentLaf.isRestartRequired()) {
|
||||
icon2.setIcon(IconUtilKt.getDisabledIcon(AllIcons.Actions.Restart, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
return super.createPopup(e, group, aid);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void showPopup(AnActionEvent e, ListPopup popup) {
|
||||
ApplicationManager.getApplication().getService(QuickChangeLookAndFeelService.class)
|
||||
@@ -105,6 +186,7 @@ public final class QuickChangeLookAndFeel extends QuickSwitchSchemeAction implem
|
||||
@Override
|
||||
public void actionPerformed(@NotNull AnActionEvent e) {
|
||||
switchLafAndUpdateUI(LafManager.getInstance(), myLookAndFeelInfo, false);
|
||||
LafManager.getInstance().checkRestart();
|
||||
}
|
||||
|
||||
private static @Nullable Icon getIcon(boolean currentLaf) {
|
||||
|
||||
@@ -6,7 +6,6 @@ import com.intellij.application.options.colors.SchemesPanel
|
||||
import com.intellij.application.options.colors.SchemesPanelFactory
|
||||
import com.intellij.application.options.editor.CheckboxDescriptor
|
||||
import com.intellij.application.options.editor.checkBox
|
||||
import com.intellij.icons.AllIcons
|
||||
import com.intellij.ide.DataManager
|
||||
import com.intellij.ide.GeneralSettings
|
||||
import com.intellij.ide.IdeBundle.message
|
||||
@@ -22,7 +21,6 @@ import com.intellij.internal.statistic.service.fus.collectors.UIEventLogger.IdeZ
|
||||
import com.intellij.internal.statistic.service.fus.collectors.UIEventLogger.ThemeAutodetectSelector
|
||||
import com.intellij.openapi.actionSystem.ActionManager
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.impl.islands.IslandsUICustomization
|
||||
import com.intellij.openapi.application.invokeLater
|
||||
import com.intellij.openapi.editor.EditorFactory
|
||||
import com.intellij.openapi.editor.PlatformEditorBundle
|
||||
@@ -164,6 +162,7 @@ internal class AppearanceConfigurable : BoundSearchableConfigurable(message("tit
|
||||
lafProperty.afterChange(disposable!!) {
|
||||
ApplicationManager.getApplication().invokeLater {
|
||||
QuickChangeLookAndFeel.switchLafAndUpdateUI(lafManager, lafManager.findLaf(it.themeId), true)
|
||||
LafManager.getInstance().checkRestart()
|
||||
}
|
||||
}
|
||||
syncThemeProperty.afterChange(disposable!!) {
|
||||
@@ -227,22 +226,6 @@ internal class AppearanceConfigurable : BoundSearchableConfigurable(message("tit
|
||||
disposable?.whenDisposed {
|
||||
colorAndFontsOptions.disposeUIResources()
|
||||
}
|
||||
|
||||
if (IslandsUICustomization.isIslandsAvailable) {
|
||||
row {
|
||||
label(message("ide.islands.combo.option"))
|
||||
.comment(message("ide.restart.required.comment"))
|
||||
.gap(RightGap.SMALL)
|
||||
icon(AllIcons.General.Beta)
|
||||
|
||||
val items = listOf("default", "island", "islands")
|
||||
val cell = comboBox(items, textListCellRenderer { message("ide.islands.type.$it") })
|
||||
.bindItem({ IslandsUICustomization.getIslandsType() }, {})
|
||||
cell.onApply {
|
||||
IslandsUICustomization.setIslandsType(cell.component.item)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
group(message("title.accessibility")) {
|
||||
|
||||
@@ -49,6 +49,11 @@ class UIThemeProvider {
|
||||
@JvmField
|
||||
var targetUI: TargetUIType = TargetUIType.UNSPECIFIED
|
||||
|
||||
@Internal
|
||||
@Attribute("restartRequired")
|
||||
@JvmField
|
||||
var isRestartRequired: Boolean = false
|
||||
|
||||
@Throws(IOException::class)
|
||||
@Internal
|
||||
fun getThemeJson(pluginDescriptor: PluginDescriptor): ByteArray? {
|
||||
|
||||
@@ -19,7 +19,9 @@ import com.intellij.openapi.actionSystem.*
|
||||
import com.intellij.openapi.actionSystem.impl.ActionMenu
|
||||
import com.intellij.openapi.actionSystem.impl.ActionToolbarImpl
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.ApplicationNamesInfo
|
||||
import com.intellij.openapi.application.ex.ApplicationInfoEx
|
||||
import com.intellij.openapi.application.ex.ApplicationManagerEx
|
||||
import com.intellij.openapi.application.impl.RawSwingDispatcher
|
||||
import com.intellij.openapi.components.*
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
@@ -45,9 +47,11 @@ import com.intellij.openapi.util.SystemInfo
|
||||
import com.intellij.openapi.util.SystemInfoRt
|
||||
import com.intellij.openapi.util.registry.Registry
|
||||
import com.intellij.openapi.wm.impl.IdeGlassPaneImpl
|
||||
import com.intellij.openapi.wm.impl.welcomeScreen.WelcomeFrame
|
||||
import com.intellij.platform.diagnostic.telemetry.impl.span
|
||||
import com.intellij.ui.*
|
||||
import com.intellij.ui.dsl.listCellRenderer.listCellRenderer
|
||||
import com.intellij.ui.icons.getDisabledIcon
|
||||
import com.intellij.ui.mac.MacFullScreenControlsManager
|
||||
import com.intellij.ui.popup.HeavyWeightPopup
|
||||
import com.intellij.ui.scale.JBUIScale.getFontScale
|
||||
@@ -74,6 +78,7 @@ import java.awt.event.WindowAdapter
|
||||
import java.awt.event.WindowEvent
|
||||
import java.util.*
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.function.Function
|
||||
import java.util.function.Supplier
|
||||
import javax.swing.*
|
||||
import javax.swing.plaf.FontUIResource
|
||||
@@ -128,6 +133,7 @@ class LafManagerImpl(private val coroutineScope: CoroutineScope) : LafManager(),
|
||||
private var themeDetector: SystemDarkThemeDetector? = null
|
||||
private var isFirstSetup = true
|
||||
private var autodetect = false
|
||||
private var isRestartRequired = false
|
||||
|
||||
// we remember the last used editor scheme for each laf to restore it after switching laf
|
||||
private var rememberSchemeForLaf = true
|
||||
@@ -493,12 +499,32 @@ class LafManagerImpl(private val coroutineScope: CoroutineScope) : LafManager(),
|
||||
}
|
||||
|
||||
override fun getLookAndFeelCellRenderer(component: JComponent): ListCellRenderer<LafReference> {
|
||||
val welcomeMode = WelcomeFrame.getInstance() != null
|
||||
return listCellRenderer {
|
||||
toolTipText = null
|
||||
text(value.name)
|
||||
if (value.themeId.isEmpty()) {
|
||||
separator { }
|
||||
}
|
||||
else {
|
||||
for (group in lafComboBoxModel.value.groupedThemes.infos) {
|
||||
val theme = group.items.find { info -> info.id == value.themeId}
|
||||
if (theme != null) {
|
||||
if (theme.isRestartRequired()) {
|
||||
icon(AllIcons.General.Beta)
|
||||
if (!welcomeMode && value.themeId != currentTheme?.id && group.items.find { info -> info.id == currentTheme?.id} == null) {
|
||||
icon(getDisabledIcon(AllIcons.Actions.Restart, null))
|
||||
toolTipText = IdeBundle.message("ide.restart.required.comment")
|
||||
}
|
||||
}
|
||||
else if (!welcomeMode && value.themeId != currentTheme?.id && currentTheme?.isRestartRequired() == true) {
|
||||
icon(getDisabledIcon(AllIcons.Actions.Restart, null))
|
||||
toolTipText = IdeBundle.message("ide.restart.required.comment")
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
val groupWithSameFirstItem = lafComboBoxModel.value.groupedThemes.infos.firstOrNull { value.themeId == it.items.firstOrNull()?.id }
|
||||
if (groupWithSameFirstItem != null) {
|
||||
separator {
|
||||
@@ -569,6 +595,39 @@ class LafManagerImpl(private val coroutineScope: CoroutineScope) : LafManager(),
|
||||
ActionToolbarImpl.updateAllToolbarsImmediately()
|
||||
}
|
||||
isFirstSetup = false
|
||||
|
||||
isRestartRequired = checkRestart(lookAndFeelInfo, oldLaf)
|
||||
}
|
||||
|
||||
private fun checkRestart(lookAndFeelInfo: UIThemeLookAndFeelInfo, oldLaf: UIThemeLookAndFeelInfo?): Boolean {
|
||||
if (WelcomeFrame.getInstance() != null) {
|
||||
return false
|
||||
}
|
||||
if (!lookAndFeelInfo.isRestartRequired() && oldLaf?.isRestartRequired() == false) {
|
||||
return false
|
||||
}
|
||||
if (lookAndFeelInfo.isRestartRequired() && oldLaf?.isRestartRequired() == true) {
|
||||
val infos = ThemeListProvider.getInstance().getShownThemes().infos
|
||||
val group = infos.find { info -> info.items.find { element -> element.id == lookAndFeelInfo.id } != null }
|
||||
if (group != null && group.items.find { element -> element.id == oldLaf.id } != null) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@Internal
|
||||
override fun checkRestart() {
|
||||
if (isRestartRequired) {
|
||||
isRestartRequired = false
|
||||
|
||||
if (PluginManagerConfigurable.showRestartDialog(IdeBundle.message("dialog.title.restart.required"), Function {
|
||||
IdeBundle.message("dialog.message.must.be.restarted.for.changes.to.take.effect",
|
||||
ApplicationNamesInfo.getInstance().fullProductName)
|
||||
}) == Messages.YES) {
|
||||
ApplicationManagerEx.getApplicationEx().restart(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("unused")
|
||||
@@ -912,9 +971,11 @@ class LafManagerImpl(private val coroutineScope: CoroutineScope) : LafManager(),
|
||||
listOf( Separator(), GetMoreLafAction())).toTypedArray()
|
||||
}
|
||||
|
||||
private fun createThemeActions(separatorText: @NlsContexts.Separator String,
|
||||
lafs: List<UIThemeLookAndFeelInfo>,
|
||||
isDark: Boolean): Collection<AnAction> {
|
||||
private fun createThemeActions(
|
||||
separatorText: @NlsContexts.Separator String,
|
||||
lafs: List<UIThemeLookAndFeelInfo>,
|
||||
isDark: Boolean,
|
||||
): Collection<AnAction> {
|
||||
if (lafs.isEmpty()) {
|
||||
return emptyList()
|
||||
}
|
||||
@@ -975,9 +1036,11 @@ class LafManagerImpl(private val coroutineScope: CoroutineScope) : LafManager(),
|
||||
}.toTypedArray()
|
||||
}
|
||||
|
||||
private fun createSchemeActions(separatorText: @NlsContexts.Separator String?,
|
||||
schemes: List<EditorColorsScheme>,
|
||||
isDark: Boolean): Collection<AnAction> {
|
||||
private fun createSchemeActions(
|
||||
separatorText: @NlsContexts.Separator String?,
|
||||
schemes: List<EditorColorsScheme>,
|
||||
isDark: Boolean,
|
||||
): Collection<AnAction> {
|
||||
if (schemes.isEmpty()) {
|
||||
return emptyList()
|
||||
}
|
||||
@@ -988,8 +1051,10 @@ class LafManagerImpl(private val coroutineScope: CoroutineScope) : LafManager(),
|
||||
return result
|
||||
}
|
||||
|
||||
private inner class SchemeToggleAction(val scheme: EditorColorsScheme,
|
||||
private val isDark: Boolean)
|
||||
private inner class SchemeToggleAction(
|
||||
val scheme: EditorColorsScheme,
|
||||
private val isDark: Boolean,
|
||||
)
|
||||
: DumbAwareToggleAction(scheme.displayName) {
|
||||
|
||||
override fun getActionUpdateThread() = ActionUpdateThread.BGT
|
||||
@@ -1018,9 +1083,11 @@ class LafManagerImpl(private val coroutineScope: CoroutineScope) : LafManager(),
|
||||
(if (isDark) defaultDarkLaf.editorSchemeId else defaultLightLaf.editorSchemeId)
|
||||
?: defaultNonLaFSchemeName(isDark)
|
||||
|
||||
private inner class LafToggleAction(name: @Nls String?,
|
||||
private val themeId: String,
|
||||
private val isDark: Boolean) : DumbAwareToggleAction(name) {
|
||||
private inner class LafToggleAction(
|
||||
name: @Nls String?,
|
||||
private val themeId: String,
|
||||
private val isDark: Boolean,
|
||||
) : DumbAwareToggleAction(name) {
|
||||
override fun getActionUpdateThread() = ActionUpdateThread.BGT
|
||||
|
||||
override fun isSelected(e: AnActionEvent): Boolean {
|
||||
|
||||
@@ -4,7 +4,6 @@ package com.intellij.ide.ui.laf
|
||||
import com.intellij.ide.IdeBundle
|
||||
import com.intellij.ide.ui.TargetUIType
|
||||
import com.intellij.ide.ui.ThemeListProvider
|
||||
import com.intellij.openapi.application.impl.islands.IslandsUICustomization
|
||||
import com.intellij.openapi.editor.colors.Groups
|
||||
import com.intellij.openapi.util.registry.Registry
|
||||
import com.intellij.ui.ExperimentalUI
|
||||
@@ -48,14 +47,11 @@ private class ThemeListProviderImpl : ThemeListProvider {
|
||||
else customThemes.add(info)
|
||||
}
|
||||
}
|
||||
|
||||
if (IslandsUICustomization.isOneIslandEnabled) {
|
||||
else if (ExperimentalUI.isNewUI()) {
|
||||
uiThemeProviderListManager.getThemeListForTargetUI(TargetUIType.ISLAND).forEach { info ->
|
||||
if (!info.isThemeFromPlugin) islandUiThemes.add(info)
|
||||
else customThemes.add(info)
|
||||
}
|
||||
}
|
||||
if (IslandsUICustomization.isManyIslandEnabled) {
|
||||
uiThemeProviderListManager.getThemeListForTargetUI(TargetUIType.ISLANDS).forEach { info ->
|
||||
if (!info.isThemeFromPlugin) islandsUiThemes.add(info)
|
||||
else customThemes.add(info)
|
||||
|
||||
@@ -15,10 +15,7 @@ import com.intellij.ui.AppUIUtil;
|
||||
import com.intellij.ui.IdeUICustomization;
|
||||
import com.intellij.ui.svg.SvgKt;
|
||||
import com.intellij.util.SVGLoader;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.*;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.io.IOException;
|
||||
@@ -35,6 +32,7 @@ import java.util.Objects;
|
||||
public class UIThemeLookAndFeelInfoImpl extends UIManager.LookAndFeelInfo implements UIThemeLookAndFeelInfo {
|
||||
private final UITheme theme;
|
||||
private boolean isInitialized;
|
||||
private boolean restartRequired;
|
||||
|
||||
public UIThemeLookAndFeelInfoImpl(@NotNull UITheme theme) {
|
||||
super(theme.getName(),
|
||||
@@ -178,6 +176,17 @@ public class UIThemeLookAndFeelInfoImpl extends UIManager.LookAndFeelInfo implem
|
||||
return theme.describe();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ApiStatus.Internal
|
||||
public boolean isRestartRequired() {
|
||||
return restartRequired;
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public void setRestartRequired(boolean restartRequired) {
|
||||
this.restartRequired = restartRequired;
|
||||
}
|
||||
|
||||
private static <T extends Enum<T>> String parseEnumValue(Object value, T defaultValue) {
|
||||
if (value instanceof String) {
|
||||
String name = Strings.toUpperCase((String)value);
|
||||
|
||||
@@ -56,7 +56,7 @@ class UiThemeProviderListManager {
|
||||
)
|
||||
}
|
||||
}
|
||||
theme?.let { UIThemeLookAndFeelInfoImpl(/* theme = */ it) }
|
||||
theme?.let { UIThemeLookAndFeelInfoImpl(/* theme = */ it).also { it.setRestartRequired(provider.isRestartRequired) } }
|
||||
}
|
||||
|
||||
LafEntry(
|
||||
@@ -129,7 +129,7 @@ class UiThemeProviderListManager {
|
||||
defaultLightParent = { themeDescriptors.single { it.id == DEFAULT_LIGHT_PARENT_THEME }.theme.get()?.theme },
|
||||
pluginDescriptor = pluginDescriptor,
|
||||
) ?: return@SynchronizedClearableLazy null
|
||||
UIThemeLookAndFeelInfoImpl(theme)
|
||||
UIThemeLookAndFeelInfoImpl(theme).also { it.setRestartRequired(provider.isRestartRequired) }
|
||||
}, bean = provider, pluginDescriptor = pluginDescriptor)
|
||||
themeDescriptors = themeDescriptors + lafEntry
|
||||
return lafEntry
|
||||
|
||||
@@ -1,24 +1,15 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.openapi.application.impl.islands
|
||||
|
||||
import com.intellij.ide.IdeBundle
|
||||
import com.intellij.ide.impl.ProjectUtil
|
||||
import com.intellij.ide.plugins.PluginManagerConfigurable
|
||||
import com.intellij.ide.ui.LafManager
|
||||
import com.intellij.ide.ui.laf.UiThemeProviderListManager
|
||||
import com.intellij.ide.util.PropertiesComponent
|
||||
import com.intellij.openapi.actionSystem.ex.ActionButtonLook
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.ApplicationNamesInfo
|
||||
import com.intellij.openapi.application.ex.ApplicationManagerEx
|
||||
import com.intellij.openapi.application.impl.InternalUICustomization
|
||||
import com.intellij.openapi.application.impl.ToolWindowUIDecorator
|
||||
import com.intellij.openapi.editor.colors.EditorColorsManager
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager
|
||||
import com.intellij.openapi.fileEditor.impl.EditorEmptyTextPainter
|
||||
import com.intellij.openapi.fileEditor.impl.EditorsSplitters
|
||||
import com.intellij.openapi.ui.Divider
|
||||
import com.intellij.openapi.ui.Messages
|
||||
import com.intellij.openapi.ui.OnePixelDivider
|
||||
import com.intellij.openapi.ui.Splittable
|
||||
import com.intellij.openapi.util.registry.Registry
|
||||
@@ -40,74 +31,28 @@ import java.awt.BorderLayout
|
||||
import java.awt.Color
|
||||
import java.awt.Graphics
|
||||
import java.awt.geom.RoundRectangle2D
|
||||
import java.util.function.Function
|
||||
import javax.swing.JComponent
|
||||
import javax.swing.JFrame
|
||||
import javax.swing.JLayeredPane
|
||||
import javax.swing.UIManager
|
||||
|
||||
internal class IslandsUICustomization : InternalUICustomization() {
|
||||
companion object {
|
||||
val isIslandsAvailable: Boolean
|
||||
get() {
|
||||
return Registry.`is`("idea.islands.enabled", false) && !Registry.`is`("llm.riderNext.enabled", false)
|
||||
}
|
||||
private val isIslandsAvailable = !Registry.`is`("llm.riderNext.enabled", false)
|
||||
|
||||
val isIslandsEnabled: Boolean = isIslandsAvailable && getIslandsType() != "default"
|
||||
|
||||
val isOneIslandEnabled: Boolean = isIslandsAvailable && getIslandsType() == "island"
|
||||
|
||||
val isManyIslandEnabled: Boolean = isIslandsAvailable && getIslandsType() == "islands"
|
||||
|
||||
fun getIslandsType(): String = PropertiesComponent.getInstance().getValue("idea.islands.type", "default")
|
||||
|
||||
fun setIslandsType(type: String) {
|
||||
if (type == getIslandsType()) {
|
||||
return
|
||||
}
|
||||
|
||||
PropertiesComponent.getInstance().setValue("idea.islands.type", type)
|
||||
|
||||
val uiThemeManager = UiThemeProviderListManager.getInstance()
|
||||
val isLight = JBColor.isBright()
|
||||
|
||||
val editorScheme: String
|
||||
var newTheme = when (type) {
|
||||
"island" -> {
|
||||
editorScheme = if (isLight) "Light" else "Island Dark"
|
||||
uiThemeManager.findThemeById(if (isLight) "One Island Light" else "One Island Dark")
|
||||
}
|
||||
"islands" -> {
|
||||
editorScheme = if (isLight) "Light" else "Island Dark"
|
||||
uiThemeManager.findThemeById(if (isLight) "Many Islands Light" else "Many Islands Dark")
|
||||
}
|
||||
else -> {
|
||||
editorScheme = if (isLight) "Light" else "Dark"
|
||||
uiThemeManager.findThemeById(if (isLight) "ExperimentalLight" else "ExperimentalDark")
|
||||
}
|
||||
}
|
||||
|
||||
val lafManager = LafManager.getInstance()
|
||||
|
||||
if (newTheme == null) {
|
||||
newTheme = if (isLight) lafManager.defaultLightLaf else lafManager.defaultDarkLaf
|
||||
lafManager.setCurrentLookAndFeel(newTheme!!, true)
|
||||
}
|
||||
else {
|
||||
lafManager.setCurrentLookAndFeel(newTheme, true)
|
||||
}
|
||||
|
||||
val colorsManager = EditorColorsManager.getInstance()
|
||||
newTheme.installEditorScheme(colorsManager.getScheme(editorScheme) ?: colorsManager.defaultScheme)
|
||||
|
||||
if (PluginManagerConfigurable.showRestartDialog(IdeBundle.message("dialog.title.restart.required"), Function {
|
||||
IdeBundle.message("dialog.message.must.be.restarted.for.changes.to.take.effect",
|
||||
ApplicationNamesInfo.getInstance().fullProductName)
|
||||
}) == Messages.YES) {
|
||||
ApplicationManagerEx.getApplicationEx().restart(true)
|
||||
}
|
||||
private val isOneIslandEnabled: Boolean
|
||||
get() {
|
||||
return isIslandsAvailable && JBUI.getInt("Island", 0) == 1
|
||||
}
|
||||
|
||||
private val isManyIslandEnabled: Boolean
|
||||
get() {
|
||||
return isIslandsAvailable && JBUI.getInt("Islands", 0) == 1
|
||||
}
|
||||
|
||||
private val isIslandsEnabled: Boolean
|
||||
get() {
|
||||
return isOneIslandEnabled || isManyIslandEnabled
|
||||
}
|
||||
}
|
||||
|
||||
private val isIslandsGradientEnabled: Boolean = Registry.`is`("idea.islands.gradient.enabled", true)
|
||||
|
||||
|
||||
@@ -695,13 +695,13 @@
|
||||
<themeProvider id="JetBrainsHighContrastTheme" path="/themes/HighContrast.theme.json"/>
|
||||
<bundledColorScheme id="High contrast" path="themes/highContrastScheme.xml"/>
|
||||
|
||||
<themeProvider id="One Island Light" path="/themes/islands/OneIslandLight.theme.json" targetUi="island"/>
|
||||
<themeProvider id="One Island Light" path="/themes/islands/OneIslandLight.theme.json" targetUi="island" restartRequired="true"/>
|
||||
|
||||
<themeProvider id="One Island Dark" path="/themes/islands/OneIslandDark.theme.json" targetUi="island"/>
|
||||
<themeProvider id="One Island Dark" path="/themes/islands/OneIslandDark.theme.json" targetUi="island" restartRequired="true"/>
|
||||
<bundledColorScheme id="Island Dark" path="/themes/islands/IslandSchemeDark.xml"/>
|
||||
|
||||
<themeProvider id="Many Islands Dark" path="/themes/islands/ManyIslandsDark.theme.json" targetUi="islands"/>
|
||||
<themeProvider id="Many Islands Light" path="/themes/islands/ManyIslandsLight.theme.json" targetUi="islands"/>
|
||||
<themeProvider id="Many Islands Dark" path="/themes/islands/ManyIslandsDark.theme.json" targetUi="islands" restartRequired="true"/>
|
||||
<themeProvider id="Many Islands Light" path="/themes/islands/ManyIslandsLight.theme.json" targetUi="islands" restartRequired="true"/>
|
||||
|
||||
<themeMetadataProvider path="/themes/metadata/IntelliJPlatform.themeMetadata.json"/>
|
||||
<themeMetadataProvider path="/themes/metadata/JDK.themeMetadata.json"/>
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
"selectionInactiveBackground": "SelectionInactive"
|
||||
},
|
||||
|
||||
"Islands": 1,
|
||||
"Island": {
|
||||
"arc": 20,
|
||||
"border1.insets": "6,6,6,6"
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
},
|
||||
|
||||
"ui": {
|
||||
"Islands": 1,
|
||||
"Island": {
|
||||
"arc": 20,
|
||||
"border1.insets": "6,6,6,6"
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
"selectionInactiveBackground": "SelectionInactive"
|
||||
},
|
||||
|
||||
"Island": 1,
|
||||
"Island.arc": 20,
|
||||
|
||||
"MainWindow.background": "BackgroundLight",
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
},
|
||||
|
||||
"ui": {
|
||||
"Island": 1,
|
||||
"Island.arc": 20,
|
||||
|
||||
"MainWindow.background": "BackgroundDark",
|
||||
|
||||
@@ -2531,9 +2531,6 @@ ide.popup.async.enabled.description=Feature flag for IJPL-183574 improving UX of
|
||||
station.use.station.comms.tools.management=false
|
||||
station.use.station.comms.tools.management.description=Use station backend for updating/installing tools
|
||||
|
||||
idea.islands.enabled=false
|
||||
idea.islands.enabled.description=Enable Islands UI themes
|
||||
|
||||
idea.islands.gradient.enabled=true
|
||||
idea.islands.gradient.enabled.description=Enable Islands UI themes gradient painter
|
||||
idea.islands.gradient.enabled.restartRequired=true
|
||||
|
||||
Reference in New Issue
Block a user