blob: 098a1e3d2fc417739f5129026c6caac933280661 [file] [log] [blame]
/*
* Copyright 2000-2011 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.packageDependencies.ui;
import com.intellij.analysis.AnalysisScopeBundle;
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
import com.intellij.ide.util.scopeChooser.PackageSetChooserCombo;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.options.BaseConfigurable;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.Project;
import com.intellij.packageDependencies.DefaultScopesProvider;
import com.intellij.packageDependencies.DependencyRule;
import com.intellij.packageDependencies.DependencyValidationManager;
import com.intellij.psi.search.scope.packageSet.NamedScope;
import com.intellij.psi.search.scope.packageSet.PackageSet;
import com.intellij.ui.ToolbarDecorator;
import com.intellij.ui.table.TableView;
import com.intellij.util.ui.*;
import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
public class DependencyConfigurable extends BaseConfigurable {
private final Project myProject;
private MyTableModel myDenyRulesModel;
private MyTableModel myAllowRulesModel;
private TableView<DependencyRule> myDenyTable;
private TableView<DependencyRule> myAllowTable;
private final ColumnInfo<DependencyRule, NamedScope> DENY_USAGES_OF = new LeftColumn(AnalysisScopeBundle.message("dependency.configurable.deny.table.column1"));
private final ColumnInfo<DependencyRule, NamedScope> DENY_USAGES_IN = new RightColumn(AnalysisScopeBundle.message("dependency.configurable.deny.table.column2"));
private final ColumnInfo<DependencyRule, NamedScope> ALLOW_USAGES_OF = new LeftColumn(AnalysisScopeBundle.message("dependency.configurable.allow.table.column1"));
private final ColumnInfo<DependencyRule, NamedScope> ALLOW_USAGES_ONLY_IN = new RightColumn(AnalysisScopeBundle.message("dependency.configurable.allow.table.column2"));
private JPanel myWholePanel;
private JPanel myDenyPanel;
private JPanel myAllowPanel;
private JCheckBox mySkipImports;
private static final Logger LOG = Logger.getInstance("#" + DependencyConfigurable.class.getName());
public DependencyConfigurable(Project project) {
myProject = project;
}
@Override
public String getDisplayName() {
return AnalysisScopeBundle.message("dependency.configurable.display.name");
}
@Override
public String getHelpTopic() {
return "editing.analyzeDependencies.validation";
}
@Override
public JComponent createComponent() {
myDenyRulesModel = new MyTableModel(myProject, new ColumnInfo[]{DENY_USAGES_OF, DENY_USAGES_IN}, true);
myDenyRulesModel.setSortable(false);
myAllowRulesModel = new MyTableModel(myProject, new ColumnInfo[]{ALLOW_USAGES_OF, ALLOW_USAGES_ONLY_IN}, false);
myAllowRulesModel.setSortable(false);
myDenyTable = new TableView<DependencyRule>(myDenyRulesModel);
myDenyPanel.add(createRulesPanel(myDenyRulesModel, myDenyTable), BorderLayout.CENTER);
myAllowTable = new TableView<DependencyRule>(myAllowRulesModel);
myAllowPanel.add(createRulesPanel(myAllowRulesModel, myAllowTable), BorderLayout.CENTER);
return myWholePanel;
}
private JPanel createRulesPanel(MyTableModel model, TableView<DependencyRule> table) {
table.setSurrendersFocusOnKeystroke(true);
table.setPreferredScrollableViewportSize(new Dimension(300, 150));
table.setShowGrid(true);
table.setRowHeight(new PackageSetChooserCombo(myProject, null).getPreferredSize().height);
return ToolbarDecorator.createDecorator(table).createPanel();
}
@Override
public JComponent getPreferredFocusedComponent() {
return myDenyTable;
}
@Override
public void apply() throws ConfigurationException {
stopTableEditing();
DependencyValidationManager validationManager = DependencyValidationManager.getInstance(myProject);
validationManager.removeAllRules();
final HashMap<String, PackageSet> unUsed = new HashMap<String, PackageSet>(validationManager.getUnnamedScopes());
List<DependencyRule> modelItems = new ArrayList<DependencyRule>();
modelItems.addAll(myDenyRulesModel.getItems());
modelItems.addAll(myAllowRulesModel.getItems());
for (DependencyRule rule : modelItems) {
validationManager.addRule(rule);
final NamedScope fromScope = rule.getFromScope();
if (fromScope instanceof NamedScope.UnnamedScope) {
final PackageSet fromPackageSet = fromScope.getValue();
LOG.assertTrue(fromPackageSet != null);
unUsed.remove(fromPackageSet.getText());
}
final NamedScope toScope = rule.getToScope();
if (toScope instanceof NamedScope.UnnamedScope) {
final PackageSet toPackageSet = toScope.getValue();
LOG.assertTrue(toPackageSet != null);
unUsed.remove(toPackageSet.getText());
}
}
for (String text : unUsed.keySet()) {//cleanup
validationManager.getUnnamedScopes().remove(text);
}
validationManager.setSkipImportStatements(mySkipImports.isSelected());
DaemonCodeAnalyzer.getInstance(myProject).restart();
}
private void stopTableEditing() {
myDenyTable.stopEditing();
myAllowTable.stopEditing();
}
@Override
public void reset() {
final DependencyValidationManager validationManager = DependencyValidationManager.getInstance(myProject);
DependencyRule[] rules = validationManager.getAllRules();
final ArrayList<DependencyRule> denyList = new ArrayList<DependencyRule>();
final ArrayList<DependencyRule> allowList = new ArrayList<DependencyRule>();
for (DependencyRule rule : rules) {
if (rule.isDenyRule()) {
denyList.add(rule.createCopy());
}
else {
allowList.add(rule.createCopy());
}
}
myDenyRulesModel.setItems(denyList);
myAllowRulesModel.setItems(allowList);
mySkipImports.setSelected(validationManager.skipImportStatements());
}
@Override
public boolean isModified() {
final DependencyValidationManager validationManager = DependencyValidationManager.getInstance(myProject);
if (validationManager.skipImportStatements() != mySkipImports.isSelected()) return true;
final List<DependencyRule> rules = new ArrayList<DependencyRule>();
rules.addAll(myDenyRulesModel.getItems());
rules.addAll(myAllowRulesModel.getItems());
return !Arrays.asList(validationManager.getAllRules()).equals(rules);
}
@Override
public void disposeUIResources() {
}
private static final DefaultTableCellRenderer
CELL_RENDERER = new DefaultTableCellRenderer() {
@Override
public Component getTableCellRendererComponent(JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
setText(value == null ? "" : ((NamedScope)value).getName());
return this;
}
};
public abstract class MyColumnInfo extends ColumnInfo<DependencyRule, NamedScope> {
protected MyColumnInfo(String name) {
super(name);
}
@Override
public boolean isCellEditable(DependencyRule rule) {
return true;
}
@Override
public TableCellRenderer getRenderer(DependencyRule rule) {
return CELL_RENDERER;
}
@Override
public TableCellEditor getEditor(DependencyRule packageSetDependencyRule) {
return new AbstractTableCellEditor() {
private PackageSetChooserCombo myCombo;
@Override
public Object getCellEditorValue() {
return myCombo.getSelectedScope();
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
myCombo = new PackageSetChooserCombo(myProject, value == null ? null : ((NamedScope)value).getName());
return new CellEditorComponentWithBrowseButton<JComponent>(myCombo, this);
}
};
}
@Override
public abstract void setValue(DependencyRule rule, NamedScope packageSet);
}
private class RightColumn extends MyColumnInfo {
public RightColumn(final String name) {
super(name);
}
@Override
public NamedScope valueOf(DependencyRule rule) {
return rule.getFromScope();
}
@Override
public void setValue(DependencyRule rule, NamedScope set) {
rule.setFromScope(set);
}
}
private class LeftColumn extends MyColumnInfo {
public LeftColumn(final String name) {
super(name);
}
@Override
public NamedScope valueOf(DependencyRule rule) {
return rule.getToScope();
}
@Override
public void setValue(DependencyRule rule, NamedScope set) {
rule.setToScope(set);
}
}
private static class MyTableModel extends ListTableModel<DependencyRule> implements EditableModel {
private final Project myProject;
private final boolean myDenyRule;
public MyTableModel(final Project project, final ColumnInfo[] columnInfos, final boolean isDenyRule) {
super(columnInfos);
myProject = project;
myDenyRule = isDenyRule;
}
@Override
public void addRow() {
ArrayList<DependencyRule> newList = new ArrayList<DependencyRule>(getItems());
final NamedScope scope = DefaultScopesProvider.getAllScope();
newList.add(new DependencyRule(scope, scope, myDenyRule));
setItems(newList);
}
@Override
public void exchangeRows(int index1, int index2) {
ArrayList<DependencyRule> newList = new ArrayList<DependencyRule>(getItems());
DependencyRule r1 = newList.get(index1);
DependencyRule r2 = newList.get(index2);
newList.set(index1, r2);
newList.set(index2, r1);
setItems(newList);
}
}
}