Color and Code style schemes UI refactoring, dialogless Duplicate action

This commit is contained in:
Rustam Vishnyakov
2017-01-17 15:25:34 +03:00
parent b2dfd5cc4c
commit dd31e6dcbd
13 changed files with 364 additions and 405 deletions
@@ -15,10 +15,9 @@
*/
package com.intellij.application.options.codeStyle;
import com.intellij.application.options.SaveSchemeDialog;
import com.intellij.application.options.SchemesToImportPopup;
import com.intellij.application.options.schemes.AbstractSchemesPanel;
import com.intellij.application.options.schemes.AbstractSchemeActions;
import com.intellij.application.options.schemes.AbstractSchemesPanel;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.Presentation;
@@ -36,12 +35,10 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileWrapper;
import com.intellij.psi.codeStyle.CodeStyleScheme;
import com.intellij.psi.impl.source.codeStyle.CodeStyleSchemesImpl;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.OutputStream;
import java.util.Collection;
import java.util.List;
abstract class CodeStyleSchemesActions extends AbstractSchemeActions<CodeStyleScheme> {
@@ -106,7 +103,7 @@ abstract class CodeStyleSchemesActions extends AbstractSchemeActions<CodeStyleSc
}
@Override
protected void doReset(@NotNull CodeStyleScheme scheme) {
protected void resetScheme(@NotNull CodeStyleScheme scheme) {
if (Messages
.showOkCancelDialog(ApplicationBundle.message("settings.code.style.reset.to.defaults.message"),
ApplicationBundle.message("settings.code.style.reset.to.defaults.title"), Messages.getQuestionIcon()) ==
@@ -117,26 +114,20 @@ abstract class CodeStyleSchemesActions extends AbstractSchemeActions<CodeStyleSc
}
@Override
protected void doSaveAs(@NotNull CodeStyleScheme scheme) {
protected void duplicateScheme(@NotNull CodeStyleScheme scheme, @NotNull String newName) {
if (!getSchemesModel().isProjectScheme(scheme)) {
String selectedName = scheme.getName();
Collection<String> names = CodeStyleSchemesImpl.getSchemeManager().getAllSchemeNames();
SaveSchemeDialog saveDialog =
new SaveSchemeDialog(getSchemesPanel(), ApplicationBundle.message("title.save.code.style.scheme.as"), names, selectedName);
if (saveDialog.showAndGet()) {
CodeStyleScheme newScheme = getSchemesModel().createNewScheme(saveDialog.getSchemeName(), getCurrentScheme());
getSchemesModel().addScheme(newScheme, true);
}
CodeStyleScheme newScheme = getSchemesModel().createNewScheme(newName, getCurrentScheme());
getSchemesModel().addScheme(newScheme, true);
}
}
@Override
protected void doDelete(@NotNull CodeStyleScheme scheme) {
protected void deleteScheme(@NotNull CodeStyleScheme scheme) {
getSchemesModel().removeScheme(scheme);
}
@Override
protected void doImport(@NotNull String importerName) {
protected void importScheme(@NotNull String importerName) {
CodeStyleScheme currentScheme = getCurrentScheme();
if (currentScheme != null) {
chooseAndImport(currentScheme, importerName);
@@ -254,7 +245,7 @@ abstract class CodeStyleSchemesActions extends AbstractSchemeActions<CodeStyleSc
@SuppressWarnings("Duplicates")
@Override
protected void doExport(@NotNull CodeStyleScheme scheme, @NotNull String exporterName) {
protected void exportScheme(@NotNull CodeStyleScheme scheme, @NotNull String exporterName) {
SchemeExporter<CodeStyleScheme> exporter = SchemeExporterEP.getExporter(exporterName, CodeStyleScheme.class);
if (exporter != null) {
String ext = exporter.getExtension();
@@ -15,6 +15,8 @@
*/
package com.intellij.application.options.codeStyle;
import com.intellij.application.options.schemes.SchemesModel;
import com.intellij.application.options.schemes.SchemeNameGenerator;
import com.intellij.openapi.project.Project;
import com.intellij.psi.codeStyle.CodeStyleScheme;
import com.intellij.psi.codeStyle.CodeStyleSchemes;
@@ -30,7 +32,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.*;
public class CodeStyleSchemesModel {
public class CodeStyleSchemesModel implements SchemesModel<CodeStyleScheme> {
private final List<CodeStyleScheme> mySchemes = new ArrayList<>();
private CodeStyleScheme myGlobalSelected;
private final CodeStyleSchemeImpl myProjectScheme;
@@ -207,29 +209,9 @@ public class CodeStyleSchemesModel {
}
public CodeStyleScheme createNewScheme(final String preferredName, final CodeStyleScheme parentScheme) {
String name;
if (preferredName == null) {
if (parentScheme == null) throw new IllegalArgumentException("parentScheme must not be null");
// Generate using parent name
name = null;
for (int i = 1; name == null; i++) {
String currName = parentScheme.getName() + " (" + i + ")";
if (findSchemeByName(currName) == null) {
name = currName;
}
}
}
else {
name = null;
for (int i = 0; name == null; i++) {
String currName = i == 0 ? preferredName : preferredName + " (" + i + ")";
if (findSchemeByName(currName) == null) {
name = currName;
}
}
}
return new CodeStyleSchemeImpl(name, false, parentScheme);
return new CodeStyleSchemeImpl(SchemeNameGenerator.getUniqueName(preferredName, parentScheme, name -> nameExists(name)),
false,
parentScheme);
}
@Nullable
@@ -244,10 +226,41 @@ public class CodeStyleSchemesModel {
return myProjectScheme;
}
public boolean isProjectScheme(CodeStyleScheme scheme) {
@Override
public boolean supportsProjectSchemes() {
return true;
}
@Override
public boolean canDuplicateScheme(@NotNull CodeStyleScheme scheme) {
return !isProjectScheme(scheme);
}
@Override
public boolean canResetScheme(@NotNull CodeStyleScheme scheme) {
return true;
}
@Override
public boolean canDeleteScheme(@NotNull CodeStyleScheme scheme) {
return !isProjectScheme(scheme) && !scheme.isDefault();
}
@Override
public boolean isProjectScheme(@NotNull CodeStyleScheme scheme) {
return myProjectScheme == scheme;
}
@Override
public boolean canRenameScheme(@NotNull CodeStyleScheme scheme) {
return canDeleteScheme(scheme);
}
@Override
public boolean nameExists(@NotNull String name) {
return findSchemeByName(name) != null;
}
public List<CodeStyleScheme> getAllSortedSchemes() {
List<CodeStyleScheme> schemes = new ArrayList<>();
schemes.addAll(getSchemes());
@@ -17,9 +17,9 @@
package com.intellij.application.options.codeStyle;
import com.intellij.application.options.schemes.AbstractSchemesPanel;
import com.intellij.application.options.schemes.AbstractSchemeActions;
import com.intellij.application.options.schemes.SchemeListItem;
import com.intellij.application.options.schemes.AbstractSchemesPanel;
import com.intellij.application.options.schemes.SchemesModel;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.psi.codeStyle.CodeStyleScheme;
import com.intellij.psi.impl.source.codeStyle.CodeStyleSchemeImpl;
@@ -113,7 +113,7 @@ public class CodeStyleSchemesPanel extends AbstractSchemesPanel<CodeStyleScheme>
}
@Override
protected void doRename(@NotNull CodeStyleScheme scheme, @NotNull String newName) {
protected void renameScheme(@NotNull CodeStyleScheme scheme, @NotNull String newName) {
CodeStyleSchemeImpl newScheme = new CodeStyleSchemeImpl(newName, false, scheme);
myModel.addScheme(newScheme, false);
myModel.removeScheme(scheme);
@@ -122,44 +122,10 @@ public class CodeStyleSchemesPanel extends AbstractSchemesPanel<CodeStyleScheme>
};
}
@NotNull
@Override
public SchemeListItem<CodeStyleScheme> createItem(@NotNull CodeStyleScheme scheme) {
return new SchemeListItem<CodeStyleScheme>(scheme) {
@Override
public boolean isDuplicateAvailable() {
return !myModel.isProjectScheme(scheme);
}
@Override
public boolean isResetAvailable() {
return true;
}
@Override
public boolean isDeleteAvailable() {
return !myModel.isProjectScheme(scheme) && !scheme.isDefault();
}
@Override
public SchemeLevel getSchemeLevel() {
return myModel.isProjectScheme(scheme) ? SchemeLevel.Project : SchemeLevel.IDE;
}
@Override
public boolean isRenameAvailable() {
return isDeleteAvailable();
}
@Nullable
@Override
public String validateSchemeName(@NotNull String name) {
for (CodeStyleScheme scheme : myModel.getSchemes()) {
if (name.equals(scheme.getName()) && scheme != getScheme()) {
return NAME_ALREADY_EXISTS_MESSAGE;
}
}
return super.validateSchemeName(name);
}
};
public SchemesModel<CodeStyleScheme> getModel() {
return myModel;
}
}
@@ -18,6 +18,7 @@ package com.intellij.application.options.colors;
import com.intellij.application.options.OptionsContainingConfigurable;
import com.intellij.application.options.editor.EditorOptionsProvider;
import com.intellij.application.options.schemes.SchemesModel;
import com.intellij.execution.impl.ConsoleViewUtil;
import com.intellij.ide.ui.LafManager;
import com.intellij.ide.ui.laf.LafManagerImpl;
@@ -54,7 +55,6 @@ import com.intellij.psi.search.scope.packageSet.NamedScope;
import com.intellij.psi.search.scope.packageSet.NamedScopesHolder;
import com.intellij.psi.search.scope.packageSet.PackageSet;
import com.intellij.ui.ColorUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.EventDispatcher;
import com.intellij.util.ui.UIUtil;
import gnu.trove.THashMap;
@@ -70,7 +70,8 @@ import java.awt.*;
import java.util.*;
import java.util.List;
public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract implements EditorOptionsProvider {
public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract
implements EditorOptionsProvider, SchemesModel<EditorColorsScheme> {
public static final String ID = "reference.settingsdialog.IDE.editor.colors";
private Map<String, MyColorScheme> mySchemes;
@@ -143,23 +144,6 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract
return mySchemes.get(name);
}
@NotNull
public String getUniqueName(@NotNull String preferredName) {
String name;
if (mySchemes.containsKey(preferredName)) {
for (int i = 1; ; i++) {
name = preferredName + " (" + i + ")";
if (!mySchemes.containsKey(name)) {
break;
}
}
}
else {
name = preferredName;
}
return name;
}
public EditorColorsScheme getSelectedScheme() {
return mySelectedScheme;
}
@@ -168,6 +152,46 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract
return mySelectedScheme.getDescriptors();
}
@Override
public boolean supportsProjectSchemes() {
return false;
}
@Override
public boolean canDuplicateScheme(@NotNull EditorColorsScheme scheme) {
return true;
}
@Override
public boolean canResetScheme(@NotNull EditorColorsScheme scheme) {
AbstractColorsScheme originalScheme =
scheme instanceof AbstractColorsScheme ? ((AbstractColorsScheme)scheme).getOriginal() : null;
return
!isReadOnly(scheme) &&
scheme.getName().startsWith(SchemeManager.EDITABLE_COPY_PREFIX) &&
originalScheme instanceof ReadOnlyColorsScheme;
}
@Override
public boolean canDeleteScheme(@NotNull EditorColorsScheme scheme) {
return !isReadOnly(scheme) && canBeDeleted(scheme);
}
@Override
public boolean isProjectScheme(@NotNull EditorColorsScheme scheme) {
return false;
}
@Override
public boolean canRenameScheme(@NotNull EditorColorsScheme scheme) {
return canDeleteScheme(scheme);
}
@Override
public boolean nameExists(@NotNull String name) {
return mySchemes.get(name) != null || mySchemes.get(SchemeManager.EDITABLE_COPY_PREFIX + name) != null;
}
public static boolean isReadOnly(@NotNull final EditorColorsScheme scheme) {
return ((MyColorScheme)scheme).isReadOnly();
}
@@ -175,16 +199,6 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract
public static boolean canBeDeleted(@NotNull final EditorColorsScheme scheme) {
return scheme instanceof MyColorScheme && ((MyColorScheme)scheme).canBeDeleted();
}
@NotNull
public String[] getSchemeNames() {
List<String> names = new ArrayList<>();
for (EditorColorsScheme scheme : getOrderedSchemes()) {
names.add(scheme.getName());
}
return ArrayUtil.toStringArray(names);
}
@NotNull
public Collection<EditorColorsScheme> getOrderedSchemes() {
@@ -198,12 +212,6 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract
return new ArrayList<>(mySchemes.values());
}
public void saveSchemeAs(String name) {
MyColorScheme scheme = mySelectedScheme;
if (scheme == null) return;
saveSchemeAs(scheme, name);
}
public boolean saveSchemeAs(@NotNull EditorColorsScheme editorScheme, @NotNull String name) {
if (editorScheme instanceof MyColorScheme) {
MyColorScheme scheme = (MyColorScheme)editorScheme;
@@ -15,21 +15,23 @@
*/
package com.intellij.application.options.colors;
import com.intellij.application.options.SaveSchemeDialog;
import com.intellij.application.options.schemes.AbstractSchemesPanel;
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.application.ApplicationBundle;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.colors.impl.AbstractColorsScheme;
import com.intellij.openapi.editor.colors.impl.EditorColorsSchemeImpl;
import com.intellij.openapi.editor.colors.impl.EmptyColorScheme;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.options.*;
import com.intellij.openapi.options.SchemeImportException;
import com.intellij.openapi.options.SchemeImportUtil;
import com.intellij.openapi.options.SchemeImporter;
import com.intellij.openapi.options.SchemeImporterEP;
import com.intellij.openapi.project.DefaultProjectFactory;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
@@ -53,7 +55,7 @@ public abstract class ColorSchemeActions extends AbstractSchemeActions<EditorCol
}
@Override
protected void doImport(@NotNull String importerName) {
protected void importScheme(@NotNull String importerName) {
if (tryImportWithImportHandler(importerName)) {
return;
}
@@ -65,7 +67,9 @@ public abstract class ColorSchemeActions extends AbstractSchemeActions<EditorCol
EditorColorsScheme imported =
importer.importScheme(DefaultProjectFactory.getInstance().getDefaultProject(), importSource, getOptions().getSelectedScheme(),
name -> {
String newName = getOptions().getUniqueName(name != null ? name : "Unnamed");
String newName = SchemeNameGenerator.getUniqueName(name != null ? name : "Unnamed",
candidate -> getSchemesPanel().getModel()
.nameExists(candidate));
AbstractColorsScheme newScheme = new EditorColorsSchemeImpl(EmptyColorScheme.INSTANCE);
newScheme.setName(newName);
newScheme.setDefaultMetaInfo(EmptyColorScheme.INSTANCE);
@@ -95,7 +99,7 @@ public abstract class ColorSchemeActions extends AbstractSchemeActions<EditorCol
}
@Override
protected void doReset(@NotNull EditorColorsScheme scheme) {
protected void resetScheme(@NotNull EditorColorsScheme scheme) {
if (Messages
.showOkCancelDialog(ApplicationBundle.message("color.scheme.reset.message"),
ApplicationBundle.message("color.scheme.reset.title"), Messages.getQuestionIcon()) == Messages.OK) {
@@ -104,23 +108,17 @@ public abstract class ColorSchemeActions extends AbstractSchemeActions<EditorCol
}
@Override
protected void doSaveAs(@NotNull EditorColorsScheme scheme) {
List<String> names = ContainerUtil.newArrayList(getOptions().getSchemeNames());
String selectedName = SchemeManager.getDisplayName(scheme);
SaveSchemeDialog dialog =
new SaveSchemeDialog(getSchemesPanel(), ApplicationBundle.message("title.save.color.scheme.as"), names, selectedName);
if (dialog.showAndGet()) {
getOptions().saveSchemeAs(dialog.getSchemeName());
}
protected void duplicateScheme(@NotNull EditorColorsScheme scheme, @NotNull String newName) {
getOptions().saveSchemeAs(scheme, newName);
}
@Override
protected void doDelete(@NotNull EditorColorsScheme scheme) {
protected void deleteScheme(@NotNull EditorColorsScheme scheme) {
getOptions().removeScheme(scheme.getName());
}
@Override
protected void doExport(@NotNull EditorColorsScheme scheme, @NotNull String exporterName) {
protected void exportScheme(@NotNull EditorColorsScheme scheme, @NotNull String exporterName) {
// Unsupported for now.
}
@@ -17,13 +17,10 @@
package com.intellij.application.options.colors;
import com.intellij.application.options.SkipSelfSearchComponent;
import com.intellij.application.options.schemes.AbstractSchemesPanel;
import com.intellij.application.options.schemes.AbstractSchemeActions;
import com.intellij.application.options.schemes.SchemeListItem;
import com.intellij.application.options.schemes.AbstractSchemesPanel;
import com.intellij.application.options.schemes.SchemesModel;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.colors.impl.AbstractColorsScheme;
import com.intellij.openapi.editor.colors.impl.ReadOnlyColorsScheme;
import com.intellij.openapi.options.SchemeManager;
import com.intellij.util.EventDispatcher;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -97,7 +94,7 @@ public class SchemesPanel extends AbstractSchemesPanel<EditorColorsScheme> imple
}
@Override
protected void doRename(@NotNull EditorColorsScheme scheme, @NotNull String newName) {
protected void renameScheme(@NotNull EditorColorsScheme scheme, @NotNull String newName) {
if (myOptions.saveSchemeAs(scheme, newName)) {
myOptions.removeScheme(scheme.getName());
myOptions.selectScheme(newName);
@@ -106,52 +103,10 @@ public class SchemesPanel extends AbstractSchemesPanel<EditorColorsScheme> imple
};
}
@NotNull
@Override
public SchemeListItem<EditorColorsScheme> createItem(@NotNull EditorColorsScheme scheme) {
return new SchemeListItem<EditorColorsScheme>(scheme) {
@Override
public boolean isDuplicateAvailable() {
return true;
}
@Override
public boolean isResetAvailable() {
AbstractColorsScheme originalScheme =
scheme instanceof AbstractColorsScheme ? ((AbstractColorsScheme)scheme).getOriginal() : null;
return
!ColorAndFontOptions.isReadOnly(scheme) &&
scheme.getName().startsWith(SchemeManager.EDITABLE_COPY_PREFIX) &&
originalScheme instanceof ReadOnlyColorsScheme;
}
@Override
public boolean isDeleteAvailable() {
return !ColorAndFontOptions.isReadOnly(scheme) && ColorAndFontOptions.canBeDeleted(scheme);
}
@Override
public SchemeLevel getSchemeLevel() {
return SchemeLevel.IDE_Only;
}
@Override
public boolean isRenameAvailable() {
return isDeleteAvailable();
}
@Nullable
@Override
public String validateSchemeName(@NotNull String name) {
EditorColorsScheme scheme = myOptions.getScheme(name);
if (scheme == null) {
scheme = myOptions.getScheme(SchemeManager.EDITABLE_COPY_PREFIX + name);
}
if (scheme != null && name.equals(SchemeManager.getDisplayName(scheme)) && scheme != getScheme()) {
return NAME_ALREADY_EXISTS_MESSAGE;
}
return super.validateSchemeName(name);
}
};
public SchemesModel<EditorColorsScheme> getModel() {
return myOptions;
}
}
@@ -17,9 +17,7 @@ package com.intellij.application.options.schemes;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.openapi.options.Scheme;
import com.intellij.openapi.options.SchemeExporterEP;
import com.intellij.openapi.options.SchemeImporterEP;
import com.intellij.openapi.options.*;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.ui.popup.ListPopup;
@@ -31,6 +29,7 @@ import java.util.Collection;
import java.util.List;
public abstract class AbstractSchemeActions<T extends Scheme> {
private final Collection<String> mySchemeImportersNames;
private final Collection<String> mySchemeExporterNames;
private AbstractSchemesPanel<T> mySchemesPanel;
@@ -99,15 +98,16 @@ public abstract class AbstractSchemeActions<T extends Scheme> {
public void actionPerformed(AnActionEvent e) {
T currentScheme = getCurrentScheme();
if (currentScheme != null) {
doReset(currentScheme);
}
mySchemesPanel.cancelEdit();
resetScheme(currentScheme);
}
}
@Override
public void update(AnActionEvent e) {
Presentation p = e.getPresentation();
SchemeListItem<T> item = mySchemesPanel.getSelectedItem();
p.setEnabled(item != null && item.isResetAvailable());
T scheme = getCurrentScheme();
p.setEnabled(scheme != null && mySchemesPanel.getModel().canResetScheme(scheme));
}
}
@@ -121,15 +121,23 @@ public abstract class AbstractSchemeActions<T extends Scheme> {
public void actionPerformed(AnActionEvent e) {
T currentScheme = getCurrentScheme();
if (currentScheme != null) {
doSaveAs(currentScheme);
mySchemesPanel.cancelEdit();
duplicateScheme(currentScheme,
SchemeNameGenerator.getUniqueName(
SchemeManager.getDisplayName(currentScheme),
name -> mySchemesPanel.getModel().nameExists(name)));
currentScheme = getCurrentScheme();
if (currentScheme != null) {
mySchemesPanel.startEdit();
}
}
}
@Override
public void update(AnActionEvent e) {
Presentation p = e.getPresentation();
SchemeListItem<T> item = mySchemesPanel.getSelectedItem();
p.setEnabledAndVisible(item != null && item.isDuplicateAvailable());
T scheme = getCurrentScheme();
p.setEnabledAndVisible(scheme != null && mySchemesPanel.getModel().canDuplicateScheme(scheme));
}
}
@@ -150,8 +158,8 @@ public abstract class AbstractSchemeActions<T extends Scheme> {
@Override
public void update(AnActionEvent e) {
Presentation p = e.getPresentation();
SchemeListItem<T> item = mySchemesPanel.getSelectedItem();
p.setEnabled(item != null && item.isRenameAvailable());
T scheme = getCurrentScheme();
p.setEnabledAndVisible(scheme != null && mySchemesPanel.getModel().canRenameScheme(scheme));
}
}
@@ -164,15 +172,16 @@ public abstract class AbstractSchemeActions<T extends Scheme> {
public void actionPerformed(AnActionEvent e) {
T currentScheme = getCurrentScheme();
if (currentScheme != null) {
doDelete(currentScheme);
mySchemesPanel.cancelEdit();
deleteScheme(currentScheme);
}
}
@Override
public void update(AnActionEvent e) {
Presentation p = e.getPresentation();
SchemeListItem<T> item = mySchemesPanel.getSelectedItem();
p.setEnabledAndVisible(item != null && item.isDeleteAvailable());
T scheme = getCurrentScheme();
p.setEnabledAndVisible(scheme != null && mySchemesPanel.getModel().canDeleteScheme(scheme));
}
}
@@ -215,7 +224,8 @@ public abstract class AbstractSchemeActions<T extends Scheme> {
@Override
public void actionPerformed(AnActionEvent e) {
doImport(myImporterName);
mySchemesPanel.cancelEdit();
importScheme(myImporterName);
}
}
@@ -231,24 +241,25 @@ public abstract class AbstractSchemeActions<T extends Scheme> {
public void actionPerformed(AnActionEvent e) {
T currentScheme = getCurrentScheme();
if (currentScheme != null) {
doExport(currentScheme, myExporterName);
mySchemesPanel.cancelEdit();
exportScheme(currentScheme, myExporterName);
}
}
}
protected abstract void importScheme(@NotNull String importerName);
protected abstract void doImport(@NotNull String importerName);
protected abstract void doReset(@NotNull T scheme);
protected abstract void resetScheme(@NotNull T scheme);
protected abstract void doSaveAs(@NotNull T scheme);
protected abstract void duplicateScheme(@NotNull T scheme, @NotNull String newName);
protected abstract void doDelete(@NotNull T scheme);
protected abstract void deleteScheme(@NotNull T scheme);
protected abstract void doExport(@NotNull T scheme, @NotNull String exporterName);
protected abstract void exportScheme(@NotNull T scheme, @NotNull String exporterName);
protected abstract void onSchemeChanged(@Nullable T scheme);
protected abstract void doRename(@NotNull T scheme, @NotNull String newName);
protected abstract void renameScheme(@NotNull T scheme, @NotNull String newName);
@Nullable
protected final T getCurrentScheme() {
@@ -28,7 +28,7 @@ import javax.swing.*;
import java.awt.*;
import java.util.Collection;
public abstract class AbstractSchemesPanel<T extends Scheme> extends JPanel implements SchemeListItemFactory<T> {
public abstract class AbstractSchemesPanel<T extends Scheme> extends JPanel {
private SchemesCombo<T> mySchemesCombo;
private AbstractSchemeActions<T> myActions;
@@ -98,10 +98,6 @@ public abstract class AbstractSchemesPanel<T extends Scheme> extends JPanel impl
return mySchemesCombo.getSelectedScheme();
}
public SchemeListItem<T> getSelectedItem() {
return mySchemesCombo.getSelectedItem();
}
public void selectScheme(@Nullable T scheme) {
mySchemesCombo.selectScheme(scheme);
}
@@ -117,6 +113,10 @@ public abstract class AbstractSchemesPanel<T extends Scheme> extends JPanel impl
public void startEdit() {
mySchemesCombo.startEdit();
}
public void cancelEdit() {
mySchemesCombo.cancelEdit();
}
public void showInfo(@Nullable String message, @NotNull MessageType messageType) {
myInfoLabel.setText(message);
@@ -131,54 +131,6 @@ public abstract class AbstractSchemesPanel<T extends Scheme> extends JPanel impl
return myActions;
}
@Override
public SchemeListItem<T> createSeparator(@NotNull String title) {
return new SeparatorItem(title);
}
private class SeparatorItem extends SchemeListItem<T> {
private String myTitle;
public SeparatorItem(@NotNull String title) {
super(null);
myTitle = title;
}
@Override
public boolean isSeparator() {
return true;
}
@Override
public boolean isDuplicateAvailable() {
return false;
}
@Override
public boolean isResetAvailable() {
return false;
}
@Override
public boolean isDeleteAvailable() {
return false;
}
@Override
public SchemeLevel getSchemeLevel() {
return SchemeLevel.IDE_Only;
}
@Override
public boolean isRenameAvailable() {
return false;
}
@NotNull
@Override
public String getPresentableText() {
return myTitle;
}
}
@NotNull
public abstract SchemesModel<T> getModel();
}
@@ -1,74 +0,0 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.application.options.schemes;
import com.intellij.openapi.options.Scheme;
import com.intellij.openapi.options.SchemeManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class SchemeListItem<T extends Scheme> {
public static final String EMPTY_NAME_MESSAGE = "The name must not be empty";
public static final String NAME_ALREADY_EXISTS_MESSAGE = "The name already exists";
public enum SchemeLevel {
IDE_Only, IDE, Project
}
private @Nullable T myScheme;
public SchemeListItem(@Nullable T scheme) {
myScheme = scheme;
}
@Nullable
public String getSchemeName() {
return myScheme != null ? myScheme.getName() : null;
}
@Nullable
public T getScheme() {
return myScheme;
}
@NotNull
public String getPresentableText() {
return myScheme != null ? SchemeManager.getDisplayName(myScheme) : "";
}
public boolean isSeparator() {
return false;
}
public abstract boolean isDuplicateAvailable();
public abstract boolean isResetAvailable();
public abstract boolean isDeleteAvailable();
public abstract SchemeLevel getSchemeLevel();
public abstract boolean isRenameAvailable();
@Nullable
public String validateSchemeName(@NotNull String name) {
if (name.isEmpty()) {
return EMPTY_NAME_MESSAGE;
}
return null;
}
}
@@ -0,0 +1,59 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.application.options.schemes;
import com.intellij.openapi.options.Scheme;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.function.Function;
public class SchemeNameGenerator {
private final static String COPY_NAME_SUFFIX = "copy";
private SchemeNameGenerator() {
}
public static String getUniqueName(@NotNull String preferredName, @NotNull Function<String, Boolean> nameExistsFunction) {
if (nameExistsFunction.apply(preferredName)) {
int numberPos = preferredName.length() - 1;
while (numberPos >= 0 && Character.isDigit(preferredName.charAt(numberPos))) {
numberPos--;
}
String baseName = numberPos >= 0 ? preferredName.substring(0, numberPos + 1) : preferredName;
if (!baseName.endsWith(COPY_NAME_SUFFIX)) {
baseName = preferredName + " " + COPY_NAME_SUFFIX;
}
if (!nameExistsFunction.apply(baseName)) return baseName;
int i = 1;
while (true) {
String newName = baseName + i;
if (!nameExistsFunction.apply(newName)) return newName;
i++;
}
}
return preferredName;
}
public static String getUniqueName(@Nullable String preferredName,
@Nullable Scheme parentScheme,
@NotNull Function<String, Boolean> nameExistsFunction) {
assert preferredName != null || parentScheme != null : "Either preferredName or parentScheme must be non-null";
String baseName = preferredName != null ? preferredName : parentScheme.getName();
return getUniqueName(baseName, nameExistsFunction);
}
}
@@ -16,6 +16,7 @@
package com.intellij.application.options.schemes;
import com.intellij.openapi.options.Scheme;
import com.intellij.openapi.options.SchemeManager;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.ui.MessageType;
import com.intellij.ui.*;
@@ -28,9 +29,18 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.Collection;
import java.util.function.Function;
public class SchemesCombo<T extends Scheme> {
private ComboBox<SchemeListItem<T>> myComboBox;
// region Message constants
public static final String PROJECT_LEVEL = "Project";
public static final String IDE_LEVEL = "IDE";
public static final String EMPTY_NAME_MESSAGE = "The name must not be empty";
public static final String NAME_ALREADY_EXISTS_MESSAGE = "The name already exists";
// endregion
private ComboBox<MySchemeListItem<T>> myComboBox;
private JPanel myRootPanel;
private AbstractSchemesPanel<T> mySchemesPanel;
private final CardLayout myLayout;
@@ -69,20 +79,26 @@ public class SchemesCombo<T extends Scheme> {
private void stopEdit() {
String newName = myNameEditorField.getText();
SchemeListItem<T> selectedItem = getSelectedItem();
String validationMessage = selectedItem != null ? selectedItem.validateSchemeName(newName) : null;
if (validationMessage != null) {
mySchemesPanel.showInfo(validationMessage, MessageType.ERROR);
}
else {
cancelEdit();
if (selectedItem != null && selectedItem.getScheme() != null) {
mySchemesPanel.getActions().doRename(selectedItem.getScheme(), newName);
MySchemeListItem<T> selectedItem = getSelectedItem();
if (selectedItem != null) {
if (newName.equals(selectedItem.getSchemeName())) {
cancelEdit();
return;
}
String validationMessage = validateSchemeName(newName);
if (validationMessage != null) {
mySchemesPanel.showInfo(validationMessage, MessageType.ERROR);
}
else {
cancelEdit();
if (selectedItem.getScheme() != null) {
mySchemesPanel.getActions().renameScheme(selectedItem.getScheme(), newName);
}
}
}
}
private void cancelEdit() {
public void cancelEdit() {
mySchemesPanel.clearInfo();
myLayout.first(myRootPanel);
myRootPanel.requestFocus();
@@ -97,10 +113,10 @@ public class SchemesCombo<T extends Scheme> {
mySchemesPanel.getActions().onSchemeChanged(getSelectedScheme());
}
});
myComboBox.setModel(new DefaultComboBoxModel<SchemeListItem<T>>() {
myComboBox.setModel(new DefaultComboBoxModel<MySchemeListItem<T>>() {
@Override
public void setSelectedItem(Object anObject) {
if (anObject instanceof SchemeListItem && ((SchemeListItem)anObject).isSeparator()) {
if (anObject instanceof MySchemeListItem && ((MySchemeListItem)anObject).isSeparator()) {
return;
}
super.setSelectedItem(anObject);
@@ -117,31 +133,40 @@ public class SchemesCombo<T extends Scheme> {
}
}
private SimpleTextAttributes getSchemeAttributes(@NotNull SchemeListItem<T> item) {
return item.isDeleteAvailable() ? SimpleTextAttributes.REGULAR_ATTRIBUTES : SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES;
private SimpleTextAttributes getSchemeAttributes(@NotNull MySchemeListItem<T> item) {
T scheme = item.getScheme();
return scheme != null && mySchemesPanel.getModel().canDeleteScheme(scheme)
? SimpleTextAttributes.REGULAR_ATTRIBUTES
: SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES;
}
public void resetSchemes(@NotNull Collection<T> schemes) {
myComboBox.removeAllItems();
SchemeListItem.SchemeLevel currSchemeLevel = SchemeListItem.SchemeLevel.IDE_Only;
SchemesModel<T> model = mySchemesPanel.getModel();
if (model.supportsProjectSchemes()) {
myComboBox.addItem(new MySeparatorItem(PROJECT_LEVEL));
addItems(schemes, scheme -> model.isProjectScheme(scheme));
myComboBox.addItem(new MySeparatorItem(IDE_LEVEL));
addItems(schemes, scheme -> !model.isProjectScheme(scheme));
}
else {
addItems(schemes, scheme -> true);
}
}
private void addItems(@NotNull Collection<T> schemes, Function<T,Boolean> filter) {
for (T scheme : schemes) {
SchemeListItem<T> item = mySchemesPanel.createItem(scheme);
SchemeListItem.SchemeLevel schemeLevel = item.getSchemeLevel();
if (!currSchemeLevel.equals(schemeLevel)) {
currSchemeLevel = schemeLevel;
if (!schemeLevel.equals(SchemeListItem.SchemeLevel.IDE_Only)) {
myComboBox.addItem(mySchemesPanel.createSeparator(currSchemeLevel.toString()));
}
if (filter.apply(scheme)) {
myComboBox.addItem(new MySchemeListItem<>(scheme));
}
myComboBox.addItem(item);
}
}
private class MyListCellRenderer extends ColoredListCellRenderer<SchemeListItem<T>> {
private ListCellRendererWrapper<SchemeListItem> myWrapper = new ListCellRendererWrapper<SchemeListItem>() {
private class MyListCellRenderer extends ColoredListCellRenderer<MySchemeListItem<T>> {
private ListCellRendererWrapper<MySchemeListItem> myWrapper = new ListCellRendererWrapper<MySchemeListItem>() {
@Override
public void customize(JList list,
SchemeListItem value,
MySchemeListItem value,
int index,
boolean selected,
boolean hasFocus) {
@@ -153,8 +178,8 @@ public class SchemesCombo<T extends Scheme> {
};
@Override
public Component getListCellRendererComponent(JList<? extends SchemeListItem<T>> list,
SchemeListItem<T> value,
public Component getListCellRendererComponent(JList<? extends MySchemeListItem<T>> list,
MySchemeListItem<T> value,
int index,
boolean selected,
boolean hasFocus) {
@@ -169,29 +194,32 @@ public class SchemesCombo<T extends Scheme> {
}
@Override
protected void customizeCellRenderer(@NotNull JList<? extends SchemeListItem<T>> list,
SchemeListItem<T> value,
protected void customizeCellRenderer(@NotNull JList<? extends MySchemeListItem<T>> list,
MySchemeListItem<T> value,
int index,
boolean selected,
boolean hasFocus) {
if (value.getScheme() != null) {
T scheme = value.getScheme();
if (scheme != null) {
append(value.getPresentableText(), getSchemeAttributes(value));
SchemeListItem.SchemeLevel schemeLevel = value.getSchemeLevel();
if (index == -1 && !SchemeListItem.SchemeLevel.IDE_Only.equals(schemeLevel)) {
append(" " + schemeLevel.toString(), SimpleTextAttributes.GRAY_ATTRIBUTES);
if (mySchemesPanel.getModel().supportsProjectSchemes()) {
if (index == -1) {
append(" " + (mySchemesPanel.getModel().isProjectScheme(scheme) ? PROJECT_LEVEL : IDE_LEVEL),
SimpleTextAttributes.GRAY_ATTRIBUTES);
}
}
}
}
}
@Nullable
public T getSelectedScheme() {
SchemeListItem<T> item = getSelectedItem();
MySchemeListItem<T> item = getSelectedItem();
return item != null ? item.getScheme() : null;
}
@Nullable
public SchemeListItem<T> getSelectedItem() {
public MySchemeListItem<T> getSelectedItem() {
int i = myComboBox.getSelectedIndex();
return i >= 0 ? myComboBox.getItemAt(i) : null;
}
@@ -209,4 +237,64 @@ public class SchemesCombo<T extends Scheme> {
return myRootPanel;
}
private class MySeparatorItem extends MySchemeListItem<T> {
private String myTitle;
public MySeparatorItem(@NotNull String title) {
super(null);
myTitle = title;
}
@Override
public boolean isSeparator() {
return true;
}
@NotNull
@Override
public String getPresentableText() {
return myTitle;
}
}
private static class MySchemeListItem<T extends Scheme> {
private @Nullable T myScheme;
public MySchemeListItem(@Nullable T scheme) {
myScheme = scheme;
}
@Nullable
public String getSchemeName() {
return myScheme != null ? myScheme.getName() : null;
}
@Nullable
public T getScheme() {
return myScheme;
}
@NotNull
public String getPresentableText() {
return myScheme != null ? SchemeManager.getDisplayName(myScheme) : "";
}
public boolean isSeparator() {
return false;
}
}
@Nullable
public String validateSchemeName(@NotNull String name) {
if (name.isEmpty()) {
return EMPTY_NAME_MESSAGE;
}
else if (mySchemesPanel.getModel().nameExists(name)) {
return NAME_ALREADY_EXISTS_MESSAGE;
}
return null;
}
}
@@ -18,9 +18,18 @@ package com.intellij.application.options.schemes;
import com.intellij.openapi.options.Scheme;
import org.jetbrains.annotations.NotNull;
public interface SchemeListItemFactory<T extends Scheme> {
public interface SchemesModel<T extends Scheme> {
boolean supportsProjectSchemes();
SchemeListItem<T> createItem(@NotNull T scheme);
SchemeListItem<T> createSeparator(@NotNull String title);
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);
}
@@ -15,6 +15,7 @@
*/
package com.intellij.psi.impl.source.codeStyle;
import com.intellij.application.options.schemes.SchemeNameGenerator;
import com.intellij.configurationStore.LazySchemeProcessor;
import com.intellij.configurationStore.SchemeDataHolder;
import com.intellij.openapi.options.SchemeManager;
@@ -63,28 +64,10 @@ public abstract class CodeStyleSchemesImpl extends CodeStyleSchemes {
@SuppressWarnings("ForLoopThatDoesntUseLoopVariable")
@Override
public CodeStyleScheme createNewScheme(String preferredName, CodeStyleScheme parentScheme) {
String name;
if (preferredName == null) {
if (parentScheme == null) throw new IllegalArgumentException("parentScheme must not be null");
// Generate using parent name
name = null;
for (int i = 1; name == null; i++) {
String currName = parentScheme.getName() + " (" + i + ")";
if (mySchemeManager.findSchemeByName(currName) == null) {
name = currName;
}
}
}
else {
name = null;
for (int i = 0; name == null; i++) {
String currName = i == 0 ? preferredName : preferredName + " (" + i + ")";
if (mySchemeManager.findSchemeByName(currName) == null) {
name = currName;
}
}
}
return new CodeStyleSchemeImpl(name, false, parentScheme);
return new CodeStyleSchemeImpl(
SchemeNameGenerator.getUniqueName(preferredName, parentScheme, name -> mySchemeManager.findSchemeByName(name) != null),
false,
parentScheme);
}
@Override