Merge branch 'db/inspection-profile-ui'

# Conflicts:
#	platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionToolsConfigurable.java
This commit is contained in:
Dmitry Batkovich
2017-02-16 08:35:11 +03:00
29 changed files with 1184 additions and 1463 deletions
@@ -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 = JdomKt.loadElement(mergedText);
@@ -42,7 +42,7 @@ abstract class CodeStyleSchemesActions extends AbstractSchemeActions<CodeStyleSc
private final static String SHARED_IMPORT_SOURCE = ApplicationBundle.message("import.scheme.shared");
protected CodeStyleSchemesActions(@NotNull AbstractSchemesPanel<CodeStyleScheme> schemesPanel) {
protected CodeStyleSchemesActions(@NotNull AbstractSchemesPanel<CodeStyleScheme, ?> schemesPanel) {
super(schemesPanel);
}
@@ -75,8 +75,9 @@ abstract class CodeStyleSchemesActions extends AbstractSchemeActions<CodeStyleSc
@Override
protected void copyToIDE(@NotNull CodeStyleScheme scheme) {
final boolean isProjectScheme = getModel().isProjectScheme(scheme);
String name =
SchemeNameGenerator.getUniqueName(getProjectName(), schemeName -> getModel().containsScheme(schemeName));
SchemeNameGenerator.getUniqueName(getProjectName(), schemeName -> getModel().containsScheme(schemeName, isProjectScheme));
CodeStyleScheme newScheme = getModel().exportProjectScheme(name);
getModel().setUsePerProjectSettings(false);
getModel().selectScheme(newScheme, null);
@@ -76,6 +76,11 @@ public class CodeStyleSchemesModel implements SchemesModel<CodeStyleScheme> {
}
}
@Override
public boolean supportsProjectSchemes() {
return true;
}
public CodeStyleSettings getCloneSettings(final CodeStyleScheme scheme) {
if (!mySettingsToClone.containsKey(scheme)) {
mySettingsToClone.put(scheme, scheme.getCodeStyleSettings().clone());
@@ -210,15 +215,16 @@ public class CodeStyleSchemesModel implements SchemesModel<CodeStyleScheme> {
}
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 +259,8 @@ public class CodeStyleSchemesModel implements SchemesModel<CodeStyleScheme> {
}
@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
@@ -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<CodeStyleScheme> {
public class CodeStyleSchemesPanel extends SimpleSchemesPanel<CodeStyleScheme> {
private final CodeStyleSchemesModel myModel;
@@ -122,9 +122,4 @@ public class CodeStyleSchemesPanel extends AbstractSchemesPanel<CodeStyleScheme>
public SchemesModel<CodeStyleScheme> getModel() {
return myModel;
}
@Override
public boolean supportsProjectSchemes() {
return true;
}
}
@@ -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;
}
@@ -275,6 +276,11 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract
mySomeSchemesDeleted = mySomeSchemesDeleted || !deletedNewlyCreated;
}
@Override
public boolean supportsProjectSchemes() {
return false;
}
private void selectDefaultScheme() {
DefaultColorsScheme defaultScheme =
@@ -40,7 +40,7 @@ import java.util.List;
public abstract class ColorSchemeActions extends AbstractSchemeActions<EditorColorsScheme> {
protected ColorSchemeActions(@NotNull AbstractSchemesPanel<EditorColorsScheme> schemesPanel) {
protected ColorSchemeActions(@NotNull AbstractSchemesPanel<EditorColorsScheme, ?> schemesPanel) {
super(schemesPanel);
}
@@ -69,7 +69,7 @@ public abstract class ColorSchemeActions extends AbstractSchemeActions<EditorCol
name -> {
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);
@@ -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<EditorColorsScheme> implements SkipSelfSearchComponent {
public class SchemesPanel extends SimpleSchemesPanel<EditorColorsScheme> implements SkipSelfSearchComponent {
private final ColorAndFontOptions myOptions;
private final EventDispatcher<ColorAndFontSettingsListener> myDispatcher = EventDispatcher.create(ColorAndFontSettingsListener.class);
@@ -108,9 +108,4 @@ public class SchemesPanel extends AbstractSchemesPanel<EditorColorsScheme> imple
public SchemesModel<EditorColorsScheme> getModel() {
return myOptions;
}
@Override
public boolean supportsProjectSchemes() {
return false;
}
}
@@ -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<T extends Scheme> extends AbstractSchemesPanel<T, JPanel> {
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<T>)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<T>)getActions())).setDescription(getSelectedScheme(), myDescriptionTextField.getText());
showDescription();
}
private static class DescriptionLabel extends MultiLineLabel {
@@ -31,7 +31,7 @@ import java.util.List;
/**
* <p>
* 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 <T> The actual scheme type.
* @see AbstractSchemesPanel
* @see SimpleSchemesPanel
* @see SchemesModel
* @see SchemeImporter
* @see SchemeExporter
@@ -48,9 +48,9 @@ public abstract class AbstractSchemeActions<T extends Scheme> {
private final Collection<String> mySchemeImportersNames;
private final Collection<String> mySchemeExporterNames;
private final AbstractSchemesPanel<T> mySchemesPanel;
protected final AbstractSchemesPanel<T, ?> mySchemesPanel;
protected AbstractSchemeActions(@NotNull AbstractSchemesPanel<T> schemesPanel) {
protected AbstractSchemeActions(@NotNull AbstractSchemesPanel<T, ?> schemesPanel) {
mySchemesPanel = schemesPanel;
mySchemeImportersNames = getSchemeImportersNames();
mySchemeExporterNames = getSchemeExporterNames();
@@ -75,7 +75,7 @@ public abstract class AbstractSchemeActions<T extends Scheme> {
public final Collection<AnAction> getActions() {
List<AnAction> actions = new ArrayList<>();
if (mySchemesPanel.supportsProjectSchemes()) {
if (mySchemesPanel.getModel().supportsProjectSchemes()) {
actions.add(new CopyToProjectAction());
actions.add(new CopyToIDEAction());
actions.add(new Separator());
@@ -84,6 +84,7 @@ public abstract class AbstractSchemeActions<T extends Scheme> {
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<T extends Scheme> {
}
});
}
addAdditionalActions(actions);
return actions;
}
@@ -195,10 +195,11 @@ public abstract class AbstractSchemeActions<T extends Scheme> {
T currentScheme = getCurrentScheme();
if (currentScheme != null) {
mySchemesPanel.cancelEdit();
final boolean isProjectScheme = mySchemesPanel.getModel().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();
@@ -414,7 +415,7 @@ public abstract class AbstractSchemeActions<T extends Scheme> {
*/
protected abstract Class<T> getSchemeType();
public final AbstractSchemesPanel<T> getSchemesPanel() {
public final AbstractSchemesPanel<T, ?> getSchemesPanel() {
return mySchemesPanel;
}
}
@@ -42,12 +42,11 @@ import java.util.Collection;
* @see AbstractSchemeActions
* @see SchemesModel
*/
public abstract class AbstractSchemesPanel<T extends Scheme> extends JPanel {
private SchemesCombo<T> mySchemesCombo;
public abstract class AbstractSchemesPanel<T extends Scheme, InfoComponent extends JComponent> extends JPanel {
private EditableSchemesCombo<T> mySchemesCombo;
private AbstractSchemeActions<T> myActions;
private JComponent myToolbar;
private JLabel myInfoLabel;
protected InfoComponent myInfoComponent;
public AbstractSchemesPanel() {
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
@@ -57,15 +56,15 @@ public abstract class AbstractSchemesPanel<T extends Scheme> 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);
mySchemesCombo = new EditableSchemesCombo<T>(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<T extends Scheme> 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<T extends Scheme> extends JPanel {
return mySchemesCombo.getSelectedScheme();
}
public final void selectScheme(@Nullable T scheme) {
public void selectScheme(@Nullable T scheme) {
mySchemesCombo.selectScheme(scheme);
}
@@ -139,19 +137,21 @@ public abstract class AbstractSchemesPanel<T extends Scheme> 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<T> getActions() {
return myActions;
}
@NotNull
protected abstract InfoComponent createInfoComponent();
protected String getTitle() {
return ApplicationBundle.message("editbox.scheme.name");
}
/**
* @return Schemes model implementation.
* @see SchemesModel
@@ -166,13 +166,6 @@ public abstract class AbstractSchemesPanel<T extends Scheme> 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(),
@@ -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<T extends Scheme> extends AbstractSchemeActions<T> {
protected DescriptionAwareSchemeActions(@NotNull AbstractDescriptionAwareSchemesPanel<T> 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<AnAction> 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<T>) mySchemesPanel).editDescription(getDescription(getSchemesPanel().getSelectedScheme()));
}
});
}
@Override
protected void onSchemeChanged(@Nullable T scheme) {
if (scheme != null) {
((AbstractDescriptionAwareSchemesPanel<T>) mySchemesPanel).showDescription();
}
}
}
@@ -0,0 +1,222 @@
/*
* 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<T extends Scheme> {
// 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<T> myComboBox;
private JPanel myRootPanel;
private AbstractSchemesPanel<T, ?> 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<T, ?> 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<T> 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<T> selectedItem = myComboBox.getSelectedItem();
if (selectedItem != null) {
myNameEditorField.setText(selectedItem.getSchemeName());
}
}
public void updateSelected() {
myComboBox.repaint();
}
private void stopEdit() {
String newName = myNameEditorField.getText();
SchemesCombo.MySchemeListItem<T> 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<T>() {
@Override
protected boolean supportsProjectSchemes() {
return mySchemesPanel.getModel().supportsProjectSchemes();
}
@Override
protected boolean isProjectScheme(@NotNull T scheme) {
return mySchemesPanel.getModel().isProjectScheme(scheme);
}
@NotNull
@Override
protected SimpleTextAttributes getSchemeAttributes(T scheme) {
SchemesModel<T> 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<T> 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;
}
}
@@ -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,193 +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.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<T extends Scheme> {
// region Message constants
public abstract class SchemesCombo<T extends Scheme> extends ComboBox<SchemesCombo.MySchemeListItem<T>> {
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<MySchemeListItem<T>> myComboBox;
private JPanel myRootPanel;
private AbstractSchemesPanel<T> 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<T> 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<T> selectedItem = getSelectedItem();
if (selectedItem != null && !currName.equals(selectedItem.getSchemeName())) {
String validationMessage = validateSchemeName(currName);
if (validationMessage != null) {
mySchemesPanel.showInfo(validationMessage, MessageType.ERROR);
return;
}
}
showHint();
}
private void showHint() {
mySchemesPanel.showInfo(EDITING_HINT, MessageType.INFO);
}
private void revertSchemeName() {
MySchemeListItem<T> selectedItem = getSelectedItem();
if (selectedItem != null) {
myNameEditorField.setText(selectedItem.getSchemeName());
}
}
public void updateSelected() {
myComboBox.repaint();
}
private void stopEdit() {
String newName = myNameEditorField.getText();
MySchemeListItem<T> selectedItem = getSelectedItem();
if (selectedItem != null) {
if (newName.equals(selectedItem.getSchemeName())) {
cancelEdit();
return;
}
String validationMessage = validateSchemeName(newName);
if (validationMessage != null) {
mySchemesPanel.showInfo(validationMessage, MessageType.ERROR);
}
else {
cancelEdit();
if (selectedItem.getScheme() != null) {
mySchemesPanel.getActions().renameScheme(selectedItem.getScheme(), newName);
}
}
}
}
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<T> item) {
SchemesModel<T> 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<T> schemes) {
myComboBoxModel.removeAllElements();
SchemesModel<T> model = mySchemesPanel.getModel();
if (mySchemesPanel.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<T> model = (MyComboBoxModel<T>)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<T> item = getSelectedItem();
return item != null ? item.getScheme() : null;
}
@Nullable
public SchemesCombo.MySchemeListItem<T> 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<T> schemes, Predicate<T> filter) {
for (T scheme : schemes) {
if (filter.test(scheme)) {
myComboBoxModel.addElement(new MySchemeListItem<>(scheme));
((MyComboBoxModel<T>) getModel()).addElement(new MySchemeListItem<>(scheme));
}
}
}
static class MySchemeListItem<T extends Scheme> {
private @Nullable T myScheme;
public MySchemeListItem(@Nullable T scheme) {
myScheme = scheme;
}
@Nullable
public String getSchemeName() {
return myScheme != null ? myScheme.getName() : null;
}
@Nullable
public T getScheme() {
return myScheme;
}
@NotNull
public String getPresentableText() {
return myScheme != null ? SchemeManager.getDisplayName(myScheme) : "";
}
public boolean isSeparator() {
return false;
}
}
private class MyListCellRenderer extends ColoredListCellRenderer<MySchemeListItem<T>> {
private ListCellRendererWrapper<MySchemeListItem> myWrapper = new ListCellRendererWrapper<MySchemeListItem>() {
@Override
@@ -244,10 +154,10 @@ public class SchemesCombo<T extends Scheme> {
boolean hasFocus) {
T scheme = value.getScheme();
if (scheme != null) {
append(value.getPresentableText(), getSchemeAttributes(value));
if (mySchemesPanel.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);
}
}
@@ -255,33 +165,18 @@ public class SchemesCombo<T extends Scheme> {
}
}
@Nullable
public T getSelectedScheme() {
MySchemeListItem<T> item = getSelectedItem();
return item != null ? item.getScheme() : null;
}
@Nullable
public MySchemeListItem<T> 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<T extends Scheme> extends DefaultComboBoxModel<MySchemeListItem<T>> {
@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<T> {
private String myTitle;
public MySeparatorItem(@NotNull String title) {
@@ -300,55 +195,4 @@ public class SchemesCombo<T extends Scheme> {
return myTitle;
}
}
private static class MySchemeListItem<T extends Scheme> {
private @Nullable T myScheme;
public MySchemeListItem(@Nullable T scheme) {
myScheme = scheme;
}
@Nullable
public String getSchemeName() {
return myScheme != null ? myScheme.getName() : null;
}
@Nullable
public T getScheme() {
return myScheme;
}
@NotNull
public String getPresentableText() {
return myScheme != null ? SchemeManager.getDisplayName(myScheme) : "";
}
public boolean isSeparator() {
return false;
}
}
@Nullable
public String validateSchemeName(@NotNull String name) {
if (name.isEmpty()) {
return EMPTY_NAME_MESSAGE;
}
else if (mySchemesPanel.getModel().containsScheme(name)) {
return NAME_ALREADY_EXISTS_MESSAGE;
}
return null;
}
private class MyComboBoxModel extends DefaultComboBoxModel<MySchemeListItem<T>> {
@Override
public void setSelectedItem(Object anObject) {
if (anObject instanceof MySchemeListItem && ((MySchemeListItem)anObject).isSeparator()) {
return;
}
super.setSelectedItem(anObject);
}
}
}
@@ -61,9 +61,11 @@ public interface SchemesModel<T extends Scheme> {
/**
* @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.
@@ -73,4 +75,11 @@ public interface SchemesModel<T extends Scheme> {
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();
}
@@ -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<CodeStyleScheme> {
public class SerializableSchemeExporter extends SchemeExporter<Scheme> {
@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
@@ -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<T extends Scheme> extends AbstractSchemesPanel<T, JLabel> {
@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);
}
}
@@ -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<InspectionProfileImpl> profilesCombo) {
return new ExternalProfilesComboboxAwareInspectionToolsConfigurable(projectProfileManager, profilesCombo) {
@Override
protected boolean acceptTool(InspectionToolWrapper entry) {
@@ -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;
@@ -34,17 +34,16 @@ 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.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;
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);
@@ -105,20 +104,25 @@ 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<InspectionProfileImpl> profiles = (ProfilesComboBox<InspectionProfileImpl>)panel.myBrowseProfilesCombo.getComboBox();
final SchemesCombo<InspectionProfileImpl> profiles = (SchemesCombo<InspectionProfileImpl>)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
final InspectionProfile profile = (InspectionProfile)profiles.getSelectedItem();
final InspectionProfile profile = profiles.getSelectedScheme();
final boolean canExecute = profile != null && profile.isExecutable(project);
dialog.setOKActionEnabled(canExecute);
}
@@ -127,7 +131,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 +140,44 @@ 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<InspectionProfileImpl> profilesCombo) {
return new ExternalProfilesComboboxAwareInspectionToolsConfigurable(projectProfileManager, profilesCombo);
}
protected static class ExternalProfilesComboboxAwareInspectionToolsConfigurable extends InspectionToolsConfigurable {
private final ProfilesComboBox<InspectionProfileImpl> myProfilesCombo;
private final SchemesCombo<InspectionProfileImpl> myProfilesCombo;
private String mySelectedName;
private boolean mySelectedIsProjectProfile;
public ExternalProfilesComboboxAwareInspectionToolsConfigurable(@NotNull ProjectInspectionProfileManager projectProfileManager, ProfilesComboBox profilesCombo) {
public ExternalProfilesComboboxAwareInspectionToolsConfigurable(@NotNull ProjectInspectionProfileManager projectProfileManager, SchemesCombo<InspectionProfileImpl> 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<InspectionProfileImpl> profilesCombo,
InspectionProfileManager inspectionProfileManager,
InspectionProjectProfileManager inspectionProjectProfileManager,
InspectionManagerEx inspectionManager) {
InspectionProfileImpl selectedProfile = getProfileToUse(inspectionManager.getProject(), inspectionProfileManager, inspectionProjectProfileManager);
List<InspectionProfileImpl> profiles = new ArrayList<>();
profiles.addAll(inspectionProfileManager.getProfiles());
profiles.addAll(inspectionProjectProfileManager.getProfiles());
profilesCombo.reset(profiles);
profilesCombo.selectProfile(selectedProfile);
private void reloadProfiles(SchemesCombo<InspectionProfileImpl> profilesCombo,
InspectionProfileManager appProfileManager,
InspectionProjectProfileManager projectProfileManager,
Project project) {
profilesCombo.resetSchemes(InspectionProfileSchemesModel.getSortedProfiles(appProfileManager, projectProfileManager));
InspectionProfileImpl selectedProfile = getProfileToUse(project, appProfileManager, projectProfileManager);
profilesCombo.selectScheme(selectedProfile);
}
@NotNull
@@ -215,10 +205,21 @@ public class CodeInspectionAction extends BaseAnalysisAction {
public JPanel myAdditionalPanel;
private void createUIComponents() {
myBrowseProfilesCombo = new ComboboxWithBrowseButton(new ProfilesComboBox() {
myBrowseProfilesCombo = new ComboboxWithBrowseButton(new SchemesCombo<InspectionProfileImpl>() {
@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;
}
});
}
@@ -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<NewInspectionProfile> {
@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<NewInspectionProfile> schemeFactory) throws SchemeImportException {
throw new UnsupportedOperationException();
}
@Nullable
@Override
public String getAdditionalImportInfo(@NotNull NewInspectionProfile scheme) {
return null;
}
}
@@ -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<InspectionProfileModifiableModel> {
private final List<SingleInspectionProfilePanel> myProfilePanels = new ArrayList<>();
private final List<InspectionProfileImpl> 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<InspectionProfileModifiableModel> allProfiles = myProfilePanels.stream().map(p -> p.getProfile()).collect(Collectors.toList());
panel.resetSchemes(allProfiles);
}
void apply(InspectionProfileModifiableModel selected, Consumer<InspectionProfileImpl> 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<SingleInspectionProfilePanel> 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<InspectionProfileImpl> getSortedProfiles(InspectionProfileManager appManager,
InspectionProfileManager projectManager) {
return ContainerUtil.concat(ContainerUtil.sorted(appManager.getProfiles()),
ContainerUtil.sorted(projectManager.getProfiles()));
}
}
@@ -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<InspectionProfileModifiableModel> {
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<InspectionProfileModifiableModel> 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<InspectionProfileModifiableModel> createSchemeActions() {
return new DescriptionAwareSchemeActions<InspectionProfileModifiableModel>(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<InspectionProfileModifiableModel> 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);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
* 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.
@@ -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,129 +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.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.JdomKt;
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 org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
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<SingleInspectionProfilePanel> myPanels = new ArrayList<>();
private final List<InspectionProfileModifiableModel> 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;
}
@@ -197,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() {
@@ -230,219 +137,21 @@ 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);
Path file = Paths.get(dir.getPath(), sanitizeFileName(profile.getName()) + ".xml");
if (Files.isRegularFile(file.toAbsolutePath()) &&
Messages.showOkCancelDialog(wholePanel, "File \'" + file + "\' already exist. Do you want to overwrite it?", "Warning",
Messages.getQuestionIcon()) != Messages.OK) {
return;
}
JdomKt.write(element, file);
}
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(), wholePanel);
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;
}
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")) {
@@ -463,8 +172,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) {
@@ -505,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);
@@ -539,22 +239,12 @@ public abstract class InspectionToolsConfigurable extends BaseConfigurable
}
private void doReset() {
myDeletedProfiles.clear();
disposeUIResources();
final Collection<InspectionProfileImpl> profiles = getProfiles();
final List<InspectionProfileModifiableModel> 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
@@ -564,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) {
@@ -573,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<InspectionProfileImpl> getProfiles() {
final Collection<InspectionProfileImpl> 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
@@ -665,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);
}
@@ -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();
}
}
}
@@ -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();
}
@@ -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<InspectionProfileModifiableModel> 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<InspectionProfileModifiableModel>() {
@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<InspectionProfileModifiableModel> 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);
}
}
@@ -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<T extends InspectionProfileImpl> extends ComboBox<T> {
private static final String PROJECT_LEVEL_SEPARATOR_TEXT = "Project Level";
private static final String GLOBAL_LEVEL_SEPARATOR_TEXT = "Global Level";
private SortedComboBoxModel<T> myComboModel;
private T myFirstGlobalProfile;
public ProfilesComboBox() {
myComboModel = new SortedComboBoxModel<>(Comparator.comparing(T::isProjectLevel)
.reversed()
.thenComparing(InspectionProfileImpl::getDisplayName));
setModel(myComboModel);
//noinspection GtkPreferredJComboBoxRenderer
setRenderer(new ListCellRenderer<InspectionProfileImpl>() {
ListCellRendererWrapper<InspectionProfileImpl> baseRenderer = new ListCellRendererWrapper<InspectionProfileImpl>() {
@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<T> 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<T> 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();
}
}
@@ -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();
}
}
}
}
@@ -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);
}
}
}
@@ -974,12 +974,21 @@
<schemeExporter
name="Intellij IDEA code style XML"
schemeClass="com.intellij.psi.codeStyle.CodeStyleScheme"
implementationClass="com.intellij.psi.impl.source.codeStyle.CodeStyleSchemeCopyExporter"/>
implementationClass="com.intellij.application.options.schemes.SerializableSchemeExporter"/>
<schemeImporter
name="Intellij IDEA code style XML"
schemeClass="com.intellij.psi.codeStyle.CodeStyleScheme"
implementationClass="com.intellij.psi.impl.source.codeStyle.CodeStyleSchemeXmlImporter"/>
<schemeExporter
name="Intellij IDEA inspection profile XML"
schemeClass="com.intellij.codeInspection.ex.InspectionProfileModifiableModel"
implementationClass="com.intellij.application.options.schemes.SerializableSchemeExporter"/>
<schemeImporter
name="Intellij IDEA inspection profile XML"
schemeClass="com.intellij.codeInspection.ex.InspectionProfileModifiableModel"
implementationClass="com.intellij.profile.codeInspection.ui.InspectionProfileImporter"/>
<nonProjectFileWritingAccessExtension implementation="com.intellij.ide.actions.EditCustomPropertiesAction$AccessExtension"/>
<nonProjectFileWritingAccessExtension implementation="com.intellij.ide.actions.EditCustomVmOptionsAction$AccessExtension"/>
<lineIndentProvider