From a3aa0fbe87d631d7afe2f8e820d632b595b3ddce Mon Sep 17 00:00:00 2001 From: Rustam Vishnyakov Date: Wed, 14 Sep 2016 15:24:46 +0300 Subject: [PATCH] IDEA-102869 Automatically create a copy of default scheme for chaging --- .../colors/impl/AbstractColorsScheme.java | 18 ++++++ .../colors/impl/DefaultColorsScheme.java | 21 +++++++ .../editor/colors/impl/EmptyColorScheme.java | 5 ++ .../options/colors/ColorAndFontOptions.java | 28 ++++++++- .../options/colors/SchemesPanel.java | 57 +++++++++++++++---- .../application/options/SaveSchemeDialog.java | 16 +++++- .../colors/impl/EditorColorsManagerImpl.java | 28 ++++++++- 7 files changed, 155 insertions(+), 18 deletions(-) diff --git a/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java b/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java index 090e6ced0921..385df80dd010 100644 --- a/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java +++ b/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java @@ -70,6 +70,8 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme { private float myConsoleLineSpacing = -1; private boolean myIsSaveNeeded; + + private boolean myCanBeDeleted = true; // version influences XML format and triggers migration private int myVersion = CURR_VERSION; @@ -835,4 +837,20 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme { public Properties getMetaProperties() { return myMetaInfo; } + + public boolean canBeDeleted() { + return myCanBeDeleted; + } + + public void setCanBeDeleted(boolean canBeDeleted) { + myCanBeDeleted = canBeDeleted; + } + + public boolean isVisible() { + return true; + } + + public static boolean isVisible(@NotNull EditorColorsScheme scheme) { + return !(scheme instanceof AbstractColorsScheme) || ((AbstractColorsScheme)scheme).isVisible(); + } } diff --git a/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/DefaultColorsScheme.java b/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/DefaultColorsScheme.java index e55ecdd5cfac..0dd928987e45 100644 --- a/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/DefaultColorsScheme.java +++ b/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/DefaultColorsScheme.java @@ -27,6 +27,9 @@ import org.jetbrains.annotations.Nullable; import java.awt.*; public class DefaultColorsScheme extends AbstractColorsScheme implements ReadOnlyColorsScheme { + + public final static String EDITABLE_COPY_PREFIX = "#_user_"; + private String myName; public DefaultColorsScheme() { @@ -93,4 +96,22 @@ public class DefaultColorsScheme extends AbstractColorsScheme implements ReadOnl newScheme.setDefaultMetaInfo(this); return newScheme; } + + /** + * Tells if there is an editable user copy of the scheme to be edited. + * + * @return True if the editable copy shall exist, false if the scheme is non-editable. + */ + public boolean hasEditableCopy() { + return true; + } + + public String getEditableCopyName() { + return EDITABLE_COPY_PREFIX + myName; + } + + @Override + public boolean isVisible() { + return false; + } } diff --git a/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/EmptyColorScheme.java b/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/EmptyColorScheme.java index 9f9dfb78c6d2..7637380c3d99 100644 --- a/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/EmptyColorScheme.java +++ b/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/EmptyColorScheme.java @@ -58,4 +58,9 @@ public class EmptyColorScheme extends DefaultColorsScheme { public String getName() { return NAME; } + + @Override + public boolean hasEditableCopy() { + return false; + } } diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java b/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java index 5b29aa3186b4..cf18432f18c6 100644 --- a/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java +++ b/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java @@ -32,7 +32,10 @@ import com.intellij.openapi.editor.colors.impl.*; import com.intellij.openapi.editor.markup.EffectType; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.extensions.Extensions; -import com.intellij.openapi.options.*; +import com.intellij.openapi.options.Configurable; +import com.intellij.openapi.options.ConfigurationException; +import com.intellij.openapi.options.SchemeManager; +import com.intellij.openapi.options.SearchableConfigurable; import com.intellij.openapi.options.colors.*; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; @@ -136,7 +139,7 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract return mySelectedScheme; } - private MyColorScheme getScheme(String name) { + MyColorScheme getScheme(String name) { return mySchemes.get(name); } @@ -168,6 +171,10 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract public static boolean isReadOnly(@NotNull final EditorColorsScheme scheme) { return ((MyColorScheme)scheme).isReadOnly(); } + + public static boolean canBeDeleted(@NotNull final EditorColorsScheme scheme) { + return scheme instanceof MyColorScheme && ((MyColorScheme)scheme).canBeDeleted(); + } @NotNull public String[] getSchemeNames() { @@ -265,7 +272,7 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract // refresh only if scheme is not switched boolean refreshEditors = activeSchemeModified && schemeManager.getCurrentScheme() == activeOriginalScheme; - schemeManager.setSchemes(result, activeOriginalScheme); + schemeManager.setSchemes(includingInvisible(result, schemeManager), activeOriginalScheme); if (refreshEditors) { EditorColorsManagerImpl.schemeChangedOrSwitched(); } @@ -280,6 +287,16 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract } } + private static List includingInvisible(@NotNull List schemeList, + @NotNull SchemeManager schemeManager) { + for (EditorColorsScheme scheme : schemeManager.getAllSchemes()) { + if (!AbstractColorsScheme.isVisible(scheme)) { + schemeList.add(scheme); + } + } + return schemeList; + } + private static void changeLafIfNecessary(boolean isDarkEditorTheme) { String propKey = "change.laf.on.editor.theme.change"; String value = PropertiesComponent.getInstance().getValue(propKey); @@ -1071,6 +1088,11 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract return false; } + @Override + public boolean canBeDeleted() { + return (myParentScheme instanceof AbstractColorsScheme) && ((AbstractColorsScheme)myParentScheme).canBeDeleted(); + } + private boolean isFontModified() { if (!getFontPreferences().equals(myParentScheme.getFontPreferences())) return true; if (getLineSpacing() != myParentScheme.getLineSpacing()) return true; diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/SchemesPanel.java b/platform/lang-impl/src/com/intellij/application/options/colors/SchemesPanel.java index f8cfde8fe328..b0b7013fb308 100644 --- a/platform/lang-impl/src/com/intellij/application/options/colors/SchemesPanel.java +++ b/platform/lang-impl/src/com/intellij/application/options/colors/SchemesPanel.java @@ -22,6 +22,7 @@ import com.intellij.application.options.SkipSelfSearchComponent; import com.intellij.openapi.application.ApplicationBundle; import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.colors.impl.AbstractColorsScheme; +import com.intellij.openapi.editor.colors.impl.DefaultColorsScheme; import com.intellij.openapi.editor.colors.impl.EditorColorsSchemeImpl; import com.intellij.openapi.editor.colors.impl.EmptyColorScheme; import com.intellij.openapi.extensions.Extensions; @@ -37,6 +38,7 @@ import com.intellij.util.EventDispatcher; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.JBInsets; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; @@ -47,7 +49,7 @@ import java.util.List; public class SchemesPanel extends JPanel implements SkipSelfSearchComponent { private final ColorAndFontOptions myOptions; - private ComboBox mySchemeComboBox; + private ComboBox mySchemeComboBox; private JButton myDeleteButton; private JButton myImportButton; @@ -69,10 +71,11 @@ public class SchemesPanel extends JPanel implements SkipSelfSearchComponent { mySchemeComboBox.addActionListener(new ActionListener() { @Override public void actionPerformed(@NotNull ActionEvent e) { - if (mySchemeComboBox.getSelectedIndex() != -1) { - EditorColorsScheme selected = myOptions.selectScheme((String)mySchemeComboBox.getSelectedItem()); + String selectedName = getSelectedSchemeName(); + if (selectedName != null) { + EditorColorsScheme selected = myOptions.selectScheme(selectedName); final boolean readOnly = ColorAndFontOptions.isReadOnly(selected); - myDeleteButton.setEnabled(!readOnly); + myDeleteButton.setEnabled(!readOnly && ColorAndFontOptions.canBeDeleted(selected)); myHintLabel.setVisible(readOnly); if (areSchemesLoaded()) { myDispatcher.getMulticaster().schemeChanged(SchemesPanel.this); @@ -117,8 +120,9 @@ public class SchemesPanel extends JPanel implements SkipSelfSearchComponent { myDeleteButton.addActionListener(new ActionListener() { @Override public void actionPerformed(@NotNull ActionEvent e) { - if (mySchemeComboBox.getSelectedIndex() != -1) { - myOptions.removeScheme((String)mySchemeComboBox.getSelectedItem()); + String selectedName = getSelectedSchemeName(); + if (selectedName != null) { + myOptions.removeScheme(selectedName); } } }); @@ -165,7 +169,7 @@ public class SchemesPanel extends JPanel implements SkipSelfSearchComponent { private void showSaveAsDialog() { List names = ContainerUtil.newArrayList(myOptions.getSchemeNames()); - String selectedName = myOptions.getSelectedScheme().getName(); + String selectedName = getSchemeDisplayName(myOptions.getSelectedScheme().getName()); SaveSchemeDialog dialog = new SaveSchemeDialog(this, ApplicationBundle.message("title.save.color.scheme.as"), names, selectedName); if (dialog.showAndGet()) { myOptions.saveSchemeAs(dialog.getSchemeName()); @@ -187,20 +191,29 @@ public class SchemesPanel extends JPanel implements SkipSelfSearchComponent { if (this != source) { setListLoaded(false); - String selectedSchemeBackup = myOptions.getSelectedScheme().getName(); + EditorColorsScheme selectedSchemeBackup = myOptions.getSelectedScheme(); mySchemeComboBox.removeAllItems(); String[] schemeNames = myOptions.getSchemeNames(); + MySchemeItem itemToSelect = null; for (String schemeName : schemeNames) { - mySchemeComboBox.addItem(schemeName); + EditorColorsScheme scheme = myOptions.getScheme(schemeName); + MySchemeItem item = new MySchemeItem(scheme); + if (scheme == selectedSchemeBackup) itemToSelect = item; + mySchemeComboBox.addItem(item); } - mySchemeComboBox.setSelectedItem(selectedSchemeBackup); + mySchemeComboBox.setSelectedItem(itemToSelect); setListLoaded(true); myDispatcher.getMulticaster().schemeChanged(this); } } + + @Nullable + private String getSelectedSchemeName() { + return mySchemeComboBox.getSelectedIndex() != -1 ? ((MySchemeItem)mySchemeComboBox.getSelectedItem()).getSchemeName() : null; + } private void setListLoaded(final boolean b) { myListLoaded = b; @@ -247,4 +260,28 @@ public class SchemesPanel extends JPanel implements SkipSelfSearchComponent { private static boolean isImportAvailable() { return !SchemeImporterEP.getExtensions(EditorColorsScheme.class).isEmpty(); } + + private final static class MySchemeItem { + private EditorColorsScheme myScheme; + + public MySchemeItem(EditorColorsScheme scheme) { + myScheme = scheme; + } + + public String getSchemeName() { + return myScheme.getName(); + } + + @Override + public String toString() { + return getSchemeDisplayName(getSchemeName()); + } + } + + private final static String getSchemeDisplayName(@NotNull String schemeName) { + return + schemeName.startsWith(DefaultColorsScheme.EDITABLE_COPY_PREFIX) ? + schemeName.substring(DefaultColorsScheme.EDITABLE_COPY_PREFIX.length()) : + schemeName; + } } diff --git a/platform/platform-impl/src/com/intellij/application/options/SaveSchemeDialog.java b/platform/platform-impl/src/com/intellij/application/options/SaveSchemeDialog.java index 1ac010575004..4ad5df4f2a05 100644 --- a/platform/platform-impl/src/com/intellij/application/options/SaveSchemeDialog.java +++ b/platform/platform-impl/src/com/intellij/application/options/SaveSchemeDialog.java @@ -18,6 +18,8 @@ package com.intellij.application.options; import com.intellij.CommonBundle; import com.intellij.openapi.application.ApplicationBundle; +import com.intellij.openapi.editor.colors.ex.DefaultColorSchemesManager; +import com.intellij.openapi.editor.colors.impl.DefaultColorsScheme; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; import com.intellij.util.text.UniqueNameGenerator; @@ -69,12 +71,15 @@ public class SaveSchemeDialog extends DialogWrapper { @Override protected void doOKAction() { - if (getSchemeName().trim().isEmpty()) { + final String schemeName = getSchemeName(); + if (schemeName.trim().isEmpty()) { Messages.showMessageDialog(getContentPane(), ApplicationBundle.message("error.scheme.must.have.a.name"), CommonBundle.getErrorTitle(), Messages.getErrorIcon()); return; } - else if ("default".equals(getSchemeName())) { + else if ( + isDefaultSchemeName(schemeName) || + schemeName.startsWith(DefaultColorsScheme.EDITABLE_COPY_PREFIX)) { Messages.showMessageDialog(getContentPane(), ApplicationBundle.message("error.illegal.scheme.name"), CommonBundle.getErrorTitle(), Messages.getErrorIcon()); return; @@ -90,6 +95,13 @@ public class SaveSchemeDialog extends DialogWrapper { } super.doOKAction(); } + + private static boolean isDefaultSchemeName(@NotNull String schemeName) { + for (DefaultColorsScheme defaultScheme : DefaultColorSchemesManager.getInstance().getAllSchemes()) { + if (schemeName.equalsIgnoreCase(defaultScheme.getName())) return true; + } + return false; + } @Override protected JComponent createCenterPanel() { 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 b35689ac2628..57a57b309d23 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 @@ -137,6 +137,8 @@ public class EditorColorsManagerImpl extends EditorColorsManager implements Pers scheme = getScheme(wizardEditorScheme); LOG.assertTrue(scheme != null, "Wizard scheme " + wizardEditorScheme + " not found"); } + + initEditableDefaultSchemesCopies(); setGlobalSchemeInner(scheme == null ? getDefaultScheme() : scheme); } @@ -147,6 +149,22 @@ public class EditorColorsManagerImpl extends EditorColorsManager implements Pers loadAdditionalTextAttributes(); } + + private void initEditableDefaultSchemesCopies() { + for (DefaultColorsScheme defaultScheme : myDefaultColorSchemeManager.getAllSchemes()) { + if (defaultScheme.hasEditableCopy()) { + String editableCopyName = defaultScheme.getEditableCopyName(); + AbstractColorsScheme editableCopy = (AbstractColorsScheme)getScheme(editableCopyName); + if (editableCopy == null) { + editableCopy = (AbstractColorsScheme)defaultScheme.clone(); + editableCopy.setName(editableCopyName); + addColorsScheme(editableCopy); + } + editableCopy.setCanBeDeleted(false); + } + } + } + private void loadBundledSchemes() { if (!isUnitTestOrHeadlessMode()) { for (BundledColorSchemeEP ep : BundledColorSchemeEP.EP_NAME.getExtensions()) { @@ -246,7 +264,7 @@ public class EditorColorsManagerImpl extends EditorColorsManager implements Pers private static EditorColorsScheme[] getAllVisibleSchemes(@NotNull Collection schemes) { List visibleSchemes = new ArrayList<>(schemes.size() - 1); for (EditorColorsScheme scheme : schemes) { - if (!(scheme instanceof EmptyColorScheme)) { + if (AbstractColorsScheme.isVisible(scheme)) { visibleSchemes.add(scheme); } } @@ -263,8 +281,12 @@ public class EditorColorsManagerImpl extends EditorColorsManager implements Pers } @NotNull - private DefaultColorsScheme getDefaultScheme() { - return myDefaultColorSchemeManager.getFirstScheme(); + private EditorColorsScheme getDefaultScheme() { + DefaultColorsScheme defaultScheme = myDefaultColorSchemeManager.getFirstScheme(); + String editableCopyName = defaultScheme.getEditableCopyName(); + EditorColorsScheme editableCopy = getScheme(editableCopyName); + assert editableCopy != null : "An editable copy of " + defaultScheme.getName() + " has not been initialized."; + return editableCopy; } @NotNull