From af3a1eae2bb35c82e3b705f2bdc32d4490bdd101 Mon Sep 17 00:00:00 2001 From: Rustam Vishnyakov Date: Mon, 30 Jan 2017 13:21:22 +0300 Subject: [PATCH] Schemes UI refactoring, JavaDoc --- .../codeStyle/CodeStyleSchemesActions.java | 111 ++++--------- .../codeStyle/CodeStyleSchemesModel.java | 5 +- .../codeStyle/CodeStyleSchemesPanel.java | 5 - .../options/colors/ColorAndFontOptions.java | 2 +- .../options/colors/ColorSchemeActions.java | 2 +- .../schemes/AbstractSchemeActions.java | 152 ++++++++++++++++-- .../options/schemes/AbstractSchemesPanel.java | 40 +++-- .../options/schemes/SchemesCombo.java | 2 +- .../options/schemes/SchemesModel.java | 65 ++++++-- 9 files changed, 260 insertions(+), 124 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/CodeStyleSchemesActions.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/CodeStyleSchemesActions.java index a627a8a0bee4..12938b8270e3 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/CodeStyleSchemesActions.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/CodeStyleSchemesActions.java @@ -19,19 +19,13 @@ import com.intellij.application.options.SchemesToImportPopup; import com.intellij.application.options.schemes.AbstractSchemeActions; import com.intellij.application.options.schemes.AbstractSchemesPanel; import com.intellij.application.options.schemes.SchemeNameGenerator; -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.Presentation; -import com.intellij.openapi.actionSystem.Separator; import com.intellij.openapi.application.ApplicationBundle; import com.intellij.openapi.application.WriteAction; import com.intellij.openapi.fileChooser.FileChooserFactory; import com.intellij.openapi.fileChooser.FileSaverDescriptor; import com.intellij.openapi.fileChooser.FileSaverDialog; import com.intellij.openapi.options.*; -import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; -import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.project.ProjectUtil; import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.ui.Messages; @@ -43,7 +37,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.OutputStream; -import java.util.List; abstract class CodeStyleSchemesActions extends AbstractSchemeActions { @@ -53,59 +46,6 @@ abstract class CodeStyleSchemesActions extends AbstractSchemeActions defaultActions) { - defaultActions.add(0, new CopyToProjectAction()); - defaultActions.add(1, new CopyToIDEAction()); - defaultActions.add(2, new Separator()); - } - - private class CopyToProjectAction extends DumbAwareAction { - - public CopyToProjectAction() { - super(ApplicationBundle.message("settings.editor.scheme.copy.to.project")); - } - - @Override - public void actionPerformed(AnActionEvent e) { - CodeStyleScheme currentScheme = getCurrentScheme(); - if (currentScheme != null && !getSchemesModel().isProjectScheme(currentScheme)) { - copyToProject(currentScheme); - } - } - - @Override - public void update(AnActionEvent e) { - Presentation p = e.getPresentation(); - CodeStyleScheme currentScheme = getCurrentScheme(); - p.setEnabledAndVisible(currentScheme != null && !getSchemesModel().isProjectScheme(currentScheme)); - } - } - - - private class CopyToIDEAction extends DumbAwareAction { - - public CopyToIDEAction() { - super(ApplicationBundle.message("settings.editor.scheme.copy.to.ide")); - } - - @Override - public void actionPerformed(AnActionEvent e) { - CodeStyleScheme currentScheme = getCurrentScheme(); - if (currentScheme != null && getSchemesModel().isProjectScheme(currentScheme)) { - exportProjectScheme(); - } - } - - @Override - public void update(AnActionEvent e) { - Presentation p = e.getPresentation(); - CodeStyleScheme currentScheme = getCurrentScheme(); - p.setEnabledAndVisible(currentScheme != null && getSchemesModel().isProjectScheme(currentScheme)); - } - } - @Override protected void resetScheme(@NotNull CodeStyleScheme scheme) { if (Messages @@ -113,21 +53,21 @@ abstract class CodeStyleSchemesActions extends AbstractSchemeActions getSchemesModel().nameExists(schemeName)); - CodeStyleScheme newScheme = getSchemesModel().exportProjectScheme(name); - getSchemesModel().setUsePerProjectSettings(false); - getSchemesModel().selectScheme(newScheme, null); + SchemeNameGenerator.getUniqueName(getProjectName(), schemeName -> getModel().containsScheme(schemeName)); + CodeStyleScheme newScheme = getModel().exportProjectScheme(name); + getModel().setUsePerProjectSettings(false); + getModel().selectScheme(newScheme, null); getSchemesPanel().startEdit(); } @@ -159,10 +100,10 @@ abstract class CodeStyleSchemesActions extends AbstractSchemeActions importer = SchemeImporterEP.getImporter(importerName, CodeStyleScheme.class); @@ -198,13 +139,13 @@ abstract class CodeStyleSchemesActions extends AbstractSchemeActions { mySettingsToClone.clear(); } + @SuppressWarnings("unused") @Deprecated public static boolean cannotBeModified(final CodeStyleScheme currentScheme) { return false; @@ -213,7 +214,7 @@ public class CodeStyleSchemesModel implements SchemesModel { } public CodeStyleScheme createNewScheme(final String preferredName, final CodeStyleScheme parentScheme) { - return new CodeStyleSchemeImpl(SchemeNameGenerator.getUniqueName(preferredName, parentScheme, name -> nameExists(name)), + return new CodeStyleSchemeImpl(SchemeNameGenerator.getUniqueName(preferredName, parentScheme, name -> containsScheme(name)), false, parentScheme); } @@ -261,7 +262,7 @@ public class CodeStyleSchemesModel implements SchemesModel { } @Override - public boolean nameExists(@NotNull String name) { + public boolean containsScheme(@NotNull String name) { return findSchemeByName(name) != null; } diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/CodeStyleSchemesPanel.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/CodeStyleSchemesPanel.java index b16adac591a7..0be698ac7bc5 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/CodeStyleSchemesPanel.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/CodeStyleSchemesPanel.java @@ -100,11 +100,6 @@ public class CodeStyleSchemesPanel extends AbstractSchemesPanel return new CodeStyleSchemesActions(this) { - @Override - protected CodeStyleSchemesModel getSchemesModel() { - return myModel; - } - @Override protected void onSchemeChanged(@Nullable CodeStyleScheme scheme) { if (!myIsReset) { 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 39e5fc721a5e..8f5d7377cf21 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 @@ -189,7 +189,7 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract } @Override - public boolean nameExists(@NotNull String name) { + public boolean containsScheme(@NotNull String name) { return mySchemes.get(name) != null || mySchemes.get(SchemeManager.EDITABLE_COPY_PREFIX + name) != null; } diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/ColorSchemeActions.java b/platform/lang-impl/src/com/intellij/application/options/colors/ColorSchemeActions.java index d926cf7f572c..ed20faaf7b70 100644 --- a/platform/lang-impl/src/com/intellij/application/options/colors/ColorSchemeActions.java +++ b/platform/lang-impl/src/com/intellij/application/options/colors/ColorSchemeActions.java @@ -69,7 +69,7 @@ public abstract class ColorSchemeActions extends AbstractSchemeActions { String newName = SchemeNameGenerator.getUniqueName(name != null ? name : "Unnamed", candidate -> getSchemesPanel().getModel() - .nameExists(candidate)); + .containsScheme(candidate)); AbstractColorsScheme newScheme = new EditorColorsSchemeImpl(EmptyColorScheme.INSTANCE); newScheme.setName(newName); newScheme.setDefaultMetaInfo(EmptyColorScheme.INSTANCE); diff --git a/platform/lang-impl/src/com/intellij/application/options/schemes/AbstractSchemeActions.java b/platform/lang-impl/src/com/intellij/application/options/schemes/AbstractSchemeActions.java index 51f3ad2e7b47..8a7192d3603e 100644 --- a/platform/lang-impl/src/com/intellij/application/options/schemes/AbstractSchemeActions.java +++ b/platform/lang-impl/src/com/intellij/application/options/schemes/AbstractSchemeActions.java @@ -28,12 +28,27 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +/** + *

+ * A standard set of scheme actions: copy, reset, rename, etc. used in {@link AbstractSchemesPanel}. More actions can be added via + * {@link #addAdditionalActions(List)} method. Available actions depend on {@link SchemesModel}. If schemes model supports both IDE and + * project schemes, {@link #copyToIDE(Scheme)} and {@link #copyToProject(Scheme)} must be overridden to do the actual job, default + * implementation for the methods does nothing. + *

+ * Import and export actions are available only if there are importer/exporter implementations for the actual scheme type. + * + * @param The actual scheme type. + * @see AbstractSchemesPanel + * @see SchemesModel + * @see SchemeImporter + * @see SchemeExporter + */ public abstract class AbstractSchemeActions { private final Collection mySchemeImportersNames; private final Collection mySchemeExporterNames; - private AbstractSchemesPanel mySchemesPanel; - + private final AbstractSchemesPanel mySchemesPanel; + protected AbstractSchemeActions(@NotNull AbstractSchemesPanel schemesPanel) { mySchemesPanel = schemesPanel; mySchemeImportersNames = getSchemeImportersNames(); @@ -59,6 +74,11 @@ public abstract class AbstractSchemeActions { public final Collection getActions() { List actions = new ArrayList<>(); + if (getModel().supportsProjectSchemes()) { + actions.add(new CopyToProjectAction()); + actions.add(new CopyToIDEAction()); + actions.add(new Separator()); + } actions.add(new CopyAction()); actions.add(new RenameAction()); actions.add(new ResetAction()); @@ -86,7 +106,53 @@ public abstract class AbstractSchemeActions { return actions; } + @SuppressWarnings("unused") protected void addAdditionalActions(@NotNull List defaultActions) {} + + private class CopyToProjectAction extends DumbAwareAction { + + public CopyToProjectAction() { + super(ApplicationBundle.message("settings.editor.scheme.copy.to.project")); + } + + @Override + public void actionPerformed(AnActionEvent e) { + T currentScheme = getCurrentScheme(); + if (currentScheme != null && !getModel().isProjectScheme(currentScheme)) { + copyToProject(currentScheme); + } + } + + @Override + public void update(AnActionEvent e) { + Presentation p = e.getPresentation(); + T currentScheme = getCurrentScheme(); + p.setEnabledAndVisible(currentScheme != null && !getModel().isProjectScheme(currentScheme)); + } + } + + + private class CopyToIDEAction extends DumbAwareAction { + + public CopyToIDEAction() { + super(ApplicationBundle.message("settings.editor.scheme.copy.to.ide")); + } + + @Override + public void actionPerformed(AnActionEvent e) { + T currentScheme = getCurrentScheme(); + if (currentScheme != null && getModel().isProjectScheme(currentScheme)) { + copyToIDE(currentScheme); + } + } + + @Override + public void update(AnActionEvent e) { + Presentation p = e.getPresentation(); + T currentScheme = getCurrentScheme(); + p.setEnabledAndVisible(currentScheme != null && getModel().isProjectScheme(currentScheme)); + } + } private class ResetAction extends DumbAwareAction { @@ -131,7 +197,7 @@ public abstract class AbstractSchemeActions { duplicateScheme(currentScheme, SchemeNameGenerator.getUniqueName( SchemeManager.getDisplayName(currentScheme), - name -> mySchemesPanel.getModel().nameExists(name))); + name -> mySchemesPanel.getModel().containsScheme(name))); currentScheme = getCurrentScheme(); if (currentScheme != null) { mySchemesPanel.startEdit(); @@ -252,29 +318,95 @@ public abstract class AbstractSchemeActions { } } } - + + /** + * Import a scheme using the given importer name. + * + * @param importerName The importer name. + * @see SchemeImporter + * @see SchemeImporterEP + */ protected abstract void importScheme(@NotNull String importerName); + /** + * Reset scheme's settings to their default values (presets). + * + * @param scheme The scheme to reset. + */ protected abstract void resetScheme(@NotNull T scheme); - + + /** + * Creates a copy of the scheme with a different name. + * + * @param scheme The scheme to copy. + * @param newName New name. + */ protected abstract void duplicateScheme(@NotNull T scheme, @NotNull String newName); - + + /** + * Delete the scheme. + * + * @param scheme The scheme to delete. + */ protected abstract void deleteScheme(@NotNull T scheme); - + + /** + * Export the scheme using the given exporter name. + * + * @param scheme The scheme to export. + * @param exporterName The exporter name. + * @see SchemeExporter + * @see SchemeExporterEP + */ protected abstract void exportScheme(@NotNull T scheme, @NotNull String exporterName); + /** + * Make necessary configurable updates when another scheme has been selected. + * + * @param scheme The new current scheme. + */ protected abstract void onSchemeChanged(@Nullable T scheme); - + + /** + * Change scheme's name to the new one. Called when a user stops editing by pressing Enter. + * + * @param scheme The scheme to rename. + * @param newName New scheme name. + */ protected abstract void renameScheme(@NotNull T scheme, @NotNull String newName); + + /** + * Copy the scheme to project. The implementation may decide what name to use. + * + * @param scheme The scheme to copy. + */ + protected void copyToProject(@NotNull T scheme) { + } + + /** + * Copy the scheme to IDE (application). The implementation may decide what name to use. + * + * @param scheme The scheme to copy. + */ + protected void copyToIDE(@NotNull T scheme) { + } + + @NotNull + protected SchemesModel getModel() { + return mySchemesPanel.getModel(); + } @Nullable protected final T getCurrentScheme() { return mySchemesPanel.getSelectedScheme(); } - + + /** + * @return The actual scheme type. + */ protected abstract Class getSchemeType(); - public AbstractSchemesPanel getSchemesPanel() { + public final AbstractSchemesPanel getSchemesPanel() { return mySchemesPanel; } } diff --git a/platform/lang-impl/src/com/intellij/application/options/schemes/AbstractSchemesPanel.java b/platform/lang-impl/src/com/intellij/application/options/schemes/AbstractSchemesPanel.java index 920977d19638..75098b40c4a7 100644 --- a/platform/lang-impl/src/com/intellij/application/options/schemes/AbstractSchemesPanel.java +++ b/platform/lang-impl/src/com/intellij/application/options/schemes/AbstractSchemesPanel.java @@ -28,6 +28,14 @@ import javax.swing.*; import java.awt.*; import java.util.Collection; +/** + * Base panel for schemes combo box and related actions. When settings change, {@link #updateOnCurrentSettingsChange()} method must be + * called to reflect the change in schemes panel. The method should be added to settings model listener. + * + * @param The actual scheme type. + * @see AbstractSchemeActions + * @see SchemesModel + */ public abstract class AbstractSchemesPanel extends JPanel { private SchemesCombo mySchemesCombo; @@ -88,21 +96,26 @@ public abstract class AbstractSchemesPanel extends JPanel { } } - public JComponent getToolbar() { + public final JComponent getToolbar() { return myToolbar; } + /** + * Creates schemes actions. Used when panel UI components are created. + * @return Scheme actions associated with the panel. + * @see AbstractSchemeActions + */ protected abstract AbstractSchemeActions createSchemeActions(); - public T getSelectedScheme() { + public final T getSelectedScheme() { return mySchemesCombo.getSelectedScheme(); } - public void selectScheme(@Nullable T scheme) { + public final void selectScheme(@Nullable T scheme) { mySchemesCombo.selectScheme(scheme); } - public void resetSchemes(@NotNull Collection schemes) { + public final void resetSchemes(@NotNull Collection schemes) { mySchemesCombo.resetSchemes(schemes); } @@ -110,31 +123,38 @@ public abstract class AbstractSchemesPanel extends JPanel { removeAll(); } - public void startEdit() { + public final void startEdit() { mySchemesCombo.startEdit(); } - public void cancelEdit() { + public final void cancelEdit() { mySchemesCombo.cancelEdit(); } - public void showInfo(@Nullable String message, @NotNull MessageType messageType) { + public final void showInfo(@Nullable String message, @NotNull MessageType messageType) { myInfoLabel.setText(message); myInfoLabel.setForeground(messageType.getTitleForeground()); } - public void clearInfo() { + public final void clearInfo() { myInfoLabel.setText(null); } - public AbstractSchemeActions getActions() { + public final AbstractSchemeActions getActions() { return myActions; } + /** + * @return Schemes model implementation. + * @see SchemesModel + */ @NotNull public abstract SchemesModel getModel(); - public void updateOnCurrentSettingsChange() { + /** + * Must be called when any settings are changed. + */ + public final void updateOnCurrentSettingsChange() { mySchemesCombo.updateSelected(); } } diff --git a/platform/lang-impl/src/com/intellij/application/options/schemes/SchemesCombo.java b/platform/lang-impl/src/com/intellij/application/options/schemes/SchemesCombo.java index c08276ca5dde..8c5a838b34b6 100644 --- a/platform/lang-impl/src/com/intellij/application/options/schemes/SchemesCombo.java +++ b/platform/lang-impl/src/com/intellij/application/options/schemes/SchemesCombo.java @@ -294,7 +294,7 @@ public class SchemesCombo { if (name.isEmpty()) { return EMPTY_NAME_MESSAGE; } - else if (mySchemesPanel.getModel().nameExists(name)) { + else if (mySchemesPanel.getModel().containsScheme(name)) { return NAME_ALREADY_EXISTS_MESSAGE; } return null; diff --git a/platform/lang-impl/src/com/intellij/application/options/schemes/SchemesModel.java b/platform/lang-impl/src/com/intellij/application/options/schemes/SchemesModel.java index d95b8204a12d..8331c8eab8c6 100644 --- a/platform/lang-impl/src/com/intellij/application/options/schemes/SchemesModel.java +++ b/platform/lang-impl/src/com/intellij/application/options/schemes/SchemesModel.java @@ -18,20 +18,61 @@ package com.intellij.application.options.schemes; import com.intellij.openapi.options.Scheme; import org.jetbrains.annotations.NotNull; +/** + * A generic schemes model used in schemes UI: schemes combo box and related actions. + * + * @param Actual scheme type derived from {@code Scheme} + * @see AbstractSchemesPanel + * @see AbstractSchemeActions + */ public interface SchemesModel { + /** + * @return True if the model may contain both projects and IDE (application) schemes. + */ boolean supportsProjectSchemes(); - - boolean canDuplicateScheme(@NotNull T scheme ); - - boolean canResetScheme(@NotNull T scheme); - - boolean canDeleteScheme(@NotNull T scheme); - - boolean isProjectScheme(@NotNull T scheme); - - boolean canRenameScheme(@NotNull T scheme); - - boolean nameExists(@NotNull String name); + /** + * @param scheme The scheme to check. + * @return True if the scheme can be duplicated with a different name. + */ + boolean canDuplicateScheme(@NotNull T scheme ); + + /** + * @param scheme The scheme to check. + * @return True if the scheme can be reset from default values (presets) in principle regardless of whether scheme settings actually + * differ from presets or not. + * @see #differsFromDefault(Scheme) + */ + boolean canResetScheme(@NotNull T scheme); + + /** + * @param scheme The scheme to check. + * @return True if the scheme can be deleted, normally applies to custom schemes created by a user. + */ + boolean canDeleteScheme(@NotNull T scheme); + + /** + * @param scheme The scheme to check. + * @return True if the given scheme is a project one. Always {@code false} if project schemes are not supported. + */ + boolean isProjectScheme(@NotNull T scheme); + + /** + * @param scheme The scheme to check. + * @return True if scheme's name can be edited. + */ + boolean canRenameScheme(@NotNull T scheme); + + /** + * @param name The scheme to check. + * @return True if a scheme by the given name already exists. + */ + boolean containsScheme(@NotNull String name); + + /** + * @param scheme The scheme to check. + * @return True if scheme's settings differ from default values (presets). The method is called only if {@link #canResetScheme(Scheme)} + * returns {@code true}. + */ boolean differsFromDefault(@NotNull T scheme); }