From 24fb55550f6c038617d180d87bb6a02a02225338 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Mon, 13 Feb 2017 13:00:32 +0300 Subject: [PATCH 01/12] schemes ui: allow to choose the same name for schemes with different level --- .../options/codeStyle/CodeStyleSchemesActions.java | 3 ++- .../options/codeStyle/CodeStyleSchemesModel.java | 11 ++++++----- .../options/colors/ColorAndFontOptions.java | 3 ++- .../options/colors/ColorSchemeActions.java | 2 +- .../options/schemes/AbstractSchemeActions.java | 3 ++- .../application/options/schemes/SchemesCombo.java | 10 ++++++---- .../application/options/schemes/SchemesModel.java | 4 +++- 7 files changed, 22 insertions(+), 14 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 2dfc69b36a8d..7fb3e5eff73b 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 @@ -75,8 +75,9 @@ abstract class CodeStyleSchemesActions extends AbstractSchemeActions getModel().containsScheme(schemeName)); + SchemeNameGenerator.getUniqueName(getProjectName(), schemeName -> getModel().containsScheme(schemeName, isProjectScheme)); CodeStyleScheme newScheme = getModel().exportProjectScheme(name); getModel().setUsePerProjectSettings(false); getModel().selectScheme(newScheme, null); diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/CodeStyleSchemesModel.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/CodeStyleSchemesModel.java index 3ddd62c6c0d6..76c57b1da42f 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/CodeStyleSchemesModel.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/CodeStyleSchemesModel.java @@ -210,15 +210,16 @@ public class CodeStyleSchemesModel implements SchemesModel { } public CodeStyleScheme createNewScheme(final String preferredName, final CodeStyleScheme parentScheme) { - return new CodeStyleSchemeImpl(SchemeNameGenerator.getUniqueName(preferredName, parentScheme, name -> containsScheme(name)), + final boolean isProjectScheme = isProjectScheme(parentScheme); + return new CodeStyleSchemeImpl(SchemeNameGenerator.getUniqueName(preferredName, parentScheme, name -> containsScheme(name, isProjectScheme)), false, parentScheme); } @Nullable - private CodeStyleScheme findSchemeByName(final String name) { + private CodeStyleScheme findSchemeByName(final String name, boolean isProjectScheme) { for (CodeStyleScheme scheme : mySchemes) { - if (name.equals(scheme.getName())) return scheme; + if (isProjectScheme == isProjectScheme(scheme) && name.equals(scheme.getName())) return scheme; } return null; } @@ -253,8 +254,8 @@ public class CodeStyleSchemesModel implements SchemesModel { } @Override - public boolean containsScheme(@NotNull String name) { - return findSchemeByName(name) != null; + public boolean containsScheme(@NotNull String name, boolean isProjectScheme) { + return findSchemeByName(name, isProjectScheme) != null; } @Override 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 b3835630df55..02aed394b6cf 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 @@ -184,7 +184,8 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract } @Override - public boolean containsScheme(@NotNull String name) { + public boolean containsScheme(@NotNull String name, boolean projectScheme) { + assert !projectScheme; 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 eca6ae152512..f80933a0d378 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() - .containsScheme(candidate)); + .containsScheme(candidate, false)); 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 47e99eb6f718..83d41e82f8cb 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 @@ -195,10 +195,11 @@ public abstract class AbstractSchemeActions { T currentScheme = getCurrentScheme(); if (currentScheme != null) { mySchemesPanel.cancelEdit(); + final boolean isProjectScheme = mySchemesPanel.supportsProjectSchemes() && getModel().isProjectScheme(currentScheme); duplicateScheme(currentScheme, SchemeNameGenerator.getUniqueName( SchemeManager.getDisplayName(currentScheme), - name -> mySchemesPanel.getModel().containsScheme(name))); + name -> mySchemesPanel.getModel().containsScheme(name, isProjectScheme))); currentScheme = getCurrentScheme(); if (currentScheme != null) { mySchemesPanel.startEdit(); 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 99d69f735d2f..015108999b6d 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 @@ -20,6 +20,7 @@ import com.intellij.openapi.options.SchemeManager; import com.intellij.openapi.ui.ComboBox; import com.intellij.openapi.ui.MessageType; import com.intellij.ui.*; +import com.intellij.util.ObjectUtils; import com.intellij.util.ui.JBUI; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -99,7 +100,7 @@ public class SchemesCombo { String currName = myNameEditorField.getText(); MySchemeListItem selectedItem = getSelectedItem(); if (selectedItem != null && !currName.equals(selectedItem.getSchemeName())) { - String validationMessage = validateSchemeName(currName); + String validationMessage = validateSchemeName(currName, mySchemesPanel.getModel().isProjectScheme(ObjectUtils.notNull(selectedItem.getScheme()))); if (validationMessage != null) { mySchemesPanel.showInfo(validationMessage, MessageType.ERROR); return; @@ -131,7 +132,8 @@ public class SchemesCombo { cancelEdit(); return; } - String validationMessage = validateSchemeName(newName); + boolean isProjectScheme = mySchemesPanel.getModel().isProjectScheme(ObjectUtils.notNull(selectedItem.getScheme())); + String validationMessage = validateSchemeName(newName, isProjectScheme); if (validationMessage != null) { mySchemesPanel.showInfo(validationMessage, MessageType.ERROR); } @@ -331,11 +333,11 @@ public class SchemesCombo { } @Nullable - public String validateSchemeName(@NotNull String name) { + private String validateSchemeName(@NotNull String name, boolean isProjectScheme) { if (name.isEmpty()) { return EMPTY_NAME_MESSAGE; } - else if (mySchemesPanel.getModel().containsScheme(name)) { + else if (mySchemesPanel.getModel().containsScheme(name, isProjectScheme)) { 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 d4044c8de8ed..327948bb0603 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 @@ -61,9 +61,11 @@ public interface SchemesModel { /** * @param name The scheme to check. + * @param projectScheme Level of the scheme to check. If schemes model does not support project level schemes + * then the parameter is always equal to false. * @return True if a scheme by the given name already exists. */ - boolean containsScheme(@NotNull String name); + boolean containsScheme(@NotNull String name, boolean projectScheme); /** * @param scheme The scheme to check. From 9674c7a4217465e2eb7d23fd0c45f4deb81cbdf7 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Mon, 13 Feb 2017 13:23:29 +0300 Subject: [PATCH 02/12] scheme ui: move supportsProjectSchemes method to SchemesModel --- .../options/codeStyle/CodeStyleSchemesModel.java | 5 +++++ .../options/codeStyle/CodeStyleSchemesPanel.java | 5 ----- .../application/options/colors/ColorAndFontOptions.java | 5 +++++ .../intellij/application/options/colors/SchemesPanel.java | 5 ----- .../application/options/schemes/AbstractSchemeActions.java | 4 ++-- .../application/options/schemes/AbstractSchemesPanel.java | 7 ------- .../intellij/application/options/schemes/SchemesCombo.java | 4 ++-- .../intellij/application/options/schemes/SchemesModel.java | 7 +++++++ 8 files changed, 21 insertions(+), 21 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/CodeStyleSchemesModel.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/CodeStyleSchemesModel.java index 76c57b1da42f..dce210ef46bb 100644 --- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/CodeStyleSchemesModel.java +++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/CodeStyleSchemesModel.java @@ -76,6 +76,11 @@ public class CodeStyleSchemesModel implements SchemesModel { } } + @Override + public boolean supportsProjectSchemes() { + return true; + } + public CodeStyleSettings getCloneSettings(final CodeStyleScheme scheme) { if (!mySettingsToClone.containsKey(scheme)) { mySettingsToClone.put(scheme, scheme.getCodeStyleSettings().clone()); 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 8d8ca75a7bd2..8bf9e152c0c2 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 @@ -122,9 +122,4 @@ public class CodeStyleSchemesPanel extends AbstractSchemesPanel public SchemesModel getModel() { return myModel; } - - @Override - public boolean supportsProjectSchemes() { - return true; - } } 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 02aed394b6cf..44a3af4acc1f 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 @@ -276,6 +276,11 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract mySomeSchemesDeleted = mySomeSchemesDeleted || !deletedNewlyCreated; } + @Override + public boolean supportsProjectSchemes() { + return false; + } + private void selectDefaultScheme() { DefaultColorsScheme defaultScheme = 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 5aed56ea3df9..55831d32410c 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 @@ -108,9 +108,4 @@ public class SchemesPanel extends AbstractSchemesPanel imple public SchemesModel getModel() { return myOptions; } - - @Override - public boolean supportsProjectSchemes() { - return false; - } } 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 83d41e82f8cb..e14edcd7e2f4 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 @@ -75,7 +75,7 @@ public abstract class AbstractSchemeActions { public final Collection getActions() { List actions = new ArrayList<>(); - if (mySchemesPanel.supportsProjectSchemes()) { + if (mySchemesPanel.getModel().supportsProjectSchemes()) { actions.add(new CopyToProjectAction()); actions.add(new CopyToIDEAction()); actions.add(new Separator()); @@ -195,7 +195,7 @@ public abstract class AbstractSchemeActions { T currentScheme = getCurrentScheme(); if (currentScheme != null) { mySchemesPanel.cancelEdit(); - final boolean isProjectScheme = mySchemesPanel.supportsProjectSchemes() && getModel().isProjectScheme(currentScheme); + final boolean isProjectScheme = mySchemesPanel.getModel().supportsProjectSchemes() && getModel().isProjectScheme(currentScheme); duplicateScheme(currentScheme, SchemeNameGenerator.getUniqueName( SchemeManager.getDisplayName(currentScheme), 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 b37d690c9d0d..511ebeb61d6e 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 @@ -166,13 +166,6 @@ public abstract class AbstractSchemesPanel extends JPanel { mySchemesCombo.updateSelected(); } - /** - * @return True if the panel supports project-level schemes along with IDE ones. In this case there will be - * additional "Copy to Project" and "Copy to IDE" actions for IDE and project schemes respectively and Project/IDE schemes - * separators. - */ - public abstract boolean supportsProjectSchemes(); - public void showStatus(final String message, MessageType messageType) { BalloonBuilder balloonBuilder = JBPopupFactory.getInstance() .createHtmlTextBalloonBuilder(message, messageType.getDefaultIcon(), 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 015108999b6d..3fd9a3e38f41 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 @@ -188,7 +188,7 @@ public class SchemesCombo { public void resetSchemes(@NotNull Collection schemes) { myComboBoxModel.removeAllElements(); SchemesModel model = mySchemesPanel.getModel(); - if (mySchemesPanel.supportsProjectSchemes()) { + if (mySchemesPanel.getModel().supportsProjectSchemes()) { myComboBoxModel.addElement(new MySeparatorItem(PROJECT_LEVEL)); addItems(schemes, scheme -> model.isProjectScheme(scheme)); myComboBoxModel.addElement(new MySeparatorItem(IDE_LEVEL)); @@ -247,7 +247,7 @@ public class SchemesCombo { T scheme = value.getScheme(); if (scheme != null) { append(value.getPresentableText(), getSchemeAttributes(value)); - if (mySchemesPanel.supportsProjectSchemes()) { + if (mySchemesPanel.getModel().supportsProjectSchemes()) { if (index == -1) { append(" " + (mySchemesPanel.getModel().isProjectScheme(scheme) ? PROJECT_LEVEL : IDE_LEVEL), SimpleTextAttributes.GRAY_ATTRIBUTES); 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 327948bb0603..db7e479d7714 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 @@ -75,4 +75,11 @@ public interface SchemesModel { boolean differsFromDefault(@NotNull T scheme); void removeScheme(@NotNull T scheme); + + /** + * @return True if the panel supports project-level schemes along with IDE ones. In this case there will be + * additional "Copy to Project" and "Copy to IDE" actions for IDE and project schemes respectively and Project/IDE schemes + * separators. + */ + boolean supportsProjectSchemes(); } From 0b80b4f44fdfc67051cd21a5a651b3b51f876268 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Mon, 13 Feb 2017 15:19:46 +0300 Subject: [PATCH 03/12] scheme ui: make panel's text customizable --- .../application/options/schemes/AbstractSchemesPanel.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) 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 511ebeb61d6e..0847d8136361 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 @@ -57,7 +57,7 @@ public abstract class AbstractSchemesPanel extends JPanel { private void createUIComponents() { JPanel controlsPanel = new JPanel(); controlsPanel.setLayout(new BoxLayout(controlsPanel, BoxLayout.LINE_AXIS)); - controlsPanel.add(new JLabel(ApplicationBundle.message("editbox.scheme.name"))); + controlsPanel.add(new JLabel(getTitle())); controlsPanel.add(Box.createRigidArea(new Dimension(10, 0))); myActions = createSchemeActions(); mySchemesCombo = new SchemesCombo<>(this); @@ -74,7 +74,7 @@ public abstract class AbstractSchemesPanel extends JPanel { add(Box.createVerticalGlue()); add(Box.createRigidArea(new Dimension(0, 10))); } - + private JComponent createToolbar() { DefaultActionGroup toolbarActionGroup = new DefaultActionGroup(); toolbarActionGroup.add(new TopActionGroup()); @@ -152,6 +152,10 @@ public abstract class AbstractSchemesPanel extends JPanel { return myActions; } + protected String getTitle() { + return ApplicationBundle.message("editbox.scheme.name"); + } + /** * @return Schemes model implementation. * @see SchemesModel From 89a139faed7d51ad22d6de0b7b3a8a43a43db1f2 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Mon, 13 Feb 2017 15:17:16 +0300 Subject: [PATCH 04/12] scheme ui: split SchemesCombo into 2 parts: "read-only" combobox and others --- .../options/schemes/AbstractSchemesPanel.java | 4 +- .../options/schemes/EditableSchemesCombo.java | 217 ++++++++++++ .../options/schemes/SchemesCombo.java | 322 +++++------------- 3 files changed, 301 insertions(+), 242 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/application/options/schemes/EditableSchemesCombo.java 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 0847d8136361..b46a604782f9 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 @@ -44,7 +44,7 @@ import java.util.Collection; */ public abstract class AbstractSchemesPanel extends JPanel { - private SchemesCombo mySchemesCombo; + private EditableSchemesCombo mySchemesCombo; private AbstractSchemeActions myActions; private JComponent myToolbar; private JLabel myInfoLabel; @@ -60,7 +60,7 @@ public abstract class AbstractSchemesPanel extends JPanel { controlsPanel.add(new JLabel(getTitle())); controlsPanel.add(Box.createRigidArea(new Dimension(10, 0))); myActions = createSchemeActions(); - mySchemesCombo = new SchemesCombo<>(this); + mySchemesCombo = new EditableSchemesCombo<>(this); controlsPanel.add(mySchemesCombo.getComponent()); myToolbar = createToolbar(); controlsPanel.add(myToolbar); diff --git a/platform/lang-impl/src/com/intellij/application/options/schemes/EditableSchemesCombo.java b/platform/lang-impl/src/com/intellij/application/options/schemes/EditableSchemesCombo.java new file mode 100644 index 000000000000..2429bd1a2b8e --- /dev/null +++ b/platform/lang-impl/src/com/intellij/application/options/schemes/EditableSchemesCombo.java @@ -0,0 +1,217 @@ +/* + * Copyright 2000-2016 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.ui.MessageType; +import com.intellij.ui.DocumentAdapter; +import com.intellij.ui.JBColor; +import com.intellij.ui.SimpleTextAttributes; +import com.intellij.util.ObjectUtils; +import com.intellij.util.ui.JBUI; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import java.awt.*; +import java.awt.event.*; +import java.util.Collection; + +public class EditableSchemesCombo { + + // region Message constants + public static final String EMPTY_NAME_MESSAGE = "The name must not be empty"; + public static final String NAME_ALREADY_EXISTS_MESSAGE = "Name is already in use. Please change to unique name."; + private static final String EDITING_HINT = "Enter to save, Esc to cancel."; + public static final int COMBO_WIDTH = 200; + // endregion + + private SchemesCombo myComboBox; + private JPanel myRootPanel; + private AbstractSchemesPanel mySchemesPanel; + private final CardLayout myLayout; + private final JTextField myNameEditorField; + + private final static KeyStroke ESC_KEY_STROKE = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false); + private final static KeyStroke ENTER_KEY_STROKE = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false); + + public EditableSchemesCombo(@NotNull AbstractSchemesPanel schemesPanel) { + mySchemesPanel = schemesPanel; + myLayout = new CardLayout(); + myRootPanel = new JPanel(myLayout); + createCombo(); + myRootPanel.add(myComboBox); + myNameEditorField = createNameEditorField(); + myRootPanel.add(myNameEditorField); + myRootPanel.setPreferredSize(new Dimension(JBUI.scale(COMBO_WIDTH), myNameEditorField.getPreferredSize().height)); + myRootPanel.setMaximumSize(new Dimension(JBUI.scale(COMBO_WIDTH), Short.MAX_VALUE)); + } + + private JTextField createNameEditorField() { + JTextField nameEditorField = new JTextField(); + nameEditorField.registerKeyboardAction(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + revertSchemeName(); + cancelEdit(); + } + }, ESC_KEY_STROKE, JComponent.WHEN_FOCUSED); + nameEditorField.registerKeyboardAction(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + stopEdit(); + } + }, ENTER_KEY_STROKE, JComponent.WHEN_FOCUSED); + nameEditorField.addFocusListener(new FocusAdapter() { + @Override + public void focusLost(FocusEvent e) { + stopEdit(); + } + }); + nameEditorField.getDocument().addDocumentListener(new DocumentAdapter() { + @Override + protected void textChanged(DocumentEvent e) { + validateOnTyping(); + } + }); + return nameEditorField; + } + + private void validateOnTyping() { + String currName = myNameEditorField.getText(); + SchemesCombo.MySchemeListItem selectedItem = myComboBox.getSelectedItem(); + if (selectedItem != null && !currName.equals(selectedItem.getSchemeName())) { + String validationMessage = validateSchemeName(currName, mySchemesPanel.getModel().isProjectScheme(ObjectUtils.notNull(selectedItem.getScheme()))); + if (validationMessage != null) { + mySchemesPanel.showInfo(validationMessage, MessageType.ERROR); + return; + } + } + showHint(); + } + + private void showHint() { + mySchemesPanel.showInfo(EDITING_HINT, MessageType.INFO); + } + + private void revertSchemeName() { + SchemesCombo.MySchemeListItem selectedItem = myComboBox.getSelectedItem(); + if (selectedItem != null) { + myNameEditorField.setText(selectedItem.getSchemeName()); + } + } + + public void updateSelected() { + myComboBox.repaint(); + } + + private void stopEdit() { + String newName = myNameEditorField.getText(); + SchemesCombo.MySchemeListItem selectedItem = myComboBox.getSelectedItem(); + if (selectedItem != null) { + if (newName.equals(selectedItem.getSchemeName())) { + cancelEdit(); + return; + } + boolean isProjectScheme = mySchemesPanel.getModel().isProjectScheme(ObjectUtils.notNull(selectedItem.getScheme())); + String validationMessage = validateSchemeName(newName, isProjectScheme); + if (validationMessage != null) { + mySchemesPanel.showInfo(validationMessage, MessageType.ERROR); + } + else { + cancelEdit(); + if (selectedItem.getScheme() != null) { + mySchemesPanel.getActions().renameScheme(selectedItem.getScheme(), newName); + } + } + } + } + + public void cancelEdit() { + mySchemesPanel.clearInfo(); + myLayout.first(myRootPanel); + myRootPanel.requestFocus(); + } + + private void createCombo() { + myComboBox = new SchemesCombo() { + @Override + protected boolean supportsProjectSchemes() { + return mySchemesPanel.getModel().supportsProjectSchemes(); + } + + @NotNull + @Override + protected SimpleTextAttributes getSchemeAttributes(T scheme) { + SchemesModel model = mySchemesPanel.getModel(); + SimpleTextAttributes baseAttributes = model.canDeleteScheme(scheme) + ? SimpleTextAttributes.REGULAR_ATTRIBUTES + : SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES; + if (model.canResetScheme(scheme) && model.differsFromDefault(scheme)) { + return baseAttributes.derive(-1, JBColor.BLUE, null, null); + } + return baseAttributes; + } + }; + myComboBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + mySchemesPanel.getActions().onSchemeChanged(getSelectedScheme()); + } + }); + } + + public void startEdit() { + T scheme = getSelectedScheme(); + if (scheme != null) { + showHint(); + myNameEditorField.setText(scheme.getName()); + myLayout.last(myRootPanel); + myNameEditorField.requestFocus(); + } + } + + public void resetSchemes(@NotNull Collection schemes) { + myComboBox.resetSchemes(schemes); + } + + @Nullable + public T getSelectedScheme() { + return myComboBox.getSelectedScheme(); + } + + public void selectScheme(@Nullable T scheme) { + myComboBox.selectScheme(scheme); + } + + public JComponent getComponent() { + return myRootPanel; + } + + @Nullable + private String validateSchemeName(@NotNull String name, boolean isProjectScheme) { + if (name.isEmpty()) { + return EMPTY_NAME_MESSAGE; + } + else if (mySchemesPanel.getModel().containsScheme(name, isProjectScheme)) { + return NAME_ALREADY_EXISTS_MESSAGE; + } + return null; + } + + +} 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 3fd9a3e38f41..2d66053c9ce1 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 @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * 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. @@ -18,195 +18,103 @@ 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.*; -import com.intellij.util.ObjectUtils; -import com.intellij.util.ui.JBUI; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import javax.swing.event.DocumentEvent; import java.awt.*; -import java.awt.event.*; import java.util.Collection; import java.util.function.Predicate; -public class SchemesCombo { - - // region Message constants +public abstract class SchemesCombo extends ComboBox> { 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 = "Name is already in use. Please change to unique name."; - private static final String EDITING_HINT = "Enter to save, Esc to cancel."; - public static final int COMBO_WIDTH = 200; - // endregion - - private ComboBox> myComboBox; - private JPanel myRootPanel; - private AbstractSchemesPanel mySchemesPanel; - private final CardLayout myLayout; - private final JTextField myNameEditorField; - private final MyComboBoxModel myComboBoxModel; - - private final static KeyStroke ESC_KEY_STROKE = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false); - private final static KeyStroke ENTER_KEY_STROKE = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false); - public SchemesCombo(@NotNull AbstractSchemesPanel schemesPanel) { - mySchemesPanel = schemesPanel; - myLayout = new CardLayout(); - myRootPanel = new JPanel(myLayout); - myComboBoxModel = new MyComboBoxModel(); - createCombo(); - myRootPanel.add(myComboBox); - myNameEditorField = createNameEditorField(); - myRootPanel.add(myNameEditorField); - myRootPanel.setPreferredSize(new Dimension(JBUI.scale(COMBO_WIDTH), myNameEditorField.getPreferredSize().height)); - myRootPanel.setMaximumSize(new Dimension(JBUI.scale(COMBO_WIDTH), Short.MAX_VALUE)); - } - - private JTextField createNameEditorField() { - JTextField nameEditorField = new JTextField(); - nameEditorField.registerKeyboardAction(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - revertSchemeName(); - cancelEdit(); - } - }, ESC_KEY_STROKE, JComponent.WHEN_FOCUSED); - nameEditorField.registerKeyboardAction(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - stopEdit(); - } - }, ENTER_KEY_STROKE, JComponent.WHEN_FOCUSED); - nameEditorField.addFocusListener(new FocusAdapter() { - @Override - public void focusLost(FocusEvent e) { - stopEdit(); - } - }); - nameEditorField.getDocument().addDocumentListener(new DocumentAdapter() { - @Override - protected void textChanged(DocumentEvent e) { - validateOnTyping(); - } - }); - return nameEditorField; - } - - private void validateOnTyping() { - String currName = myNameEditorField.getText(); - MySchemeListItem selectedItem = getSelectedItem(); - if (selectedItem != null && !currName.equals(selectedItem.getSchemeName())) { - String validationMessage = validateSchemeName(currName, mySchemesPanel.getModel().isProjectScheme(ObjectUtils.notNull(selectedItem.getScheme()))); - if (validationMessage != null) { - mySchemesPanel.showInfo(validationMessage, MessageType.ERROR); - return; - } - } - showHint(); - } - - private void showHint() { - mySchemesPanel.showInfo(EDITING_HINT, MessageType.INFO); - } - - private void revertSchemeName() { - MySchemeListItem selectedItem = getSelectedItem(); - if (selectedItem != null) { - myNameEditorField.setText(selectedItem.getSchemeName()); - } - } - - public void updateSelected() { - myComboBox.repaint(); - } - - private void stopEdit() { - String newName = myNameEditorField.getText(); - MySchemeListItem selectedItem = getSelectedItem(); - if (selectedItem != null) { - if (newName.equals(selectedItem.getSchemeName())) { - cancelEdit(); - return; - } - boolean isProjectScheme = mySchemesPanel.getModel().isProjectScheme(ObjectUtils.notNull(selectedItem.getScheme())); - String validationMessage = validateSchemeName(newName, isProjectScheme); - if (validationMessage != null) { - mySchemesPanel.showInfo(validationMessage, MessageType.ERROR); - } - else { - cancelEdit(); - if (selectedItem.getScheme() != null) { - mySchemesPanel.getActions().renameScheme(selectedItem.getScheme(), newName); - } - } - } - } - - public void cancelEdit() { - mySchemesPanel.clearInfo(); - myLayout.first(myRootPanel); - myRootPanel.requestFocus(); - } - - private void createCombo() { - myComboBox = new ComboBox<>(myComboBoxModel); - myComboBox.setRenderer(new MyListCellRenderer()); - myComboBox.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - mySchemesPanel.getActions().onSchemeChanged(getSelectedScheme()); - } - }); - } - - public void startEdit() { - T scheme = getSelectedScheme(); - if (scheme != null) { - showHint(); - myNameEditorField.setText(scheme.getName()); - myLayout.last(myRootPanel); - myNameEditorField.requestFocus(); - } - } - - private SimpleTextAttributes getSchemeAttributes(@NotNull MySchemeListItem item) { - SchemesModel model = mySchemesPanel.getModel(); - T scheme = item.getScheme(); - SimpleTextAttributes baseAttributes = scheme !=null && model.canDeleteScheme(scheme) - ? SimpleTextAttributes.REGULAR_ATTRIBUTES - : SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES; - if (scheme != null && model.canResetScheme(scheme) && model.differsFromDefault(scheme)) { - return baseAttributes.derive(-1, JBColor.BLUE, null, null); - } - return baseAttributes; + public SchemesCombo() { + super(new MyComboBoxModel<>()); + setRenderer(new MyListCellRenderer()); } public void resetSchemes(@NotNull Collection schemes) { - myComboBoxModel.removeAllElements(); - SchemesModel model = mySchemesPanel.getModel(); - if (mySchemesPanel.getModel().supportsProjectSchemes()) { - myComboBoxModel.addElement(new MySeparatorItem(PROJECT_LEVEL)); - addItems(schemes, scheme -> model.isProjectScheme(scheme)); - myComboBoxModel.addElement(new MySeparatorItem(IDE_LEVEL)); - addItems(schemes, scheme -> !model.isProjectScheme(scheme)); + final MyComboBoxModel model = (MyComboBoxModel)getModel(); + model.removeAllElements(); + if (supportsProjectSchemes()) { + model.addElement(new MySeparatorItem(PROJECT_LEVEL)); + addItems(schemes, scheme -> isProjectScheme(scheme)); + model.addElement(new MySeparatorItem(IDE_LEVEL)); + addItems(schemes, scheme -> !isProjectScheme(scheme)); } else { addItems(schemes, scheme -> true); } } - + + public void selectScheme(@Nullable T scheme) { + for (int i = 0; i < getItemCount(); i ++) { + if (getItemAt(i).getScheme() == scheme) { + setSelectedIndex(i); + break; + } + } + } + + @Nullable + public T getSelectedScheme() { + SchemesCombo.MySchemeListItem item = getSelectedItem(); + return item != null ? item.getScheme() : null; + } + + @Nullable + public SchemesCombo.MySchemeListItem getSelectedItem() { + int i = getSelectedIndex(); + return i >= 0 ? getItemAt(i) : null; + } + + protected abstract boolean supportsProjectSchemes(); + + protected boolean isProjectScheme(@NotNull T scheme) { + throw new UnsupportedOperationException(); + } + + @NotNull + protected abstract SimpleTextAttributes getSchemeAttributes(T scheme); + private void addItems(@NotNull Collection schemes, Predicate filter) { for (T scheme : schemes) { if (filter.test(scheme)) { - myComboBoxModel.addElement(new MySchemeListItem<>(scheme)); + ((MyComboBoxModel) getModel()).addElement(new MySchemeListItem<>(scheme)); } } } + static class MySchemeListItem { + 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; + } + } + private class MyListCellRenderer extends ColoredListCellRenderer> { private ListCellRendererWrapper myWrapper = new ListCellRendererWrapper() { @Override @@ -246,10 +154,10 @@ public class SchemesCombo { boolean hasFocus) { T scheme = value.getScheme(); if (scheme != null) { - append(value.getPresentableText(), getSchemeAttributes(value)); - if (mySchemesPanel.getModel().supportsProjectSchemes()) { + append(value.getPresentableText(), getSchemeAttributes(scheme)); + if (supportsProjectSchemes()) { if (index == -1) { - append(" " + (mySchemesPanel.getModel().isProjectScheme(scheme) ? PROJECT_LEVEL : IDE_LEVEL), + append(" " + (isProjectScheme(scheme) ? PROJECT_LEVEL : IDE_LEVEL), SimpleTextAttributes.GRAY_ATTRIBUTES); } } @@ -257,33 +165,18 @@ public class SchemesCombo { } } - @Nullable - public T getSelectedScheme() { - MySchemeListItem item = getSelectedItem(); - return item != null ? item.getScheme() : null; - } - - @Nullable - public MySchemeListItem getSelectedItem() { - int i = myComboBox.getSelectedIndex(); - return i >= 0 ? myComboBox.getItemAt(i) : null; - } - - public void selectScheme(@Nullable T scheme) { - for (int i = 0; i < myComboBox.getItemCount(); i ++) { - if (myComboBox.getItemAt(i).getScheme() == scheme) { - myComboBox.setSelectedIndex(i); - break; + private static class MyComboBoxModel extends DefaultComboBoxModel> { + @Override + public void setSelectedItem(Object anObject) { + if (anObject instanceof SchemesCombo.MySchemeListItem && ((MySchemeListItem)anObject).isSeparator()) { + return; } + super.setSelectedItem(anObject); } } - - public JComponent getComponent() { - return myRootPanel; - } - + private class MySeparatorItem extends MySchemeListItem { - + private String myTitle; public MySeparatorItem(@NotNull String title) { @@ -302,55 +195,4 @@ public class SchemesCombo { return myTitle; } } - - private static class MySchemeListItem { - - 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 - private String validateSchemeName(@NotNull String name, boolean isProjectScheme) { - if (name.isEmpty()) { - return EMPTY_NAME_MESSAGE; - } - else if (mySchemesPanel.getModel().containsScheme(name, isProjectScheme)) { - return NAME_ALREADY_EXISTS_MESSAGE; - } - return null; - } - - private class MyComboBoxModel extends DefaultComboBoxModel> { - - @Override - public void setSelectedItem(Object anObject) { - if (anObject instanceof MySchemeListItem && ((MySchemeListItem)anObject).isSeparator()) { - return; - } - super.setSelectedItem(anObject); - } - } } From e3bf4a2f9efaea489bc311efb0d65754309b5c96 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Mon, 13 Feb 2017 16:54:23 +0300 Subject: [PATCH 05/12] scheme ui: move combobox from analyze code dialog to SchemeCombo --- .../actions/CodeCleanupAction.java | 10 +-- .../actions/CodeInspectionAction.java | 83 ++++++++++--------- 2 files changed, 48 insertions(+), 45 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInspection/actions/CodeCleanupAction.java b/platform/lang-impl/src/com/intellij/codeInspection/actions/CodeCleanupAction.java index 55777007edb5..9523e05df563 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/actions/CodeCleanupAction.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/actions/CodeCleanupAction.java @@ -16,16 +16,15 @@ package com.intellij.codeInspection.actions; import com.intellij.analysis.AnalysisScope; +import com.intellij.application.options.schemes.SchemesCombo; import com.intellij.codeInspection.InspectionManager; import com.intellij.codeInspection.InspectionProfile; import com.intellij.codeInspection.ex.GlobalInspectionContextBase; +import com.intellij.codeInspection.ex.InspectionProfileImpl; import com.intellij.codeInspection.ex.InspectionToolWrapper; import com.intellij.openapi.project.Project; -import com.intellij.profile.codeInspection.InspectionProfileManager; import com.intellij.profile.codeInspection.InspectionProjectProfileManager; import com.intellij.profile.codeInspection.ProjectInspectionProfileManager; -import com.intellij.profile.codeInspection.ui.header.InspectionToolsConfigurable; -import com.intellij.profile.codeInspection.ui.header.ProfilesComboBox; public class CodeCleanupAction extends CodeInspectionAction { @@ -50,9 +49,8 @@ public class CodeCleanupAction extends CodeInspectionAction { } @Override - protected InspectionToolsConfigurable createConfigurable(ProjectInspectionProfileManager projectProfileManager, - InspectionProfileManager profileManager, - ProfilesComboBox profilesCombo) { + protected ExternalProfilesComboboxAwareInspectionToolsConfigurable createConfigurable(ProjectInspectionProfileManager projectProfileManager, + SchemesCombo profilesCombo) { return new ExternalProfilesComboboxAwareInspectionToolsConfigurable(projectProfileManager, profilesCombo) { @Override protected boolean acceptTool(InspectionToolWrapper entry) { diff --git a/platform/lang-impl/src/com/intellij/codeInspection/actions/CodeInspectionAction.java b/platform/lang-impl/src/com/intellij/codeInspection/actions/CodeInspectionAction.java index 1e35c3195c03..891be158e796 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/actions/CodeInspectionAction.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/actions/CodeInspectionAction.java @@ -18,13 +18,13 @@ package com.intellij.codeInspection.actions; import com.intellij.analysis.AnalysisScope; import com.intellij.analysis.BaseAnalysisAction; import com.intellij.analysis.BaseAnalysisActionDialog; +import com.intellij.application.options.schemes.SchemesCombo; import com.intellij.codeInspection.InspectionManager; import com.intellij.codeInspection.InspectionProfile; import com.intellij.codeInspection.InspectionsBundle; import com.intellij.codeInspection.ex.GlobalInspectionContextImpl; import com.intellij.codeInspection.ex.InspectionManagerEx; import com.intellij.codeInspection.ex.InspectionProfileImpl; -import com.intellij.codeInspection.ex.InspectionProfileModifiableModel; import com.intellij.ide.util.PropertiesComponent; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileEditor.FileDocumentManager; @@ -35,8 +35,8 @@ import com.intellij.profile.codeInspection.InspectionProjectProfileManager; import com.intellij.profile.codeInspection.ProjectInspectionProfileManager; import com.intellij.profile.codeInspection.ui.ErrorsConfigurable; import com.intellij.profile.codeInspection.ui.header.InspectionToolsConfigurable; -import com.intellij.profile.codeInspection.ui.header.ProfilesComboBox; import com.intellij.ui.ComboboxWithBrowseButton; +import com.intellij.ui.SimpleTextAttributes; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -105,16 +105,21 @@ public class CodeInspectionAction extends BaseAnalysisAction { protected JComponent getAdditionalActionSettings(@NotNull final Project project, final BaseAnalysisActionDialog dialog) { final AdditionalPanel panel = new AdditionalPanel(); final InspectionManagerEx manager = (InspectionManagerEx)InspectionManager.getInstance(project); - final ProfilesComboBox profiles = (ProfilesComboBox)panel.myBrowseProfilesCombo.getComboBox(); + final SchemesCombo profiles = (SchemesCombo)panel.myBrowseProfilesCombo.getComboBox(); final InspectionProfileManager profileManager = InspectionProfileManager.getInstance(); final ProjectInspectionProfileManager projectProfileManager = ProjectInspectionProfileManager.getInstance(project); panel.myBrowseProfilesCombo.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - final InspectionToolsConfigurable errorConfigurable = createConfigurable(projectProfileManager, profileManager, profiles); + final ExternalProfilesComboboxAwareInspectionToolsConfigurable errorConfigurable = createConfigurable(projectProfileManager, profiles); final MySingleConfigurableEditor editor = new MySingleConfigurableEditor(project, errorConfigurable, manager); if (editor.showAndGet()) { - reloadProfiles(profiles, profileManager, projectProfileManager, manager); + reloadProfiles(profiles, profileManager, projectProfileManager, project); + if (errorConfigurable.mySelectedName != null) { + final InspectionProfileImpl profile = (errorConfigurable.mySelectedIsProjectProfile ? projectProfileManager : profileManager) + .getProfile(errorConfigurable.mySelectedName); + profiles.selectScheme(profile); + } } else { //if profile was disabled and cancel after apply was pressed @@ -127,7 +132,7 @@ public class CodeInspectionAction extends BaseAnalysisAction { profiles.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - myExternalProfile = (InspectionProfileImpl)profiles.getSelectedItem(); + myExternalProfile = profiles.getSelectedScheme(); final boolean canExecute = myExternalProfile != null && myExternalProfile.isExecutable(project); dialog.setOKActionEnabled(canExecute); if (canExecute) { @@ -136,58 +141,47 @@ public class CodeInspectionAction extends BaseAnalysisAction { } } }); - reloadProfiles(profiles, profileManager, projectProfileManager, manager); + reloadProfiles(profiles, profileManager, projectProfileManager, project); return panel.myAdditionalPanel; } - protected InspectionToolsConfigurable createConfigurable(ProjectInspectionProfileManager projectProfileManager, - InspectionProfileManager profileManager, - final ProfilesComboBox profilesCombo) { + protected ExternalProfilesComboboxAwareInspectionToolsConfigurable createConfigurable(ProjectInspectionProfileManager projectProfileManager, + SchemesCombo profilesCombo) { return new ExternalProfilesComboboxAwareInspectionToolsConfigurable(projectProfileManager, profilesCombo); } protected static class ExternalProfilesComboboxAwareInspectionToolsConfigurable extends InspectionToolsConfigurable { - private final ProfilesComboBox myProfilesCombo; + private final SchemesCombo myProfilesCombo; + private String mySelectedName; + private boolean mySelectedIsProjectProfile; - public ExternalProfilesComboboxAwareInspectionToolsConfigurable(@NotNull ProjectInspectionProfileManager projectProfileManager, ProfilesComboBox profilesCombo) { + public ExternalProfilesComboboxAwareInspectionToolsConfigurable(@NotNull ProjectInspectionProfileManager projectProfileManager, SchemesCombo profilesCombo) { super(projectProfileManager); myProfilesCombo = profilesCombo; } @Override protected InspectionProfileImpl getCurrentProfile() { - return (InspectionProfileImpl)myProfilesCombo.getSelectedItem(); - } - - @Override - protected void addProfile(InspectionProfileModifiableModel model) { - super.addProfile(model); - myProfilesCombo.addProfile(model.getSource()); + return myProfilesCombo.getSelectedScheme(); } @Override protected void applyRootProfile(@NotNull String name, boolean isProjectLevel) { - for (int i = 0; i < myProfilesCombo.getItemCount(); i++) { - final InspectionProfileImpl profile = myProfilesCombo.getItemAt(i); - if (name.equals(profile.getName())) { - myProfilesCombo.setSelectedIndex(i); - break; - } - } + mySelectedName = name; + mySelectedIsProjectProfile = isProjectLevel; } } - - private void reloadProfiles(ProfilesComboBox profilesCombo, - InspectionProfileManager inspectionProfileManager, - InspectionProjectProfileManager inspectionProjectProfileManager, - InspectionManagerEx inspectionManager) { - InspectionProfileImpl selectedProfile = getProfileToUse(inspectionManager.getProject(), inspectionProfileManager, inspectionProjectProfileManager); + private void reloadProfiles(SchemesCombo profilesCombo, + InspectionProfileManager appProfileManager, + InspectionProjectProfileManager projectProfileManager, + Project project) { List profiles = new ArrayList<>(); - profiles.addAll(inspectionProfileManager.getProfiles()); - profiles.addAll(inspectionProjectProfileManager.getProfiles()); - profilesCombo.reset(profiles); - profilesCombo.selectProfile(selectedProfile); + profiles.addAll(appProfileManager.getProfiles()); + profiles.addAll(projectProfileManager.getProfiles()); + profilesCombo.resetSchemes(profiles); + InspectionProfileImpl selectedProfile = getProfileToUse(project, appProfileManager, projectProfileManager); + profilesCombo.selectScheme(selectedProfile); } @NotNull @@ -215,10 +209,21 @@ public class CodeInspectionAction extends BaseAnalysisAction { public JPanel myAdditionalPanel; private void createUIComponents() { - myBrowseProfilesCombo = new ComboboxWithBrowseButton(new ProfilesComboBox() { + myBrowseProfilesCombo = new ComboboxWithBrowseButton(new SchemesCombo() { @Override - protected void onProfileChosen(InspectionProfileImpl inspectionProfile) { - //do nothing here + protected boolean supportsProjectSchemes() { + return true; + } + + @Override + protected boolean isProjectScheme(@NotNull InspectionProfileImpl profile) { + return profile.isProjectLevel(); + } + + @NotNull + @Override + protected SimpleTextAttributes getSchemeAttributes(InspectionProfileImpl profile) { + return SimpleTextAttributes.REGULAR_ATTRIBUTES; } }); } From 7b6a3cc99f2f61a857074e31596d94cddda5e655 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Mon, 13 Feb 2017 17:23:25 +0300 Subject: [PATCH 06/12] scheme ui: split SchemesCombo into 2 parts: "read-only" combobox and others --- .../application/options/schemes/EditableSchemesCombo.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/application/options/schemes/EditableSchemesCombo.java b/platform/lang-impl/src/com/intellij/application/options/schemes/EditableSchemesCombo.java index 2429bd1a2b8e..3973d9b4c604 100644 --- a/platform/lang-impl/src/com/intellij/application/options/schemes/EditableSchemesCombo.java +++ b/platform/lang-impl/src/com/intellij/application/options/schemes/EditableSchemesCombo.java @@ -154,6 +154,11 @@ public class EditableSchemesCombo { return mySchemesPanel.getModel().supportsProjectSchemes(); } + @Override + protected boolean isProjectScheme(@NotNull T scheme) { + return mySchemesPanel.getModel().isProjectScheme(scheme); + } + @NotNull @Override protected SimpleTextAttributes getSchemeAttributes(T scheme) { From 99669bcd0a77ec676b578f21e131708d8cc251a7 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Mon, 13 Feb 2017 17:25:50 +0300 Subject: [PATCH 07/12] scheme ui: move combobox from analyze code dialog to SchemeCombo --- .../intellij/codeInspection/actions/CodeInspectionAction.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInspection/actions/CodeInspectionAction.java b/platform/lang-impl/src/com/intellij/codeInspection/actions/CodeInspectionAction.java index 891be158e796..e4179b204bf7 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/actions/CodeInspectionAction.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/actions/CodeInspectionAction.java @@ -123,7 +123,7 @@ public class CodeInspectionAction extends BaseAnalysisAction { } else { //if profile was disabled and cancel after apply was pressed - final InspectionProfile profile = (InspectionProfile)profiles.getSelectedItem(); + final InspectionProfile profile = profiles.getSelectedScheme(); final boolean canExecute = profile != null && profile.isExecutable(project); dialog.setOKActionEnabled(canExecute); } From 711a5304988d60020042dc5b51da81e142252319 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Mon, 13 Feb 2017 17:30:38 +0300 Subject: [PATCH 08/12] inspection settings: remove redundant parameter --- .../codeInspection/ex/InspectionProfileTest.java | 2 +- .../ui/header/InspectionToolsConfigurable.java | 14 ++++---------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/ex/InspectionProfileTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/ex/InspectionProfileTest.java index 2a4c24924f3a..8d192a9aa260 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/ex/InspectionProfileTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/ex/InspectionProfileTest.java @@ -293,7 +293,7 @@ public class InspectionProfileTest extends LightIdeaTestCase { Element toImportElement = profile.writeScheme(); final InspectionProfileImpl importedProfile = - InspectionToolsConfigurable.importInspectionProfile(toImportElement, getApplicationProfileManager(), getProject(), null); + InspectionToolsConfigurable.importInspectionProfile(toImportElement, getApplicationProfileManager(), getProject()); //check merged Element mergedElement = JDOMUtil.loadDocument(mergedText).getRootElement(); diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionToolsConfigurable.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionToolsConfigurable.java index 08e7d145d831..b17af0755073 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionToolsConfigurable.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionToolsConfigurable.java @@ -58,7 +58,6 @@ import com.intellij.util.ui.UIUtil; import org.jdom.Element; import org.jdom.JDOMException; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; @@ -389,7 +388,7 @@ public abstract class InspectionToolsConfigurable extends BaseConfigurable if (file != null) { final InspectionProfileImpl profile; try { - profile = importInspectionProfile(JDOMUtil.load(file.getInputStream()), myApplicationProfileManager, getProject(), wholePanel); + profile = importInspectionProfile(JDOMUtil.load(file.getInputStream()), myApplicationProfileManager, getProject()); final SingleInspectionProfilePanel existed = getProfilePanel(profile); if (existed != null) { if (Messages.showOkCancelDialog(wholePanel, "Profile with name \'" + @@ -435,12 +434,7 @@ public abstract class InspectionToolsConfigurable extends BaseConfigurable public static InspectionProfileImpl importInspectionProfile(@NotNull Element rootElement, @NotNull BaseInspectionProfileManager profileManager, - @NotNull Project project, - @Nullable JPanel anchorPanel) { - final boolean unitTestMode = ApplicationManager.getApplication().isUnitTestMode(); - if (!unitTestMode) { - LOG.assertTrue(anchorPanel != null); - } + @NotNull Project project) { InspectionProfileImpl profile = new InspectionProfileImpl("TempProfile", InspectionToolRegistrar.getInstance(), profileManager); if (Comparing.strEqual(rootElement.getName(), "component")) { @@ -461,8 +455,8 @@ public abstract class InspectionToolsConfigurable extends BaseConfigurable } } if (!levels.isEmpty()) { - if (!unitTestMode) { - if (Messages.showYesNoDialog(anchorPanel, "Undefined severities detected: " + + if (!ApplicationManager.getApplication().isUnitTestMode()) { + if (Messages.showYesNoDialog(project, "Undefined severities detected: " + StringUtil.join(levels, ", ") + ". Do you want to create them?", "Warning", Messages.getWarningIcon()) == Messages.YES) { From 47e40909020cd310b9657ef4f18fed67e3fc380f Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Mon, 13 Feb 2017 17:43:38 +0300 Subject: [PATCH 09/12] scheme ui: allow AbstractSchemesPanel to have custom right-side component --- .../codeStyle/CodeStyleSchemesActions.java | 2 +- .../codeStyle/CodeStyleSchemesPanel.java | 4 +- .../options/colors/ColorSchemeActions.java | 2 +- .../options/colors/SchemesPanel.java | 4 +- .../schemes/AbstractSchemeActions.java | 10 ++-- .../options/schemes/AbstractSchemesPanel.java | 26 +++++----- .../options/schemes/EditableSchemesCombo.java | 4 +- .../options/schemes/SimpleSchemesPanel.java | 48 +++++++++++++++++++ 8 files changed, 72 insertions(+), 28 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/application/options/schemes/SimpleSchemesPanel.java 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 7fb3e5eff73b..53ff87e5f782 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 @@ -42,7 +42,7 @@ abstract class CodeStyleSchemesActions extends AbstractSchemeActions schemesPanel) { + protected CodeStyleSchemesActions(@NotNull AbstractSchemesPanel schemesPanel) { super(schemesPanel); } 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 8bf9e152c0c2..dc5c6fc04729 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 @@ -18,7 +18,7 @@ package com.intellij.application.options.codeStyle; import com.intellij.application.options.schemes.AbstractSchemeActions; -import com.intellij.application.options.schemes.AbstractSchemesPanel; +import com.intellij.application.options.schemes.SimpleSchemesPanel; import com.intellij.application.options.schemes.SchemesModel; import com.intellij.openapi.application.ApplicationManager; import com.intellij.psi.codeStyle.CodeStyleScheme; @@ -29,7 +29,7 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; -public class CodeStyleSchemesPanel extends AbstractSchemesPanel { +public class CodeStyleSchemesPanel extends SimpleSchemesPanel { private final CodeStyleSchemesModel myModel; 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 f80933a0d378..74ba96fc51fb 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 @@ -40,7 +40,7 @@ import java.util.List; public abstract class ColorSchemeActions extends AbstractSchemeActions { - protected ColorSchemeActions(@NotNull AbstractSchemesPanel schemesPanel) { + protected ColorSchemeActions(@NotNull AbstractSchemesPanel schemesPanel) { super(schemesPanel); } 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 55831d32410c..5292b880b627 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 @@ -18,14 +18,14 @@ package com.intellij.application.options.colors; import com.intellij.application.options.SkipSelfSearchComponent; import com.intellij.application.options.schemes.AbstractSchemeActions; -import com.intellij.application.options.schemes.AbstractSchemesPanel; +import com.intellij.application.options.schemes.SimpleSchemesPanel; import com.intellij.application.options.schemes.SchemesModel; import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.util.EventDispatcher; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public class SchemesPanel extends AbstractSchemesPanel implements SkipSelfSearchComponent { +public class SchemesPanel extends SimpleSchemesPanel implements SkipSelfSearchComponent { private final ColorAndFontOptions myOptions; private final EventDispatcher myDispatcher = EventDispatcher.create(ColorAndFontSettingsListener.class); 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 e14edcd7e2f4..f26338af189d 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 @@ -31,7 +31,7 @@ import java.util.List; /** *

- * A standard set of scheme actions: copy, reset, rename, etc. used in {@link AbstractSchemesPanel}. More actions can be added via + * A standard set of scheme actions: copy, reset, rename, etc. used in {@link SimpleSchemesPanel}. 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. @@ -39,7 +39,7 @@ import java.util.List; * 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 SimpleSchemesPanel * @see SchemesModel * @see SchemeImporter * @see SchemeExporter @@ -48,9 +48,9 @@ public abstract class AbstractSchemeActions { private final Collection mySchemeImportersNames; private final Collection mySchemeExporterNames; - private final AbstractSchemesPanel mySchemesPanel; + private final AbstractSchemesPanel mySchemesPanel; - protected AbstractSchemeActions(@NotNull AbstractSchemesPanel schemesPanel) { + protected AbstractSchemeActions(@NotNull AbstractSchemesPanel schemesPanel) { mySchemesPanel = schemesPanel; mySchemeImportersNames = getSchemeImportersNames(); mySchemeExporterNames = getSchemeExporterNames(); @@ -415,7 +415,7 @@ public abstract class AbstractSchemeActions { */ protected abstract Class getSchemeType(); - public final 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 b46a604782f9..2942fd983eb2 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 @@ -42,12 +42,11 @@ import java.util.Collection; * @see AbstractSchemeActions * @see SchemesModel */ -public abstract class AbstractSchemesPanel extends JPanel { - +public abstract class AbstractSchemesPanel extends JPanel { private EditableSchemesCombo mySchemesCombo; private AbstractSchemeActions myActions; private JComponent myToolbar; - private JLabel myInfoLabel; + protected InfoComponent myInfoComponent; public AbstractSchemesPanel() { setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS)); @@ -60,12 +59,12 @@ public abstract class AbstractSchemesPanel extends JPanel { controlsPanel.add(new JLabel(getTitle())); controlsPanel.add(Box.createRigidArea(new Dimension(10, 0))); myActions = createSchemeActions(); - mySchemesCombo = new EditableSchemesCombo<>(this); + mySchemesCombo = new EditableSchemesCombo(this); controlsPanel.add(mySchemesCombo.getComponent()); myToolbar = createToolbar(); controlsPanel.add(myToolbar); - myInfoLabel = new JLabel(); - controlsPanel.add(myInfoLabel); + myInfoComponent = createInfoComponent(); + controlsPanel.add(myInfoComponent); controlsPanel.add(Box.createHorizontalGlue()); controlsPanel.setMaximumSize(new Dimension(controlsPanel.getMaximumSize().width, mySchemesCombo.getComponent().getPreferredSize().height)); add(controlsPanel); @@ -74,7 +73,6 @@ public abstract class AbstractSchemesPanel extends JPanel { add(Box.createVerticalGlue()); add(Box.createRigidArea(new Dimension(0, 10))); } - private JComponent createToolbar() { DefaultActionGroup toolbarActionGroup = new DefaultActionGroup(); toolbarActionGroup.add(new TopActionGroup()); @@ -119,7 +117,7 @@ public abstract class AbstractSchemesPanel extends JPanel { return mySchemesCombo.getSelectedScheme(); } - public final void selectScheme(@Nullable T scheme) { + public void selectScheme(@Nullable T scheme) { mySchemesCombo.selectScheme(scheme); } @@ -139,19 +137,17 @@ public abstract class AbstractSchemesPanel extends JPanel { mySchemesCombo.cancelEdit(); } - public final void showInfo(@Nullable String message, @NotNull MessageType messageType) { - myInfoLabel.setText(message); - myInfoLabel.setForeground(messageTypeToColor(messageType)); - } + public abstract void showInfo(@Nullable String message, @NotNull MessageType messageType); - public final void clearInfo() { - myInfoLabel.setText(null); - } + public abstract void clearInfo(); public final AbstractSchemeActions getActions() { return myActions; } + @NotNull + protected abstract InfoComponent createInfoComponent(); + protected String getTitle() { return ApplicationBundle.message("editbox.scheme.name"); } diff --git a/platform/lang-impl/src/com/intellij/application/options/schemes/EditableSchemesCombo.java b/platform/lang-impl/src/com/intellij/application/options/schemes/EditableSchemesCombo.java index 3973d9b4c604..4fad4c736c51 100644 --- a/platform/lang-impl/src/com/intellij/application/options/schemes/EditableSchemesCombo.java +++ b/platform/lang-impl/src/com/intellij/application/options/schemes/EditableSchemesCombo.java @@ -42,14 +42,14 @@ public class EditableSchemesCombo { private SchemesCombo myComboBox; private JPanel myRootPanel; - private AbstractSchemesPanel mySchemesPanel; + private AbstractSchemesPanel mySchemesPanel; private final CardLayout myLayout; private final JTextField myNameEditorField; private final static KeyStroke ESC_KEY_STROKE = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false); private final static KeyStroke ENTER_KEY_STROKE = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false); - public EditableSchemesCombo(@NotNull AbstractSchemesPanel schemesPanel) { + public EditableSchemesCombo(@NotNull AbstractSchemesPanel schemesPanel) { mySchemesPanel = schemesPanel; myLayout = new CardLayout(); myRootPanel = new JPanel(myLayout); diff --git a/platform/lang-impl/src/com/intellij/application/options/schemes/SimpleSchemesPanel.java b/platform/lang-impl/src/com/intellij/application/options/schemes/SimpleSchemesPanel.java new file mode 100644 index 000000000000..565c66038dbe --- /dev/null +++ b/platform/lang-impl/src/com/intellij/application/options/schemes/SimpleSchemesPanel.java @@ -0,0 +1,48 @@ +/* + * 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.ui.MessageType; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; + +/** + * Basic implementation of {@link AbstractSchemesPanel} that provides simple informational label as right side of the panel. + * + * @see AbstractSchemeActions + * @see SchemesModel + */ +public abstract class SimpleSchemesPanel extends AbstractSchemesPanel { + @NotNull + @Override + protected JLabel createInfoComponent() { + return new JLabel(); + } + + @Override + public final void showInfo(@Nullable String message, @NotNull MessageType messageType) { + myInfoComponent.setText(message); + myInfoComponent.setForeground(messageType.getTitleForeground()); + } + + @Override + public final void clearInfo() { + myInfoComponent.setText(null); + } +} From 57dfffd325b7a12e76ae84ce84117ff846ac7910 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Mon, 13 Feb 2017 17:59:06 +0300 Subject: [PATCH 10/12] scheme ui: generalize CodeStyleSchemeCopyExporter for arbitrary given scheme --- .../schemes/SerializableSchemeExporter.java} | 17 +++++++++-------- .../src/META-INF/LangExtensions.xml | 2 +- 2 files changed, 10 insertions(+), 9 deletions(-) rename platform/lang-impl/src/com/intellij/{psi/impl/source/codeStyle/CodeStyleSchemeCopyExporter.java => application/options/schemes/SerializableSchemeExporter.java} (70%) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleSchemeCopyExporter.java b/platform/lang-impl/src/com/intellij/application/options/schemes/SerializableSchemeExporter.java similarity index 70% rename from platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleSchemeCopyExporter.java rename to platform/lang-impl/src/com/intellij/application/options/schemes/SerializableSchemeExporter.java index de8e151820f8..a49cbff96000 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleSchemeCopyExporter.java +++ b/platform/lang-impl/src/com/intellij/application/options/schemes/SerializableSchemeExporter.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * 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. @@ -13,10 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.psi.impl.source.codeStyle; +package com.intellij.application.options.schemes; +import com.intellij.configurationStore.SerializableScheme; +import com.intellij.openapi.options.Scheme; import com.intellij.openapi.options.SchemeExporter; -import com.intellij.psi.codeStyle.CodeStyleScheme; import org.jdom.Element; import org.jdom.output.Format; import org.jdom.output.XMLOutputter; @@ -27,15 +28,15 @@ import java.io.OutputStream; import java.io.OutputStreamWriter; /** - * Exports (copies) a code style scheme to an external file as is. + * Exports (copies) a scheme to an external file as is. * * @author Rustam Vishnyakov */ -public class CodeStyleSchemeCopyExporter extends SchemeExporter { +public class SerializableSchemeExporter extends SchemeExporter { @Override - public void exportScheme(@NotNull final CodeStyleScheme scheme, @NotNull OutputStream outputStream) throws Exception { - assert scheme instanceof CodeStyleSchemeImpl; - writeToStream(outputStream, ((CodeStyleSchemeImpl)scheme).writeScheme()); + public void exportScheme(@NotNull Scheme scheme, @NotNull OutputStream outputStream) throws Exception { + assert scheme instanceof SerializableScheme; + writeToStream(outputStream, ((SerializableScheme)scheme).writeScheme()); } @Override diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index ebaceecb4428..ae5f947e3540 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -975,7 +975,7 @@ + implementationClass="com.intellij.application.options.schemes.SerializableSchemeExporter"/> Date: Tue, 14 Feb 2017 15:10:07 +0300 Subject: [PATCH 11/12] schemes ui: introduce description aware schemes panel --- ...AbstractDescriptionAwareSchemesPanel.java} | 136 +++++++++--------- .../schemes/AbstractSchemeActions.java | 4 +- .../DescriptionAwareSchemeActions.java | 59 ++++++++ 3 files changed, 133 insertions(+), 66 deletions(-) rename platform/lang-impl/src/com/intellij/{profile/codeInspection/ui/header/AuxiliaryRightPanel.java => application/options/schemes/AbstractDescriptionAwareSchemesPanel.java} (52%) create mode 100644 platform/lang-impl/src/com/intellij/application/options/schemes/DescriptionAwareSchemeActions.java diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/AuxiliaryRightPanel.java b/platform/lang-impl/src/com/intellij/application/options/schemes/AbstractDescriptionAwareSchemesPanel.java similarity index 52% rename from platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/AuxiliaryRightPanel.java rename to platform/lang-impl/src/com/intellij/application/options/schemes/AbstractDescriptionAwareSchemesPanel.java index 83646e67cf64..f3394c839d22 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/AuxiliaryRightPanel.java +++ b/platform/lang-impl/src/com/intellij/application/options/schemes/AbstractDescriptionAwareSchemesPanel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -13,63 +13,63 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.profile.codeInspection.ui.header; +package com.intellij.application.options.schemes; +import com.intellij.openapi.options.Scheme; +import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.ui.ex.MultiLineLabel; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.ClickListener; -import com.intellij.ui.JBColor; +import com.intellij.ui.components.JBTextField; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; -import java.awt.event.MouseEvent; +import java.awt.event.*; -/** - * @author Dmitry Batkovich - */ -public class AuxiliaryRightPanel extends JPanel { +public abstract class AbstractDescriptionAwareSchemesPanel extends AbstractSchemesPanel { private static final String SHOW_DESCRIPTION_CARD = "show.description.card"; private static final String EDIT_DESCRIPTION_CARD = "edit.description.card"; private static final String ERROR_CARD = "error.card"; - private final DescriptionLabel myDescriptionLabel; - private final JLabel myErrorLabel; - private final ValidatedTextField myValidatedTextField; - private final CardLayout myLayout; - private final JPanel myCardPanel; + private final static KeyStroke ESC_KEY_STROKE = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false); + private final static KeyStroke ENTER_KEY_STROKE = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false); - public AuxiliaryRightPanel(final DescriptionSaveListener descriptionListener) { - myCardPanel = new JPanel(); - myDescriptionLabel = new DescriptionLabel(); + private DescriptionLabel myDescriptionLabel; + private JLabel myWarningLabel; + private JBTextField myDescriptionTextField; + private CardLayout myLayout; - myErrorLabel = new JLabel(); - myErrorLabel.setBackground(UIUtil.isUnderDarcula() ? JBColor.PINK.darker() : JBColor.PINK); - myErrorLabel.setForeground(JBColor.BLACK); - myErrorLabel.setOpaque(true); + @NotNull + @Override + protected JPanel createInfoComponent() { + JPanel panel = new JPanel(); + myLayout = new CardLayout(); + panel.setLayout(myLayout); - myValidatedTextField = new ValidatedTextField(new SaveInputComponentValidator() { + myDescriptionTextField = new JBTextField(); + myDescriptionTextField.addFocusListener(new FocusAdapter() { @Override - public void doSave(@NotNull String text) { - descriptionListener.saveDescription(text.trim()); - } - - @Override - public boolean checkValid(@NotNull String text) { - return true; - } - - @Override - public void cancel() { - descriptionListener.cancel(); + public void focusLost(FocusEvent e) { + applyDescription(); } }); + myDescriptionTextField.registerKeyboardAction(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + applyDescription(); + } + }, ESC_KEY_STROKE, JComponent.WHEN_FOCUSED); + myDescriptionTextField.registerKeyboardAction(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + showDescription(); + } + }, ENTER_KEY_STROKE, JComponent.WHEN_FOCUSED); - myLayout = new CardLayout(); - myCardPanel.setLayout(myLayout); - myCardPanel.setBorder(BorderFactory.createEmptyBorder(2, 0, 4, 0)); - + myDescriptionLabel = new DescriptionLabel(); new ClickListener() { @Override public boolean onClick(@NotNull MouseEvent event, int clickCount) { @@ -81,43 +81,51 @@ public class AuxiliaryRightPanel extends JPanel { } }.installOn(myDescriptionLabel); - myCardPanel.add(myDescriptionLabel, SHOW_DESCRIPTION_CARD); - myCardPanel.add(myErrorLabel, ERROR_CARD); - myCardPanel.add(myValidatedTextField, EDIT_DESCRIPTION_CARD); + myWarningLabel = new JLabel(); - showDescription(null); + panel.add(myDescriptionTextField, EDIT_DESCRIPTION_CARD); + panel.add(myDescriptionLabel, SHOW_DESCRIPTION_CARD); + panel.add(myWarningLabel, ERROR_CARD); - setLayout(new BorderLayout()); - add(myValidatedTextField.getHintLabel(), BorderLayout.NORTH); - add(myCardPanel, BorderLayout.CENTER); + myLayout.show(panel, ERROR_CARD); + return panel; } - public void showDescription(@Nullable String newDescription) { - if (newDescription == null) { - newDescription = ""; + @Override + public final void showInfo(@Nullable String message, @NotNull MessageType messageType) { + myWarningLabel.setText(message); + myWarningLabel.setForeground(messageType.getTitleForeground()); + myLayout.show(myInfoComponent, ERROR_CARD); + } + + @Override + public void selectScheme(@Nullable T scheme) { + super.selectScheme(scheme); + if (scheme != null) { + showDescription(); } - myDescriptionLabel.setAllText(newDescription); - myLayout.show(myCardPanel, SHOW_DESCRIPTION_CARD); + } + + @Override + public final void clearInfo() { + myLayout.show(myInfoComponent, SHOW_DESCRIPTION_CARD); + } + + public void showDescription() { + String newDescription = (((DescriptionAwareSchemeActions)getActions()).getDescription(getSelectedScheme())); + myDescriptionLabel.setAllText(StringUtil.notNullize(newDescription)); + myLayout.show(myInfoComponent, SHOW_DESCRIPTION_CARD); } public void editDescription(@Nullable String startValue) { - if (startValue == null) { - startValue = ""; - } - myValidatedTextField.setText(startValue); - myLayout.show(myCardPanel, EDIT_DESCRIPTION_CARD); - myValidatedTextField.requestFocus(); + myLayout.show(myInfoComponent, EDIT_DESCRIPTION_CARD); + myDescriptionTextField.setText(StringUtil.notNullize(startValue)); + myDescriptionTextField.requestFocus(); } - public void showError(final @NotNull String errorText) { - myErrorLabel.setText(errorText); - myLayout.show(myCardPanel, ERROR_CARD); - } - - public interface DescriptionSaveListener { - void saveDescription(@NotNull String description); - - void cancel(); + private void applyDescription() { + (((DescriptionAwareSchemeActions)getActions())).setDescription(getSelectedScheme(), myDescriptionTextField.getText()); + showDescription(); } private static class DescriptionLabel extends MultiLineLabel { 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 f26338af189d..2e8fe58ae104 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 @@ -48,7 +48,7 @@ public abstract class AbstractSchemeActions { private final Collection mySchemeImportersNames; private final Collection mySchemeExporterNames; - private final AbstractSchemesPanel mySchemesPanel; + protected final AbstractSchemesPanel mySchemesPanel; protected AbstractSchemeActions(@NotNull AbstractSchemesPanel schemesPanel) { mySchemesPanel = schemesPanel; @@ -84,6 +84,7 @@ public abstract class AbstractSchemeActions { actions.add(new RenameAction()); actions.add(new ResetAction()); actions.add(new DeleteAction()); + addAdditionalActions(actions); if (!mySchemeExporterNames.isEmpty()) { actions.add(new ActionGroupPopupAction(ApplicationBundle.message("settings.editor.scheme.export"), mySchemeExporterNames) { @NotNull @@ -103,7 +104,6 @@ public abstract class AbstractSchemeActions { } }); } - addAdditionalActions(actions); return actions; } diff --git a/platform/lang-impl/src/com/intellij/application/options/schemes/DescriptionAwareSchemeActions.java b/platform/lang-impl/src/com/intellij/application/options/schemes/DescriptionAwareSchemeActions.java new file mode 100644 index 000000000000..e64f996ee5be --- /dev/null +++ b/platform/lang-impl/src/com/intellij/application/options/schemes/DescriptionAwareSchemeActions.java @@ -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.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.options.Scheme; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public abstract class DescriptionAwareSchemeActions extends AbstractSchemeActions { + protected DescriptionAwareSchemeActions(@NotNull AbstractDescriptionAwareSchemesPanel schemesPanel) { + super(schemesPanel); + } + + @Nullable + public abstract String getDescription(@NotNull T scheme); + + protected abstract void setDescription(@NotNull T scheme, @NotNull String newDescription); + + @Override + protected void addAdditionalActions(@NotNull List defaultActions) { + defaultActions.add(new AnAction("Edit description") { + + @Override + public void update(AnActionEvent e) { + final String text = getDescription(getSchemesPanel().getSelectedScheme()) == null ? "Add description" : "Edit description"; + e.getPresentation().setText(text); + } + + @Override + public void actionPerformed(AnActionEvent e) { + ((AbstractDescriptionAwareSchemesPanel) mySchemesPanel).editDescription(getDescription(getSchemesPanel().getSelectedScheme())); + } + }); + } + + @Override + protected void onSchemeChanged(@Nullable T scheme) { + if (scheme != null) { + ((AbstractDescriptionAwareSchemesPanel) mySchemesPanel).showDescription(); + } + } +} From faa19394c30749ccfa66a5c1acebeb5a17118744 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Tue, 14 Feb 2017 15:18:48 +0300 Subject: [PATCH 12/12] schemes ui: move inspection settings to schemes management ui --- .../actions/CodeInspectionAction.java | 8 +- .../ui/InspectionProfileImporter.java | 49 ++ .../header/InspectionProfileSchemesModel.java | 203 +++++++++ .../header/InspectionProfileSchemesPanel.java | 271 +++++++++++ .../header/InspectionToolsConfigurable.java | 427 ++---------------- .../ui/header/ManageButton.java | 158 ------- .../ui/header/ManageButtonBuilder.java | 45 -- .../ui/header/ProfilesChooser.java | 86 ---- .../ui/header/ProfilesComboBox.java | 167 ------- .../header/SaveInputComponentValidator.java | 61 --- .../ui/header/ValidatedTextField.java | 132 ------ .../src/META-INF/LangExtensions.xml | 9 + 12 files changed, 577 insertions(+), 1039 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionProfileImporter.java create mode 100644 platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionProfileSchemesModel.java create mode 100644 platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionProfileSchemesPanel.java delete mode 100644 platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/ManageButton.java delete mode 100644 platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/ManageButtonBuilder.java delete mode 100644 platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/ProfilesChooser.java delete mode 100644 platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/ProfilesComboBox.java delete mode 100644 platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/SaveInputComponentValidator.java delete mode 100644 platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/ValidatedTextField.java diff --git a/platform/lang-impl/src/com/intellij/codeInspection/actions/CodeInspectionAction.java b/platform/lang-impl/src/com/intellij/codeInspection/actions/CodeInspectionAction.java index e4179b204bf7..c7b07ec9bcd0 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/actions/CodeInspectionAction.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/actions/CodeInspectionAction.java @@ -34,6 +34,7 @@ import com.intellij.profile.codeInspection.InspectionProfileManager; import com.intellij.profile.codeInspection.InspectionProjectProfileManager; import com.intellij.profile.codeInspection.ProjectInspectionProfileManager; import com.intellij.profile.codeInspection.ui.ErrorsConfigurable; +import com.intellij.profile.codeInspection.ui.header.InspectionProfileSchemesModel; import com.intellij.profile.codeInspection.ui.header.InspectionToolsConfigurable; import com.intellij.ui.ComboboxWithBrowseButton; import com.intellij.ui.SimpleTextAttributes; @@ -43,8 +44,6 @@ import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.util.ArrayList; -import java.util.List; public class CodeInspectionAction extends BaseAnalysisAction { private static final Logger LOG = Logger.getInstance(CodeInspectionAction.class); @@ -176,10 +175,7 @@ public class CodeInspectionAction extends BaseAnalysisAction { InspectionProfileManager appProfileManager, InspectionProjectProfileManager projectProfileManager, Project project) { - List profiles = new ArrayList<>(); - profiles.addAll(appProfileManager.getProfiles()); - profiles.addAll(projectProfileManager.getProfiles()); - profilesCombo.resetSchemes(profiles); + profilesCombo.resetSchemes(InspectionProfileSchemesModel.getSortedProfiles(appProfileManager, projectProfileManager)); InspectionProfileImpl selectedProfile = getProfileToUse(project, appProfileManager, projectProfileManager); profilesCombo.selectScheme(selectedProfile); } diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionProfileImporter.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionProfileImporter.java new file mode 100644 index 000000000000..9b3028ad346e --- /dev/null +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/InspectionProfileImporter.java @@ -0,0 +1,49 @@ +/* + * 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.profile.codeInspection.ui; + +import com.intellij.codeInspection.ex.NewInspectionProfile; +import com.intellij.openapi.options.SchemeFactory; +import com.intellij.openapi.options.SchemeImportException; +import com.intellij.openapi.options.SchemeImporter; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +//TODO should replace current implementation +public class InspectionProfileImporter implements SchemeImporter { + @NotNull + @Override + public String[] getSourceExtensions() { + return new String[] {"xml"}; + } + + @Nullable + @Override + public NewInspectionProfile importScheme(@NotNull Project project, + @NotNull VirtualFile selectedFile, + @NotNull NewInspectionProfile currentScheme, + @NotNull SchemeFactory schemeFactory) throws SchemeImportException { + throw new UnsupportedOperationException(); + } + + @Nullable + @Override + public String getAdditionalImportInfo(@NotNull NewInspectionProfile scheme) { + return null; + } +} diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionProfileSchemesModel.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionProfileSchemesModel.java new file mode 100644 index 000000000000..db4399ca09f0 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionProfileSchemesModel.java @@ -0,0 +1,203 @@ +/* + * 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.profile.codeInspection.ui.header; + +import com.intellij.application.options.schemes.SchemesModel; +import com.intellij.codeInspection.ex.InspectionProfileImpl; +import com.intellij.codeInspection.ex.InspectionProfileModifiableModel; +import com.intellij.profile.codeInspection.InspectionProfileManager; +import com.intellij.profile.codeInspection.ui.SingleInspectionProfilePanel; +import com.intellij.util.Consumer; +import com.intellij.util.SmartList; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public abstract class InspectionProfileSchemesModel implements SchemesModel { + private final List myProfilePanels = new ArrayList<>(); + private final List myDeletedProfiles = new SmartList<>(); + + private final InspectionProfileManager myApplicationProfileManager; + private final InspectionProfileManager myProjectProfileManager; + + protected InspectionProfileSchemesModel(@NotNull InspectionProfileManager appProfileManager, + @NotNull InspectionProfileManager projectProfileManager) { + myApplicationProfileManager = appProfileManager; + myProjectProfileManager = projectProfileManager; + } + + @Override + public boolean canDuplicateScheme(@NotNull InspectionProfileModifiableModel profile) { + return true; + } + + @Override + public boolean canResetScheme(@NotNull InspectionProfileModifiableModel profile) { + return true; + } + + @Override + public boolean canDeleteScheme(@NotNull InspectionProfileModifiableModel profile) { + boolean projectProfileFound = false; + boolean ideProfileFound = false; + + for (SingleInspectionProfilePanel profilePanel : myProfilePanels) { + final InspectionProfileModifiableModel profile1 = profilePanel.getProfile(); + if (profile == profile1) continue; + final boolean isProjectProfile = profile1.getProfileManager() == myProjectProfileManager; + projectProfileFound |= isProjectProfile; + ideProfileFound |= !isProjectProfile; + + if (ideProfileFound && projectProfileFound) break; + } + + return profile.getProfileManager() == myProjectProfileManager ? projectProfileFound : ideProfileFound; + } + + @Override + public boolean isProjectScheme(@NotNull InspectionProfileModifiableModel profile) { + return profile.isProjectLevel(); + } + + @Override + public boolean canRenameScheme(@NotNull InspectionProfileModifiableModel profile) { + return true; + } + + @Override + public boolean containsScheme(@NotNull String name, boolean isProjectProfile) { + return hasName(name, isProjectProfile); + } + + @Override + public boolean differsFromDefault(@NotNull InspectionProfileModifiableModel profile) { + return false; + } + + @Override + public void removeScheme(@NotNull InspectionProfileModifiableModel profile) { + final SingleInspectionProfilePanel panel = getProfilePanel(profile); + removeProfile(profile); + myDeletedProfiles.add(profile); + onProfileRemoved(panel); + } + + protected abstract void onProfileRemoved(@NotNull SingleInspectionProfilePanel profilePanel); + + @Override + public boolean supportsProjectSchemes() { + return true; + } + + void addProfile(InspectionProfileModifiableModel profile) { + myProfilePanels.add(createPanel(profile)); + } + + void removeProfile(InspectionProfileImpl profile) { + for (SingleInspectionProfilePanel panel : myProfilePanels) { + if (panel.getProfile().equals(profile)) { + myProfilePanels.remove(panel); + break; + } + } + } + + void updatePanel(@NotNull InspectionProfileSchemesPanel panel) { + final List allProfiles = myProfilePanels.stream().map(p -> p.getProfile()).collect(Collectors.toList()); + panel.resetSchemes(allProfiles); + } + + void apply(InspectionProfileModifiableModel selected, Consumer applyRootProfileAction) { + for (InspectionProfileImpl profile : myDeletedProfiles) { + profile.getProfileManager().deleteProfile(profile); + } + myDeletedProfiles.clear(); + + SingleInspectionProfilePanel selectedPanel = getProfilePanel(selected); + for (SingleInspectionProfilePanel panel : getProfilePanels()) { + panel.apply(); + if (panel == selectedPanel) { + applyRootProfileAction.consume(panel.getProfile()); + } + } + } + + void reset() { + disposeUI(); + myDeletedProfiles.clear(); + getSortedProfiles(myApplicationProfileManager, myProjectProfileManager) + .stream() + .map(InspectionProfileModifiableModel::new) + .forEach(this::addProfile); + } + + void disposeUI() { + for (SingleInspectionProfilePanel panel : myProfilePanels) { + panel.disposeUI(); + } + myProfilePanels.clear(); + } + + public SingleInspectionProfilePanel getProfilePanel(InspectionProfileImpl profile) { + return myProfilePanels.stream().filter(panel -> panel.getProfile().equals(profile)).findFirst().orElse(null); + } + + protected abstract SingleInspectionProfilePanel createPanel(InspectionProfileModifiableModel model); + + boolean hasName(@NotNull final String name, boolean shared) { + final boolean hasName = myProfilePanels.stream().map(SingleInspectionProfilePanel::getProfile).anyMatch(p -> name.equals(p.getName()) && p.isProjectLevel() == shared); + if (hasName) return true; + return myProfilePanels.stream().anyMatch(p -> { + final InspectionProfileModifiableModel profile = p.getProfile(); + return name.equals(profile.getName()) && profile.isProjectLevel() == shared; + }); + } + + List getProfilePanels() { + return myProfilePanels; + } + + int getSize() { + return myProfilePanels.size(); + } + + boolean hasDeletedProfiles() { + return !myDeletedProfiles.isEmpty(); + } + + @NotNull + InspectionProfileModifiableModel getModifiableModelFor(@NotNull InspectionProfileImpl profile) { + if (profile instanceof InspectionProfileModifiableModel) { + return (InspectionProfileModifiableModel)profile; + } + for (SingleInspectionProfilePanel panel : myProfilePanels) { + final InspectionProfileModifiableModel modifiableModel = panel.getProfile(); + if (modifiableModel.getSource().equals(profile)) { + return modifiableModel; + } + } + throw new AssertionError(); + } + + public static List getSortedProfiles(InspectionProfileManager appManager, + InspectionProfileManager projectManager) { + return ContainerUtil.concat(ContainerUtil.sorted(appManager.getProfiles()), + ContainerUtil.sorted(projectManager.getProfiles())); + } +} diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionProfileSchemesPanel.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionProfileSchemesPanel.java new file mode 100644 index 000000000000..1289e2c2945c --- /dev/null +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionProfileSchemesPanel.java @@ -0,0 +1,271 @@ +/* + * 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.profile.codeInspection.ui.header; + +import com.intellij.application.options.schemes.AbstractDescriptionAwareSchemesPanel; +import com.intellij.application.options.schemes.AbstractSchemeActions; +import com.intellij.application.options.schemes.DescriptionAwareSchemeActions; +import com.intellij.application.options.schemes.SchemeNameGenerator; +import com.intellij.codeInspection.ex.InspectionProfileImpl; +import com.intellij.codeInspection.ex.InspectionProfileModifiableModel; +import com.intellij.codeInspection.ex.InspectionToolRegistrar; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.fileChooser.FileChooser; +import com.intellij.openapi.fileChooser.FileChooserDescriptor; +import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; +import com.intellij.openapi.fileTypes.StdFileTypes; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.InvalidDataException; +import com.intellij.openapi.util.JDOMUtil; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.profile.codeInspection.BaseInspectionProfileManager; +import com.intellij.profile.codeInspection.ui.SingleInspectionProfilePanel; +import com.intellij.util.containers.ContainerUtil; +import org.jdom.Element; +import org.jdom.JDOMException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; + +import static com.intellij.openapi.util.io.FileUtil.sanitizeFileName; + +public class InspectionProfileSchemesPanel extends AbstractDescriptionAwareSchemesPanel { + private final static Logger LOG = Logger.getInstance(InspectionProfileSchemesPanel.class); + + private final Project myProject; + private final BaseInspectionProfileManager myAppProfileManager; + private final BaseInspectionProfileManager myProjectProfileManager; + private final InspectionToolsConfigurable myConfigurable; + private final InspectionProfileSchemesModel myModel; + + InspectionProfileSchemesPanel(@NotNull Project project, + @NotNull BaseInspectionProfileManager appProfileManager, + @NotNull BaseInspectionProfileManager projectProfileManager, + @NotNull InspectionToolsConfigurable configurable) { + myProject = project; + myAppProfileManager = appProfileManager; + myProjectProfileManager = projectProfileManager; + myConfigurable = configurable; + myModel = new InspectionProfileSchemesModel(appProfileManager, projectProfileManager) { + @Override + protected void onProfileRemoved(@NotNull SingleInspectionProfilePanel profilePanel) { + myConfigurable.removeProfilePanel(profilePanel); + final List currentProfiles = getModel() + .getProfilePanels() + .stream() + .map(SingleInspectionProfilePanel::getProfile) + .collect(Collectors.toList()); + resetSchemes(currentProfiles); + selectScheme(ContainerUtil.getFirstItem(currentProfiles)); + } + + @Override + protected SingleInspectionProfilePanel createPanel(InspectionProfileModifiableModel model) { + return myConfigurable.createPanel(model); + } + }; + } + + @NotNull + @Override + public InspectionProfileSchemesModel getModel() { + return myModel; + } + + @Override + protected AbstractSchemeActions createSchemeActions() { + return new DescriptionAwareSchemeActions(this) { + @Nullable + @Override + public String getDescription(@NotNull InspectionProfileModifiableModel scheme) { + SingleInspectionProfilePanel inspectionProfile = ((InspectionProfileSchemesModel) getModel()).getProfilePanel(scheme); + return inspectionProfile.getProfile().getDescription(); + } + + @Override + protected void setDescription(@NotNull InspectionProfileModifiableModel scheme, @NotNull String newDescription) { + InspectionProfileModifiableModel inspectionProfile = InspectionProfileSchemesPanel.this.getModel().getProfilePanel(scheme).getProfile(); + if (!Comparing.strEqual(newDescription, inspectionProfile.getDescription())) { + inspectionProfile.setDescription(newDescription); + inspectionProfile.setModified(true); + } + } + + @Override + protected void importScheme(@NotNull String importerName) { + final FileChooserDescriptor descriptor = new FileChooserDescriptor(true, false, false, false, false, false) { + @Override + public boolean isFileSelectable(VirtualFile file) { + return file.getFileType().equals(StdFileTypes.XML); + } + }; + descriptor.setDescription("Choose profile file"); + FileChooser.chooseFile(descriptor, myProject, null, file -> { + if (file != null) { + final InspectionProfileImpl profile; + try { + profile = InspectionToolsConfigurable + .importInspectionProfile(JDOMUtil.load(file.getInputStream()), myAppProfileManager, myProject); + final SingleInspectionProfilePanel existed = InspectionProfileSchemesPanel.this.getModel().getProfilePanel(profile); + if (existed != null) { + if (Messages.showOkCancelDialog(myProject, "Profile with name \'" + + profile.getName() + + "\' already exists. Do you want to overwrite it?", "Warning", + Messages.getInformationIcon()) != Messages.OK) { + return; + } + getModel().removeScheme(existed.getProfile()); + } + InspectionProfileModifiableModel model = new InspectionProfileModifiableModel(profile); + model.setModified(true); + addProfile(model); + selectScheme(model); + } + catch (JDOMException | InvalidDataException | IOException e) { + LOG.error(e); + } + } + }); + } + + @Override + protected void resetScheme(@NotNull InspectionProfileModifiableModel scheme) { + throw new UnsupportedOperationException(); + } + + @Override + protected void duplicateScheme(@NotNull InspectionProfileModifiableModel scheme, @NotNull String newName) { + final InspectionProfileModifiableModel newProfile = copyToNewProfile(scheme, myProject, newName, false); + addProfile(newProfile); + myConfigurable.selectProfile(newProfile); + selectScheme(newProfile); + } + + @Override + protected void exportScheme(@NotNull InspectionProfileModifiableModel scheme, @NotNull String exporterName) { + FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor(); + descriptor.setDescription("Choose directory to store profile file"); + FileChooser.chooseFile(descriptor, myProject, null, dir -> { + try { + LOG.assertTrue(true); + Element element = scheme.writeScheme(false); + File file = new File(FileUtil.toSystemDependentName(dir.getPath()), sanitizeFileName(scheme.getName()) + ".xml"); + if (file.isFile() && + Messages.showOkCancelDialog(myProject, "File \'" + file + "\' already exist. Do you want to overwrite it?", "Warning", + Messages.getQuestionIcon()) != Messages.OK) { + return; + } + + JDOMUtil.writeParent(element, file, "\n"); + } + catch (IOException e1) { + LOG.error(e1); + } + }); + + } + + @Override + protected void onSchemeChanged(@Nullable InspectionProfileModifiableModel scheme) { + super.onSchemeChanged(scheme); + if (scheme != null) { + myConfigurable.selectProfile(scheme); + } + } + + @Override + protected void renameScheme(@NotNull InspectionProfileModifiableModel scheme, @NotNull String newName) { + scheme.setName(newName); + } + + @Override + protected void copyToProject(@NotNull InspectionProfileModifiableModel scheme) { + copyToAnotherLevel(scheme, true); + } + + @Override + protected void copyToIDE(@NotNull InspectionProfileModifiableModel scheme) { + copyToAnotherLevel(scheme, false); + } + + @Override + protected Class getSchemeType() { + return InspectionProfileModifiableModel.class; + } + + private void copyToAnotherLevel(InspectionProfileModifiableModel profile, boolean copyToProject) { + String name = SchemeNameGenerator.getUniqueName(profile.getName(), schemeName -> ((InspectionProfileSchemesModel)getModel()).hasName(schemeName, copyToProject)); + final InspectionProfileModifiableModel newProfile = copyToNewProfile(profile, myProject, name, true); + addProfile(newProfile); + selectScheme(newProfile); + getSchemesPanel().startEdit(); + } + }; + } + + @Override + protected String getTitle() { + return "Profile:"; + } + + void apply() { + getModel().apply(getSelectedScheme(), (p) -> { + if (myConfigurable.setActiveProfileAsDefaultOnApply()) { + myConfigurable.applyRootProfile(p.getName(), p.isProjectLevel()); + } + }); + } + + void reset() { + getModel().reset(); + getModel().updatePanel(this); + } + + @NotNull + private InspectionProfileModifiableModel copyToNewProfile(@NotNull InspectionProfileImpl selectedProfile, + @NotNull Project project, + @NotNull String newName, + boolean modifyLevel) { + final boolean isProjectLevel = selectedProfile.isProjectLevel() ^ modifyLevel; + + BaseInspectionProfileManager profileManager = isProjectLevel ? myProjectProfileManager : myAppProfileManager; + InspectionProfileImpl inspectionProfile = + new InspectionProfileImpl(newName, InspectionToolRegistrar.getInstance(), profileManager); + + inspectionProfile.copyFrom(selectedProfile); + inspectionProfile.setName(newName); + inspectionProfile.initInspectionTools(project); + inspectionProfile.setProjectLevel(isProjectLevel); + + InspectionProfileModifiableModel modifiableModel = new InspectionProfileModifiableModel(inspectionProfile); + modifiableModel.setModified(true); + return modifiableModel; + } + + private void addProfile(InspectionProfileModifiableModel profile) { + final InspectionProfileModifiableModel selected = getSelectedScheme(); + getModel().addProfile(profile); + getModel().updatePanel(this); + selectScheme(selected); + } +} diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionToolsConfigurable.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionToolsConfigurable.java index b17af0755073..364cda9bedef 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionToolsConfigurable.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionToolsConfigurable.java @@ -24,14 +24,9 @@ import com.intellij.codeInspection.ex.InspectionToolRegistrar; import com.intellij.codeInspection.ex.InspectionToolWrapper; import com.intellij.lang.annotation.HighlightSeverity; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.colors.CodeInsightColors; import com.intellij.openapi.editor.colors.TextAttributesKey; import com.intellij.openapi.editor.markup.TextAttributes; -import com.intellij.openapi.fileChooser.FileChooser; -import com.intellij.openapi.fileChooser.FileChooserDescriptor; -import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; -import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.options.BaseConfigurable; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.SearchableConfigurable; @@ -39,126 +34,44 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.util.InvalidDataException; -import com.intellij.openapi.util.JDOMUtil; -import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.VirtualFile; import com.intellij.profile.codeInspection.BaseInspectionProfileManager; import com.intellij.profile.codeInspection.InspectionProfileManager; import com.intellij.profile.codeInspection.ProjectInspectionProfileManager; import com.intellij.profile.codeInspection.ui.ErrorsConfigurable; import com.intellij.profile.codeInspection.ui.SingleInspectionProfilePanel; -import com.intellij.ui.IdeBorderFactory; import com.intellij.util.Alarm; -import com.intellij.util.SmartList; +import com.intellij.util.ArrayUtil; import com.intellij.util.ui.JBInsets; -import com.intellij.util.ui.JBUI; -import com.intellij.util.ui.UIUtil; import org.jdom.Element; -import org.jdom.JDOMException; import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; -import java.io.File; -import java.io.IOException; -import java.util.*; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - -import static com.intellij.openapi.util.io.FileUtil.sanitizeFileName; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; public abstract class InspectionToolsConfigurable extends BaseConfigurable implements ErrorsConfigurable, SearchableConfigurable, Configurable.NoScroll { public static final String ID = "Errors"; public static final String DISPLAY_NAME = "Inspections"; - private static final String HEADER_TITLE = "Profile:"; - - private static final Logger LOG = Logger.getInstance(InspectionToolsConfigurable.class); - private static final Pattern COPIED_PROFILE_SUFFIX_PATTERN = Pattern.compile("(.*\\s*copy)\\s*(\\d*)"); protected final BaseInspectionProfileManager myApplicationProfileManager; protected final ProjectInspectionProfileManager myProjectProfileManager; - private final List myPanels = new ArrayList<>(); - private final List myDeletedProfiles = new SmartList<>(); - protected ProfilesChooser myProfiles; private JPanel myProfilePanelHolder; - private AuxiliaryRightPanel myAuxiliaryRightPanel; private Alarm mySelectionAlarm; + private InspectionProfileSchemesPanel myAbstractSchemesPanel; public InspectionToolsConfigurable(@NotNull ProjectInspectionProfileManager projectProfileManager) { myProjectProfileManager = projectProfileManager; myApplicationProfileManager = (BaseInspectionProfileManager)InspectionProfileManager.getInstance(); } - private static JComponent withBorderOnTop(final JComponent component) { - final JPanel panel = new JPanel(); - panel.add(component); - panel.setBorder(IdeBorderFactory.createEmptyBorder(UIUtil.isUnderDarcula() ? 10 : 13, 0, 0, 0)); - return panel; - } - private Project getProject() { return myProjectProfileManager.getProject(); } - @NotNull - private InspectionProfileImpl copyToNewProfile(@NotNull InspectionProfileImpl selectedProfile, - @NotNull Project project, - boolean modifyName, - boolean modifyLevel) { - LOG.assertTrue(modifyLevel || modifyName); - String profileDefaultName = selectedProfile.getName(); - - final boolean isProjectLevel = selectedProfile.isProjectLevel() ^ modifyLevel; - if (modifyName) { - final Matcher matcher = COPIED_PROFILE_SUFFIX_PATTERN.matcher(profileDefaultName); - int nextIdx; - if (matcher.matches()) { - profileDefaultName = matcher.group(1); - nextIdx = matcher.group(2).isEmpty() ? 1 : Integer.valueOf(matcher.group(2)); - } - else { - profileDefaultName += " copy"; - nextIdx = 1; - } - if (hasName(profileDefaultName, isProjectLevel)) { - String currentProfileDefaultName; - do { - currentProfileDefaultName = profileDefaultName + " " + String.valueOf(nextIdx); - nextIdx++; - } - while (hasName(currentProfileDefaultName, isProjectLevel)); - profileDefaultName = currentProfileDefaultName; - } - } - - BaseInspectionProfileManager profileManager = isProjectLevel ? myProjectProfileManager : myApplicationProfileManager; - InspectionProfileImpl inspectionProfile = - new InspectionProfileImpl(profileDefaultName, InspectionToolRegistrar.getInstance(), profileManager); - - inspectionProfile.copyFrom(selectedProfile); - inspectionProfile.setName(profileDefaultName); - inspectionProfile.initInspectionTools(project); - inspectionProfile.setProjectLevel(isProjectLevel); - - InspectionProfileModifiableModel modifiableModel = new InspectionProfileModifiableModel(inspectionProfile); - modifiableModel.setModified(true); - addProfile(modifiableModel); - return modifiableModel; - } - - protected void addProfile(InspectionProfileModifiableModel model) { - final SingleInspectionProfilePanel panel = createPanel(model); - myPanels.add(panel); - myProfilePanelHolder.add(panel); - myProfiles.getProfilesComboBox().addProfile(model); - myProfiles.getProfilesComboBox().selectProfile(model); - } - protected boolean setActiveProfileAsDefaultOnApply() { return true; } @@ -194,9 +107,6 @@ public abstract class InspectionToolsConfigurable extends BaseConfigurable final JPanel wholePanel = new JPanel(); wholePanel.setLayout(new BorderLayout()); - final JPanel toolbar = new JPanel(); - toolbar.setBorder(BorderFactory.createEmptyBorder(0, 0, 7, 0)); - myProfilePanelHolder = new JPanel() { @Override public void doLayout() { @@ -227,208 +137,15 @@ public abstract class InspectionToolsConfigurable extends BaseConfigurable return super.getMinimumSize(); } }; - - wholePanel.add(toolbar, BorderLayout.PAGE_START); wholePanel.add(myProfilePanelHolder, BorderLayout.CENTER); - myAuxiliaryRightPanel = new AuxiliaryRightPanel(new AuxiliaryRightPanel.DescriptionSaveListener() { - @Override - public void saveDescription(@NotNull String description) { - InspectionProfileModifiableModel inspectionProfile = getSelectedObject(); - if (!Comparing.strEqual(description, inspectionProfile.getDescription())) { - inspectionProfile.setDescription(description); - inspectionProfile.setModified(true); - } - myAuxiliaryRightPanel.showDescription(description); - } - - @Override - public void cancel() { - myAuxiliaryRightPanel.showDescription(getSelectedObject().getDescription()); - } - }); - - myProfiles = new ProfilesChooser(myProjectProfileManager.getProject()) { - @Override - public void onProfileChosen(InspectionProfileImpl inspectionProfile) { - showProfile(inspectionProfile); - myAuxiliaryRightPanel.showDescription(inspectionProfile.getDescription()); - } - }; JPanel profilesHolder = new JPanel(); profilesHolder.setLayout(new CardLayout()); - - - JComponent manageButton = new ManageButton(new ManageButtonBuilder() { - @Override - public boolean isProjectLevel() { - SingleInspectionProfilePanel panel = getSelectedPanel(); - return panel != null && panel.getProfile().isProjectLevel(); - } - - @Override - public boolean canChangeProfileLevel() { - return !hasName(getSelectedPanel().getProfile().getName(), !isProjectLevel()); - } - - @Override - public void copyToAnotherLevel() { - final SingleInspectionProfilePanel selectedPanel = getSelectedPanel(); - LOG.assertTrue(selectedPanel != null, "No settings selectedPanel for: " + getSelectedObject()); - copyToNewProfile(getSelectedObject(), getProject(), false, true); - } - - @Override - public void copy() { - rename(copyToNewProfile(getSelectedObject(), getProject(), true, false)); - } - - @Override - public void rename() { - rename(getSelectedObject()); - } - - private void rename(@NotNull final InspectionProfileImpl inspectionProfile) { - final String initialName = getSelectedPanel().getProfile().getName(); - myProfiles.showEditCard(initialName, new SaveInputComponentValidator() { - @Override - public void doSave(@NotNull String text) { - if (!text.equals(initialName)) { - inspectionProfile.setName(text); - myProfiles.getProfilesComboBox().resort(); - } - myProfiles.showComboBoxCard(); - } - - @Override - public boolean checkValid(@NotNull String text) { - final boolean isValid = text.equals(initialName) || !hasName(text, inspectionProfile.isProjectLevel()); - if (isValid) { - myAuxiliaryRightPanel.showDescription(getSelectedObject().getDescription()); - } - else { - myAuxiliaryRightPanel.showError("Name is already in use. Please change name to unique."); - } - return isValid; - } - - @Override - public void cancel() { - myProfiles.showComboBoxCard(); - myAuxiliaryRightPanel.showDescription(getSelectedObject().getDescription()); - } - }); - } - - @Override - public boolean canDelete() { - return isDeleteEnabled(myProfiles.getProfilesComboBox().getSelectedProfile()); - } - - @Override - public void delete() { - InspectionProfileModifiableModel selectedProfile = myProfiles.getProfilesComboBox().getSelectedProfile(); - myProfiles.getProfilesComboBox().removeProfile(selectedProfile); - myPanels.remove(getProfilePanel(selectedProfile)); - myDeletedProfiles.add(selectedProfile); - myProfiles.getProfilesComboBox().setSelectedIndex(0); - } - - @Override - public boolean canEditDescription() { - return true; - } - - @Override - public void editDescription() { - myAuxiliaryRightPanel.editDescription(getSelectedObject().getDescription()); - } - - @Override - public boolean hasDescription() { - return !StringUtil.isEmpty(getSelectedObject().getDescription()); - } - - @Override - public void export() { - FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor(); - descriptor.setDescription("Choose directory to store profile file"); - FileChooser.chooseFile(descriptor, getProject(), wholePanel, null, dir -> { - try { - SingleInspectionProfilePanel panel = getSelectedPanel(); - LOG.assertTrue(panel != null); - InspectionProfileImpl profile = getSelectedObject(); - LOG.assertTrue(true); - Element element = profile.writeScheme(false); - File file = new File(FileUtil.toSystemDependentName(dir.getPath()), sanitizeFileName(profile.getName()) + ".xml"); - if (file.isFile() && - Messages.showOkCancelDialog(wholePanel, "File \'" + file + "\' already exist. Do you want to overwrite it?", "Warning", - Messages.getQuestionIcon()) != Messages.OK) { - return; - } - - JDOMUtil.writeParent(element, file, "\n"); - } - catch (IOException e1) { - LOG.error(e1); - } - }); - } - - @Override - public void doImport() { - final FileChooserDescriptor descriptor = new FileChooserDescriptor(true, false, false, false, false, false) { - @Override - public boolean isFileSelectable(VirtualFile file) { - return file.getFileType().equals(StdFileTypes.XML); - } - }; - descriptor.setDescription("Choose profile file"); - FileChooser.chooseFile(descriptor, getProject(), wholePanel, null, file -> { - if (file != null) { - final InspectionProfileImpl profile; - try { - profile = importInspectionProfile(JDOMUtil.load(file.getInputStream()), myApplicationProfileManager, getProject()); - final SingleInspectionProfilePanel existed = getProfilePanel(profile); - if (existed != null) { - if (Messages.showOkCancelDialog(wholePanel, "Profile with name \'" + - profile.getName() + - "\' already exists. Do you want to overwrite it?", "Warning", - Messages.getInformationIcon()) != Messages.OK) { - return; - } - myProfiles.getProfilesComboBox().removeProfile(existed.getProfile()); - myPanels.remove(existed); - } - InspectionProfileModifiableModel model = new InspectionProfileModifiableModel(profile); - model.setModified(true); - addProfile(model); - selectProfile(model); - } - catch (JDOMException | InvalidDataException | IOException e) { - LOG.error(e); - } - } - }); - } - }).build(); - - - toolbar.setLayout(new GridBagLayout()); - final JLabel headerTitleLabel = new JLabel(HEADER_TITLE); - headerTitleLabel.setBorder(IdeBorderFactory.createEmptyBorder(10, 0, 0, 0)); - toolbar.add(headerTitleLabel, new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.NONE, - JBUI.emptyInsets(), 0, 0)); - - toolbar.add(myProfiles, new GridBagConstraints(1, 0, 1, 1, 0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.VERTICAL, - JBUI.insetsLeft(6), 0, 0)); - - toolbar.add(withBorderOnTop(manageButton), new GridBagConstraints(2, 0, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.VERTICAL, - JBUI.insetsLeft(10), 0, 0)); - - toolbar.add(myAuxiliaryRightPanel, new GridBagConstraints(3, 0, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, - JBUI.insetsLeft(15), 0, 0)); - + myAbstractSchemesPanel = new InspectionProfileSchemesPanel(getProject(), + myApplicationProfileManager, + myProjectProfileManager, + this); + wholePanel.add(myAbstractSchemesPanel, BorderLayout.NORTH); return wholePanel; } @@ -497,26 +214,17 @@ public abstract class InspectionToolsConfigurable extends BaseConfigurable if (!Comparing.equal(selectedProfile, currentProfile)) { return true; } - for (SingleInspectionProfilePanel panel : myPanels) { + final InspectionProfileSchemesModel model = myAbstractSchemesPanel.getModel(); + for (SingleInspectionProfilePanel panel : model.getProfilePanels()) { if (panel.isModified()) return true; } - return getProfiles().size() != myPanels.size() || !myDeletedProfiles.isEmpty(); + return model.hasDeletedProfiles() || + InspectionProfileSchemesModel.getSortedProfiles(myApplicationProfileManager, myProjectProfileManager).size() != model.getSize(); } @Override public void apply() { - for (InspectionProfileModifiableModel profile : myDeletedProfiles) { - profile.getProfileManager().deleteProfile(profile.getSource()); - } - myDeletedProfiles.clear(); - - SingleInspectionProfilePanel selectedPanel = getSelectedPanel(); - for (SingleInspectionProfilePanel panel : myPanels) { - panel.apply(); - if (setActiveProfileAsDefaultOnApply() && panel == selectedPanel) { - applyRootProfile(panel.getProfile().getName(), panel.getProfile().isProjectLevel()); - } - } + myAbstractSchemesPanel.apply(); } protected abstract void applyRootProfile(@NotNull String name, boolean isProjectLevel); @@ -531,22 +239,12 @@ public abstract class InspectionToolsConfigurable extends BaseConfigurable } private void doReset() { - myDeletedProfiles.clear(); disposeUIResources(); - final Collection profiles = getProfiles(); - final List modifiableProfiles = new ArrayList<>(profiles.size()); - for (InspectionProfileImpl profile : profiles) { - InspectionProfileModifiableModel inspectionProfile = new InspectionProfileModifiableModel(profile); - modifiableProfiles.add(inspectionProfile); - final SingleInspectionProfilePanel panel = createPanel(inspectionProfile); - myPanels.add(panel); - myProfilePanelHolder.add(panel); - } - myProfiles.getProfilesComboBox().reset(modifiableProfiles); - myAuxiliaryRightPanel.showDescription(getSelectedObject().getDescription()); - final InspectionProfileImpl inspectionProfile = getCurrentProfile(); - myProfiles.getProfilesComboBox().selectProfile(inspectionProfile); - showProfile(inspectionProfile); + myAbstractSchemesPanel.reset(); + final InspectionProfileModifiableModel currentModifiableModel = myAbstractSchemesPanel.getModel().getModifiableModelFor(getCurrentProfile()); + myAbstractSchemesPanel.selectScheme(currentModifiableModel); + showProfile(currentModifiableModel); + final SingleInspectionProfilePanel panel = getSelectedPanel(); if (panel != null) { panel.setVisible(true);//make sure that UI was initialized @@ -556,7 +254,7 @@ public abstract class InspectionToolsConfigurable extends BaseConfigurable } } - private SingleInspectionProfilePanel createPanel(InspectionProfileModifiableModel profile) { + public SingleInspectionProfilePanel createPanel(InspectionProfileModifiableModel profile) { return new SingleInspectionProfilePanel(myProjectProfileManager, profile) { @Override protected boolean accept(InspectionToolWrapper entry) { @@ -565,90 +263,39 @@ public abstract class InspectionToolsConfigurable extends BaseConfigurable }; } - private boolean isDeleteEnabled(@NotNull InspectionProfileImpl inspectionProfile) { - boolean projectProfileFound = false; - boolean ideProfileFound = false; - - for (InspectionProfileImpl profile : myProfiles.getProfilesComboBox().getProfiles()) { - if (inspectionProfile == profile) continue; - final boolean isProjectProfile = profile.getProfileManager() == myProjectProfileManager; - projectProfileFound |= isProjectProfile; - ideProfileFound |= !isProjectProfile; - - if (ideProfileFound && projectProfileFound) break; - } - - return inspectionProfile.getProfileManager() == myProjectProfileManager ? projectProfileFound : ideProfileFound; - } - - protected Collection getProfiles() { - final Collection result = new ArrayList<>(); - result.addAll(new TreeSet<>(myApplicationProfileManager.getProfiles())); - result.addAll(myProjectProfileManager.getProfiles()); - return result; - } - @Override public void disposeUIResources() { - for (SingleInspectionProfilePanel panel : myPanels) { - panel.disposeUI(); - } - myPanels.clear(); if (mySelectionAlarm != null) { Disposer.dispose(mySelectionAlarm); mySelectionAlarm = null; } + myProfilePanelHolder.removeAll(); + myAbstractSchemesPanel.getModel().disposeUI(); } @Override public void selectProfile(InspectionProfileImpl profile) { - myProfiles.getProfilesComboBox().selectProfile(profile); - } - - private SingleInspectionProfilePanel getProfilePanel(InspectionProfileImpl profile) { - for (SingleInspectionProfilePanel panel : myPanels) { - if (panel.getProfile().equals(profile)) { - return panel; - } - } - return null; + final InspectionProfileModifiableModel modifiableModel = myAbstractSchemesPanel.getModel().getModifiableModelFor(profile); + showProfile(modifiableModel); } @Override public void selectInspectionTool(String selectedToolShortName) { - final InspectionProfileImpl inspectionProfile = getSelectedObject(); - final SingleInspectionProfilePanel panel = getProfilePanel(inspectionProfile); - LOG.assertTrue(panel != null, "No settings panel for: " + inspectionProfile + "; " + configuredProfiles()); + final InspectionProfileModifiableModel inspectionProfile = getSelectedObject(); + final SingleInspectionProfilePanel panel = myAbstractSchemesPanel.getModel().getProfilePanel(inspectionProfile); panel.selectInspectionTool(selectedToolShortName); } @Override public void selectInspectionGroup(String[] groupPath) { - getProfilePanel(getSelectedObject()).selectInspectionGroup(groupPath); + myAbstractSchemesPanel.getModel().getProfilePanel(getSelectedObject()).selectInspectionGroup(groupPath); } - protected SingleInspectionProfilePanel getSelectedPanel() { - final InspectionProfileImpl inspectionProfile = getSelectedObject(); - return getProfilePanel(inspectionProfile); - } - - private String configuredProfiles() { - return "configured profiles: " + StringUtil.join(myPanels.stream().map(p -> p.getProfile().getName()).collect(Collectors.toList()), ", "); - } - - private boolean hasName(@NotNull final String name, boolean shared) { - for (SingleInspectionProfilePanel p : myPanels) { - if (name.equals(p.getProfile().getName()) && shared == p.getProfile().isProjectLevel()) { - return true; - } - } - return false; - } @NotNull @Override public InspectionProfileModifiableModel getSelectedObject() { - return myProfiles.getProfilesComboBox().getSelectedProfile(); + return myAbstractSchemesPanel.getSelectedScheme(); } @Override @@ -657,8 +304,20 @@ public abstract class InspectionToolsConfigurable extends BaseConfigurable return panel == null ? null : panel.getPreferredFocusedComponent(); } - private void showProfile(InspectionProfileImpl profile) { - final SingleInspectionProfilePanel panel = getProfilePanel(profile); + void removeProfilePanel(SingleInspectionProfilePanel profilePanel) { + myProfilePanelHolder.remove(profilePanel); + } + + private SingleInspectionProfilePanel getSelectedPanel() { + final InspectionProfileModifiableModel inspectionProfile = getSelectedObject(); + return myAbstractSchemesPanel.getModel().getProfilePanel(inspectionProfile); + } + + private void showProfile(InspectionProfileModifiableModel profile) { + final SingleInspectionProfilePanel panel = myAbstractSchemesPanel.getModel().getProfilePanel(profile); + if (!ArrayUtil.contains(panel, myAbstractSchemesPanel.getModel().getProfilePanels())) { + myProfilePanelHolder.add(panel); + } for (Component component : myProfilePanelHolder.getComponents()) { component.setVisible(component == panel); } diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/ManageButton.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/ManageButton.java deleted file mode 100644 index 1cde43d3ee31..000000000000 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/ManageButton.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright 2000-2015 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.profile.codeInspection.ui.header; - -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.actionSystem.DefaultActionGroup; -import com.intellij.openapi.actionSystem.ex.ComboBoxAction; -import com.intellij.openapi.project.DumbAware; -import org.jetbrains.annotations.NotNull; - -import javax.swing.*; - -/** - * @author Dmitry Batkovich - */ -public class ManageButton extends ComboBoxAction implements DumbAware { - - private final ManageButtonBuilder myBuilder; - - public ManageButton(final ManageButtonBuilder builder) { - myBuilder = builder; - getTemplatePresentation().setText("Manage"); - setSmallVariant(false); - } - - public JComponent build() { - return createCustomComponent(getTemplatePresentation()); - } - - @NotNull - @Override - protected DefaultActionGroup createPopupActionGroup(JComponent button) { - DefaultActionGroup group = new DefaultActionGroup(); - - group.add(new ShareWithTeamCheckBoxAction()); - group.addSeparator(); - - group.add(new CopyAction()); - group.add(new RenameAction()); - group.add(new DeleteAction()); - group.add(new EditDescriptionAction(myBuilder.hasDescription())); - group.add(new ExportAction()); - group.addSeparator(); - - group.add(new ImportAction()); - - return group; - } - - @Override - protected boolean shouldShowDisabledActions() { - return true; - } - - private class ShareWithTeamCheckBoxAction extends AnAction implements DumbAware { - @Override - public void update(AnActionEvent e) { - final boolean isProjectLevel = myBuilder.isProjectLevel(); - e.getPresentation().setText(isProjectLevel ? "Copy as Global" : "Copy to Project"); - e.getPresentation().setEnabled(myBuilder.canChangeProfileLevel()); - } - - @Override - public void actionPerformed(AnActionEvent e) { - myBuilder.copyToAnotherLevel(); - } - } - - private class CopyAction extends AnAction implements DumbAware { - public CopyAction() { - super("Copy"); - } - - @Override - public void actionPerformed(AnActionEvent e) { - myBuilder.copy(); - } - } - - private class RenameAction extends AnAction implements DumbAware { - public RenameAction() { - super("Rename"); - } - - @Override - public void actionPerformed(AnActionEvent e) { - myBuilder.rename(); - } - } - - private class DeleteAction extends AnAction implements DumbAware { - public DeleteAction() { - super("Delete"); - } - - @Override - public void actionPerformed(AnActionEvent e) { - myBuilder.delete(); - } - - @Override - public void update(AnActionEvent e) { - e.getPresentation().setEnabledAndVisible(myBuilder.canDelete()); - } - } - - private class EditDescriptionAction extends AnAction implements DumbAware { - public EditDescriptionAction(boolean hasDescription) { - super(hasDescription ? "Edit description" : "Add description"); - } - - @Override - public void actionPerformed(AnActionEvent e) { - myBuilder.editDescription(); - } - - @Override - public void update(@NotNull AnActionEvent e) { - e.getPresentation().setEnabledAndVisible(myBuilder.canEditDescription()); - } - } - - private class ExportAction extends AnAction implements DumbAware { - public ExportAction() { - super("Export..."); - } - - @Override - public void actionPerformed(AnActionEvent e) { - myBuilder.export(); - } - } - - private class ImportAction extends AnAction implements DumbAware { - public ImportAction() { - super("Import..."); - } - - @Override - public void actionPerformed(AnActionEvent e) { - myBuilder.doImport(); - } - } -} diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/ManageButtonBuilder.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/ManageButtonBuilder.java deleted file mode 100644 index eb330800f06d..000000000000 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/ManageButtonBuilder.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2000-2015 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.profile.codeInspection.ui.header; - -/** - * @author Dmitry Batkovich - */ -public interface ManageButtonBuilder { - boolean isProjectLevel(); - - boolean canChangeProfileLevel(); - - void copyToAnotherLevel(); - - void copy(); - - void rename(); - - boolean canDelete(); - - void delete(); - - boolean canEditDescription(); - - void editDescription(); - - boolean hasDescription(); - - void export(); - - void doImport(); -} diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/ProfilesChooser.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/ProfilesChooser.java deleted file mode 100644 index 4a279d600077..000000000000 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/ProfilesChooser.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2000-2016 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.profile.codeInspection.ui.header; - -import com.intellij.codeInspection.ex.InspectionProfileImpl; -import com.intellij.codeInspection.ex.InspectionProfileModifiableModel; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.wm.IdeFocusManager; -import com.intellij.ui.IdeBorderFactory; -import com.intellij.util.ui.JBUI; - -import javax.swing.*; -import java.awt.*; - -/** - * @author Dmitry Batkovich - */ -public abstract class ProfilesChooser extends JPanel { - private static final String COMBO_CARD = "combo.card"; - private static final String EDIT_CARD = "edit.card"; - - private final ProfilesComboBox myProfilesComboBox; - private final CardLayout myCardLayout; - private final ValidatedTextField mySubmitNameComponent; - private final SaveInputComponentValidator.Wrapper mySaveListener; - private final JPanel myComboBoxPanel; - private final Project myProject; - - public ProfilesChooser(Project project) { - myProject = project; - myComboBoxPanel = new JPanel(); - - myCardLayout = new CardLayout(); - myComboBoxPanel.setLayout(myCardLayout); - setBorder(IdeBorderFactory.createEmptyBorder(JBUI.insets(4, 0, 6, 0))); - myProfilesComboBox = new ProfilesComboBox() { - @Override - protected void onProfileChosen(InspectionProfileImpl inspectionProfile) { - ProfilesChooser.this.onProfileChosen(inspectionProfile); - } - }; - myComboBoxPanel.add(myProfilesComboBox, COMBO_CARD); - - mySaveListener = new SaveInputComponentValidator.Wrapper(); - mySubmitNameComponent = new ValidatedTextField(mySaveListener); - myComboBoxPanel.add(mySubmitNameComponent, EDIT_CARD); - - //noinspection GtkPreferredJComboBoxRenderer - setLayout(new BorderLayout()); - add(mySubmitNameComponent.getHintLabel(), BorderLayout.NORTH); - add(myComboBoxPanel, BorderLayout.CENTER); - - showComboBoxCard(); - } - - ProfilesComboBox getProfilesComboBox() { - return myProfilesComboBox; - } - - protected abstract void onProfileChosen(InspectionProfileImpl profile); - - void showEditCard(final String initialValue, final SaveInputComponentValidator inputValidator) { - mySaveListener.setDelegate(inputValidator); - mySubmitNameComponent.setText(initialValue); - myCardLayout.show(myComboBoxPanel, EDIT_CARD); - ApplicationManager.getApplication().invokeLater(() -> IdeFocusManager.getInstance(myProject).requestFocus(mySubmitNameComponent, true)); - } - - void showComboBoxCard() { - myCardLayout.show(myComboBoxPanel, COMBO_CARD); - } -} diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/ProfilesComboBox.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/ProfilesComboBox.java deleted file mode 100644 index 950b26251264..000000000000 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/ProfilesComboBox.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright 2000-2016 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.profile.codeInspection.ui.header; - -import com.intellij.codeInspection.ex.InspectionProfileImpl; -import com.intellij.icons.AllIcons; -import com.intellij.openapi.ui.ComboBox; -import com.intellij.ui.IdeBorderFactory; -import com.intellij.ui.ListCellRendererWrapper; -import com.intellij.ui.SortedComboBoxModel; -import com.intellij.ui.TitledSeparator; -import com.intellij.util.ui.UIUtil; -import org.jetbrains.annotations.NotNull; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.Collection; -import java.util.Comparator; -import java.util.List; - -/** - * @author Dmitry Batkovich - */ -public abstract class ProfilesComboBox extends ComboBox { - private static final String PROJECT_LEVEL_SEPARATOR_TEXT = "Project Level"; - private static final String GLOBAL_LEVEL_SEPARATOR_TEXT = "Global Level"; - - private SortedComboBoxModel myComboModel; - private T myFirstGlobalProfile; - - public ProfilesComboBox() { - myComboModel = new SortedComboBoxModel<>(Comparator.comparing(T::isProjectLevel) - .reversed() - .thenComparing(InspectionProfileImpl::getDisplayName)); - setModel(myComboModel); - //noinspection GtkPreferredJComboBoxRenderer - setRenderer(new ListCellRenderer() { - ListCellRendererWrapper baseRenderer = new ListCellRendererWrapper() { - @Override - public void customize(final JList list, - final InspectionProfileImpl value, - final int index, - final boolean selected, - final boolean hasFocus) { - if (index == -1) { - setIcon(value.isProjectLevel() ? AllIcons.General.ProjectSettings : AllIcons.General.Settings); - } - setText(value.getDisplayName()); - } - }; - - @Override - public Component getListCellRendererComponent(JList list, - InspectionProfileImpl o, - int index, - boolean isSelected, - boolean cellHasFocus) { - TitledSeparator separator = null; - if (index != -1) { - if (!o.isProjectLevel()) { - if (o == myFirstGlobalProfile) { - separator = new TitledSeparator(GLOBAL_LEVEL_SEPARATOR_TEXT); - } - } - else { - if (o == myComboModel.get(0)) { - separator = new TitledSeparator(PROJECT_LEVEL_SEPARATOR_TEXT); - } - } - } - Component renderedComponent = baseRenderer.getListCellRendererComponent(list, o, index, isSelected, cellHasFocus); - if (separator == null) { - return renderedComponent; - } - UIUtil.applyStyle(UIUtil.ComponentStyle.MINI, separator.getLabel()); - separator.getLabel().setIcon( - separator.getText().equals(PROJECT_LEVEL_SEPARATOR_TEXT) ? AllIcons.General.ProjectSettings : AllIcons.General.Settings); - separator.setBackground(renderedComponent.getBackground()); - separator.setBorder(IdeBorderFactory.createEmptyBorder(2, 2, 0, 2)); - JPanel p = new JPanel(); - p.setLayout(new BorderLayout()); - p.add(separator, BorderLayout.NORTH); - p.add(renderedComponent, BorderLayout.CENTER); - p.setBackground(renderedComponent.getBackground()); - return p; - } - }); - addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - final InspectionProfileImpl profile = getSelectedProfile(); - if (profile != null) { - onProfileChosen(profile); - } - } - }); - } - - protected abstract void onProfileChosen(final InspectionProfileImpl inspectionProfile); - - public void selectProfile(InspectionProfileImpl inspectionProfile) { - setSelectedItem(inspectionProfile); - } - - public void reset(final Collection profiles) { - myComboModel.clear(); - for (T profile : profiles) { - myComboModel.add(profile); - } - findFirstGlobalProfile(); - setSelectedIndex(0); - resort(); - } - - void removeProfile(T profile) { - myComboModel.remove(profile); - if (!profile.isProjectLevel() && profile == myFirstGlobalProfile) { - findFirstGlobalProfile(); - } - } - - public void addProfile(T inspectionProfile) { - myComboModel.add(inspectionProfile); - if (!inspectionProfile.isProjectLevel()) { - findFirstGlobalProfile(); - } - } - - T getSelectedProfile() { - return myComboModel.getSelectedItem(); - } - - @NotNull - List getProfiles() { - return myComboModel.getItems(); - } - - private void findFirstGlobalProfile() { - myFirstGlobalProfile = null; - for (T profile : getProfiles()) { - if (!profile.isProjectLevel()) { - myFirstGlobalProfile = profile; - break; - } - } - } - - public void resort() { - myComboModel.setAll(myComboModel.getItems()); - findFirstGlobalProfile(); - } -} diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/SaveInputComponentValidator.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/SaveInputComponentValidator.java deleted file mode 100644 index 5d002b32cde7..000000000000 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/SaveInputComponentValidator.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2000-2014 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.profile.codeInspection.ui.header; - -import org.jetbrains.annotations.NotNull; - -/** -* @author Dmitry Batkovich -*/ -public interface SaveInputComponentValidator { - - void doSave(@NotNull String text); - - boolean checkValid(@NotNull String text); - - void cancel(); - - class Wrapper implements SaveInputComponentValidator { - private SaveInputComponentValidator myDelegate; - private boolean myActive; - - public void setDelegate(SaveInputComponentValidator delegate) { - myDelegate = delegate; - myActive = true; - } - - @Override - public void doSave(@NotNull String text) { - text = text.trim(); - if (myActive && myDelegate != null) { - myDelegate.doSave(text); - myActive = false; - } - } - - @Override - public boolean checkValid(@NotNull String text) { - return myActive && myDelegate != null && myDelegate.checkValid(text.trim()); - } - - @Override - public void cancel() { - if (myActive && myDelegate != null) { - myDelegate.cancel(); - } - } - } -} diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/ValidatedTextField.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/ValidatedTextField.java deleted file mode 100644 index 2925bd8681a7..000000000000 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/ValidatedTextField.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright 2000-2014 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.profile.codeInspection.ui.header; - -import com.intellij.ui.JBColor; -import com.intellij.ui.components.JBTextField; -import com.intellij.util.ui.UIUtil; - -import javax.swing.*; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; -import java.awt.*; -import java.awt.event.*; - -/** - * @author Dmitry Batkovich - */ -public class ValidatedTextField extends JBTextField { - private static final String LABEL_CARD = "label"; - private static final String NO_LABEL_CARD = "no_label"; - - private final SaveInputComponentValidator myInputValidator; - private final JPanel myHintPanel; - - private boolean myIgnoreFocus; - - public ValidatedTextField(final SaveInputComponentValidator inputValidator) { - myInputValidator = inputValidator; - getDocument().addDocumentListener(new DocumentListener() { - @Override - public void insertUpdate(DocumentEvent e) { - changedUpdate(e); - } - - @Override - public void removeUpdate(DocumentEvent e) { - changedUpdate(e); - } - - @Override - public void changedUpdate(DocumentEvent e) { - final boolean isValid = myInputValidator.checkValid(getText()); - final Color color = isValid ? UIUtil.getTextAreaForeground() : JBColor.RED; - if (!color.equals(getForeground())) { - setForeground(color); - } - } - }); - - addFocusListener(new FocusAdapter() { - @Override - public void focusLost(FocusEvent e) { - if (!myIgnoreFocus) { - checkAndApply(); - } - } - }); - - addKeyListener(new KeyAdapter() { - @Override - public void keyPressed(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_ENTER || e.getKeyCode() == KeyEvent.VK_ESCAPE) { - e.consume(); - } - } - - @Override - public void keyReleased(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_ENTER) { - checkAndApply(); - e.consume(); - } else if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { - myIgnoreFocus = true; - myInputValidator.cancel(); - e.consume(); - } - } - }); - - myHintPanel = new JPanel(); - final CardLayout cardLayout = new CardLayout(); - myHintPanel.setLayout(cardLayout); - - JLabel hintLabel = new JLabel("Save: Enter, Cancel: Esc"); - UIUtil.applyStyle(UIUtil.ComponentStyle.SMALL, hintLabel); - hintLabel.setForeground(UIUtil.getLabelDisabledForeground()); - myHintPanel.add(hintLabel, LABEL_CARD); - myHintPanel.add(new JPanel(), NO_LABEL_CARD); - - addComponentListener(new ComponentAdapter() { - @Override - public void componentShown(ComponentEvent e) { - cardLayout.show(myHintPanel, LABEL_CARD); - myIgnoreFocus = false; - } - - @Override - public void componentHidden(ComponentEvent e) { - cardLayout.show(myHintPanel, NO_LABEL_CARD); - } - }); - - cardLayout.show(myHintPanel, NO_LABEL_CARD); - } - - public JPanel getHintLabel() { - return myHintPanel; - } - - private void checkAndApply() { - String text = getText(); - if (text == null) { - text = ""; - } - if (myInputValidator.checkValid(text)) { - myInputValidator.doSave(text); - } - } -} diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index ae5f947e3540..7c8b684e385b 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -981,6 +981,15 @@ schemeClass="com.intellij.psi.codeStyle.CodeStyleScheme" implementationClass="com.intellij.psi.impl.source.codeStyle.CodeStyleSchemeXmlImporter"/> + + +