EditableModel doesn't extend TableModel anymore to add support for JList support

This commit is contained in:
Konstantin Bulenkov
2011-07-12 01:56:28 +04:00
parent f81d9844fe
commit deff1e3d02
14 changed files with 73 additions and 957 deletions
@@ -181,7 +181,7 @@ public class ChangeClassSignatureDialog extends RefactoringDialog {
return null;
}
private class MyTableModel extends AbstractTableModel implements RowEditableTableModel {
private class MyTableModel extends AbstractTableModel implements EditableModel {
public int getColumnCount() {
return 2;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* 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.
@@ -18,7 +18,7 @@ package com.intellij.refactoring.changeSignature;
import com.intellij.psi.*;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.util.CanonicalTypes;
import com.intellij.ui.RowEditableTableModel;
import com.intellij.ui.EditableModel;
import javax.swing.table.AbstractTableModel;
import java.util.ArrayList;
@@ -28,7 +28,7 @@ import java.util.List;
/**
* @author ven
*/
public class ExceptionsTableModel extends AbstractTableModel implements RowEditableTableModel {
public class ExceptionsTableModel extends AbstractTableModel implements EditableModel {
private List<PsiTypeCodeFragment> myTypeCodeFragments;
private final PsiElement myContext;
private List<ThrownExceptionInfo> myExceptionInfos;
@@ -38,6 +38,7 @@ import com.intellij.refactoring.util.CanonicalTypes;
import com.intellij.refactoring.util.RefactoringMessageUtil;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.ui.AnActionButton;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.TableColumnAnimator;
import com.intellij.ui.TableToolbarDecorator;
import com.intellij.ui.table.JBTable;
@@ -160,6 +161,7 @@ public class JavaChangeSignatureDialog extends ChangeSignatureDialogBase<Paramet
myPropExceptionsButton.setShortcut(KeyboardShortcut.fromString("alt X"));
final JPanel panel = TableToolbarDecorator.createDecorator(table).addExtraAction(myPropExceptionsButton).createPanel();
panel.setBorder(IdeBorderFactory.createEmptyBorder(0));
myExceptionsModel.addTableModelListener(new TableModelListener() {
public void tableChanged(TableModelEvent e) {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2010 JetBrains s.r.o.
* 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.
@@ -58,10 +58,7 @@ public class JavaParameterTableModel extends ParameterTableModelBase<ParameterIn
}, new AnyVarColumn<ParameterInfoImpl>() {
@Override
public boolean isCellEditable(ParameterTableModelItemBase<ParameterInfoImpl> item) {
boolean isGenerateDelegate = dialog instanceof ChangeSignatureDialogBase
? ((ChangeSignatureDialogBase)dialog).isGenerateDelegate()
: dialog instanceof AbstractChangeSignatureDialog &&
((AbstractChangeSignatureDialog)dialog).isGenerateDelegate();
boolean isGenerateDelegate = ((ChangeSignatureDialogBase)dialog).isGenerateDelegate();
return !isGenerateDelegate && super.isCellEditable(item);
}
});
@@ -1,449 +0,0 @@
/*
* Copyright 2000-2010 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.refactoring.changeSignature;
import com.intellij.openapi.fileTypes.LanguageFileType;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTypesUtil;
import com.intellij.refactoring.BaseRefactoringProcessor;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.changeSignature.inCallers.JavaCallerChooser;
import com.intellij.refactoring.ui.CodeFragmentTableCellRenderer;
import com.intellij.refactoring.ui.JavaCodeFragmentTableCellEditor;
import com.intellij.refactoring.ui.JavaComboBoxVisibilityPanel;
import com.intellij.refactoring.ui.VisibilityPanelBase;
import com.intellij.refactoring.util.CanonicalTypes;
import com.intellij.refactoring.util.RefactoringMessageUtil;
import com.intellij.ui.EditableRowTable;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.table.JBTable;
import com.intellij.ui.treeStructure.Tree;
import com.intellij.util.Consumer;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.VisibilityUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
import java.util.Set;
public class NewJavaChangeSignatureDialog extends AbstractChangeSignatureDialog<ParameterInfoImpl, PsiMethod, JavaMethodDescriptor> {
private ExceptionsTableModel myExceptionsTableModel;
protected Set<PsiMethod> myMethodsToPropagateExceptions;
private JButton myPropagateExnChangesButton;
private Tree myExceptionPropagationTree;
public NewJavaChangeSignatureDialog(Project project,
final PsiMethod method,
boolean allowDelegation,
PsiElement defaultValueContext) {
this(project, new JavaMethodDescriptor(method), allowDelegation, defaultValueContext);
}
protected NewJavaChangeSignatureDialog(Project project,
final JavaMethodDescriptor methodDescriptor,
boolean allowDelegation,
PsiElement defaultValueContext) {
super(project, methodDescriptor, allowDelegation, defaultValueContext);
}
@Override
protected JComponent createNorthPanel() {
JComponent c = super.createNorthPanel();
myPropagateExnChangesButton = new JButton(RefactoringBundle.message("changeSignature.propagate.exceptions.title"));
myPropagateExnChangesButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
final Ref<JavaCallerChooser> chooser = new Ref<JavaCallerChooser>();
Consumer<Set<PsiMethod>> callback = new Consumer<Set<PsiMethod>>() {
@Override
public void consume(Set<PsiMethod> psiMethods) {
myMethodsToPropagateExceptions = psiMethods;
myExceptionPropagationTree = chooser.get().getTree();
}
};
chooser.set(
new JavaCallerChooser(myMethod.getMethod(), myProject, RefactoringBundle.message("changeSignature.exception.caller.chooser"),
myExceptionPropagationTree, callback));
chooser.get().show();
}
});
myPropagatePanel.add(myPropagateExnChangesButton);
return c;
}
@Override
protected VisibilityPanelBase createVisibilityControl() {
return new JavaComboBoxVisibilityPanel();
}
@Override
protected void updatePropagateButtons() {
super.updatePropagateButtons();
myPropagateExnChangesButton.setEnabled(!isGenerateDelegate() && mayPropagateExceptions());
}
private boolean mayPropagateExceptions() {
final ThrownExceptionInfo[] thrownExceptions = myExceptionsTableModel.getThrownExceptions();
final PsiClassType[] types = myMethod.getMethod().getThrowsList().getReferencedTypes();
if (thrownExceptions.length <= types.length) return false;
for (int i = 0; i < types.length; i++) {
if (thrownExceptions[i].getOldIndex() != i) return false;
}
return true;
}
@Override
protected JPanel createAdditionalPanel() {
// this method is invoked before constuctor body
myExceptionsTableModel = new ExceptionsTableModel(myMethod.getMethod().getThrowsList());
myExceptionsTableModel.setTypeInfos(myMethod.getMethod());
JBTable exceptionsTable = new JBTable(myExceptionsTableModel);
exceptionsTable.getColumnModel().getColumn(0).setCellRenderer(new CodeFragmentTableCellRenderer(myProject));
exceptionsTable.getColumnModel().getColumn(0).setCellEditor(new JavaCodeFragmentTableCellEditor(myProject));
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(IdeBorderFactory.createTitledBorder(RefactoringBundle.message("changeSignature.exceptions.panel.border.title")));
JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(exceptionsTable);
JPanel tablePanel = new JPanel(new BorderLayout());
tablePanel.add(scrollPane, BorderLayout.CENTER);
tablePanel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
panel.add(tablePanel, BorderLayout.CENTER);
exceptionsTable.setPreferredScrollableViewportSize(new Dimension(450, exceptionsTable.getRowHeight() * 8));
exceptionsTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
exceptionsTable.getSelectionModel().setSelectionInterval(0, 0);
exceptionsTable.setSurrendersFocusOnKeystroke(true);
JPanel buttonsPanel = EditableRowTable.createButtonsTable(exceptionsTable, myExceptionsTableModel, false);
panel.add(buttonsPanel, BorderLayout.EAST);
myExceptionsTableModel.addTableModelListener(
new TableModelListener() {
public void tableChanged(TableModelEvent e) {
NewJavaChangeSignatureDialog.this.updateSignature();
}
}
);
return panel;
}
@Override
protected LanguageFileType getFileType() {
return StdFileTypes.JAVA;
}
@Override
protected ParameterTableModelBase<ParameterInfoImpl> createParametersInfoModel(MethodDescriptor<ParameterInfoImpl> method) {
return new JavaParameterTableModel(((JavaMethodDescriptor)method).getMethod().getParameterList(), myDefaultValueContext, this);
}
@Override
protected void invokeRefactoring(BaseRefactoringProcessor processor) {
if (myMethodsToPropagateExceptions != null && !mayPropagateExceptions()) {
Messages.showWarningDialog(myProject, RefactoringBundle.message("changeSignature.exceptions.wont.propagate"),
ChangeSignatureHandler.REFACTORING_NAME);
myMethodsToPropagateExceptions = null;
}
super.invokeRefactoring(processor);
}
private ParameterInfoImpl[] getParameters(PsiMethod method) {
if (method != null) {
final PsiParameter[] parameters = method.getParameterList().getParameters();
final ParameterInfoImpl[] params = new ParameterInfoImpl[parameters.length];
for (int i = 0; i < parameters.length; i++) {
PsiParameter p = parameters[i];
params[i] = new ParameterInfoImpl(MethodSignatureEditor.INDEXER.getIndex(p),
p.getName(),
p.getType(),
PsiTypesUtil.getDefaultValueOfType(p.getType()),
p.isVarArgs());
}
return params;
}
return ParameterInfoImpl.EMPTY_ARRAY;
}
@Override
protected BaseRefactoringProcessor createRefactoringProcessor() {
final PsiMethod method = getNewElement();
assert method != null;
final ParameterInfoImpl[] parameters = getParameters(method);
return new ChangeSignatureProcessor(myProject,
myMethod.getMethod(),
isGenerateDelegate(),
VisibilityUtil.getVisibilityModifier(method.getModifierList()),
method.getName(),
CanonicalTypes.createTypeWrapper(method.getReturnType()),
parameters,
getExceptions(),
myMethodsToPropagateParameters,
myMethodsToPropagateExceptions);
}
@Nullable
protected CanonicalTypes.Type getReturnType() {
if (myReturnTypeField != null) {
try {
final PsiType type = ((PsiTypeCodeFragment)myReturnTypeCodeFragment).getType();
return CanonicalTypes.createTypeWrapper(type);
}
catch (PsiTypeCodeFragment.TypeSyntaxException e) {
return null;
}
catch (PsiTypeCodeFragment.NoTypeException e) {
return null;
}
}
return null;
}
protected ThrownExceptionInfo[] getExceptions() {
return myExceptionsTableModel.getThrownExceptions();
}
@Override
protected PsiCodeFragment createReturnTypeCodeFragment() {
final String returnTypeText = StringUtil.notNullize(myMethod.getReturnTypeText());
final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(myProject).getElementFactory();
return elementFactory.createTypeCodeFragment(returnTypeText, myMethod.getMethod(), true, PsiElementFactory.ALLOW_VOID);
}
@Override
protected CallerChooserBase<PsiMethod> createCallerChooser(String title, Tree treeToReuse, Consumer<Set<PsiMethod>> callback) {
return new JavaCallerChooser(myMethod.getMethod(), myProject, title, treeToReuse, callback);
}
@Override
protected String validateAndCommitData() {
PsiManager manager = PsiManager.getInstance(myProject);
PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
final PsiMethod element = getNewElement();
String name = element.getName();
if (!JavaPsiFacade.getInstance(manager.getProject()).getNameHelper().isIdentifier(name)) {
return RefactoringMessageUtil.getIncorrectIdentifierMessage(name);
}
//if (myMethod.canChangeReturnType() == MethodDescriptor.ReadWriteOption.ReadWrite) {
// try {
// ((PsiTypeCodeFragment)myReturnTypeCodeFragment).getType();
// }
// catch (PsiTypeCodeFragment.TypeSyntaxException e) {
// myReturnTypeField.requestFocus();
// return RefactoringBundle.message("changeSignature.wrong.return.type", myReturnTypeCodeFragment.getText());
// }
// catch (PsiTypeCodeFragment.NoTypeException e) {
// myReturnTypeField.requestFocus();
// return RefactoringBundle.message("changeSignature.no.return.type");
// }
//}
ParameterInfoImpl[] parameterInfos = getParameters(element);
final int newParametersNumber = parameterInfos.length;
for (int i = 0; i < newParametersNumber; i++) {
ParameterInfoImpl item = parameterInfos[i];
if (!JavaPsiFacade.getInstance(manager.getProject()).getNameHelper().isIdentifier(item.getName())) {
return RefactoringMessageUtil.getIncorrectIdentifierMessage(item.getName());
}
final PsiType type = element.getParameterList().getParameters()[i].getType();
item.setType(type);
if (type instanceof PsiEllipsisType && i != newParametersNumber - 1) {
return RefactoringBundle.message("changeSignature.vararg.not.last");
}
if (item.oldParameterIndex < 0) {
item.defaultValue = PsiTypesUtil.getDefaultValueOfType(type);
String def = item.defaultValue;
def = def.trim();
if (!(type instanceof PsiEllipsisType)) {
if (def.length() == 0) {
return RefactoringBundle.message("changeSignature.no.default.value", item.getName());
}
try {
factory.createExpressionFromText(def, null);
}
catch (IncorrectOperationException e) {
return e.getMessage();
}
}
}
}
ThrownExceptionInfo[] exceptionInfos = myExceptionsTableModel.getThrownExceptions();
PsiTypeCodeFragment[] typeCodeFragments = myExceptionsTableModel.getTypeCodeFragments();
for (int i = 0; i < exceptionInfos.length; i++) {
ThrownExceptionInfo exceptionInfo = exceptionInfos[i];
PsiTypeCodeFragment typeCodeFragment = typeCodeFragments[i];
try {
PsiType type = typeCodeFragment.getType();
if (!(type instanceof PsiClassType)) {
return RefactoringBundle.message("changeSignature.wrong.type.for.exception", typeCodeFragment.getText());
}
PsiClassType throwable = JavaPsiFacade.getInstance(myProject).getElementFactory()
.createTypeByFQClassName("java.lang.Throwable", type.getResolveScope());
if (!throwable.isAssignableFrom(type)) {
return RefactoringBundle.message("changeSignature.not.throwable.type", typeCodeFragment.getText());
}
exceptionInfo.setType((PsiClassType)type);
}
catch (PsiTypeCodeFragment.TypeSyntaxException e) {
return RefactoringBundle.message("changeSignature.wrong.type.for.exception", typeCodeFragment.getText());
}
catch (PsiTypeCodeFragment.NoTypeException e) {
return RefactoringBundle.message("changeSignature.no.type.for.exception");
}
}
// warnings
//try {
// if (myMethod.canChangeReturnType() == MethodDescriptor.ReadWriteOption.ReadWrite) {
// if (!RefactoringUtil.isResolvableType(((PsiTypeCodeFragment)myReturnTypeCodeFragment).getType())) {
// if (Messages.showOkCancelDialog(myProject, RefactoringBundle
// .message("changeSignature.cannot.resolve.return.type", myReturnTypeCodeFragment.getText()),
// RefactoringBundle.message("changeSignature.refactoring.name"), Messages.getWarningIcon()) != 0) {
// return EXIT_SILENTLY;
// }
// }
// }
// for (ParameterInfoImpl item : parameterInfos) {
//
// if (!RefactoringUtil.isResolvableType(((PsiTypeCodeFragment)item.getTypeWrapper().getType())) {
// if (Messages.showOkCancelDialog(myProject, RefactoringBundle
// .message("changeSignature.cannot.resolve.parameter.type", item.typeCodeFragment.getText(), item.parameter.getName()),
// RefactoringBundle.message("changeSignature.refactoring.name"), Messages.getWarningIcon()) !=
// 0) {
// return EXIT_SILENTLY;
// }
// }
// }
//}
//catch (PsiTypeCodeFragment.IncorrectTypeException ignored) {
//}
return null;
}
@Override
protected String calculateSignature() {
return doCalculateSignature(myMethod.getMethod());
}
protected String doCalculateSignature(PsiMethod method) {
@NonNls StringBuilder buffer = new StringBuilder();
PsiModifierList modifierList = method.getModifierList();
String modifiers = modifierList.getText();
String oldModifier = VisibilityUtil.getVisibilityModifier(modifierList);
String newModifier = getVisibility();
String newModifierStr = VisibilityUtil.getVisibilityString(newModifier);
if (!newModifier.equals(oldModifier)) {
int index = modifiers.indexOf(oldModifier);
if (index >= 0) {
StringBuilder buf = new StringBuilder(modifiers);
buf.replace(index,
index + oldModifier.length() + ("".equals(newModifierStr) ? 1 : 0),
newModifierStr);
modifiers = buf.toString();
}
else {
if (!"".equals(newModifierStr)) newModifierStr += " ";
modifiers = newModifierStr + modifiers;
}
}
buffer.append(modifiers);
if (modifiers.length() > 0 &&
!StringUtil.endsWithChar(modifiers, '\n') &&
!StringUtil.endsWithChar(modifiers, '\r') &&
!StringUtil.endsWithChar(modifiers, ' ')) {
buffer.append(" ");
}
if (!method.isConstructor()) {
final CanonicalTypes.Type returnType = getReturnType();
if (returnType != null) {
buffer.append(returnType.getTypeText());
}
buffer.append(" ");
}
buffer.append(getMethodName());
buffer.append("(");
final String indent = " ";
List<ParameterTableModelItemBase<ParameterInfoImpl>> items = myParametersTableModel.getItems();
for (int i = 0; i < items.size(); i++) {
ParameterTableModelItemBase<ParameterInfoImpl> item = items.get(i);
if (i > 0) {
buffer.append(",");
}
buffer.append("\n");
buffer.append(indent);
buffer.append(item.typeCodeFragment.getText());
buffer.append(" ");
buffer.append(item.parameter.getName());
}
if (!items.isEmpty()) {
buffer.append("\n");
}
buffer.append(")");
PsiTypeCodeFragment[] thrownExceptionsFragments = myExceptionsTableModel.getTypeCodeFragments();
if (thrownExceptionsFragments.length > 0) {
buffer.append("\n");
buffer.append("throws\n");
for (int i = 0; i < thrownExceptionsFragments.length; i++) {
String text = thrownExceptionsFragments[i].getText();
buffer.append(indent);
buffer.append(text);
if (i < thrownExceptionsFragments.length - 1) {
buffer.append(",");
}
buffer.append("\n");
}
}
return buffer.toString();
}
@Override
protected MethodSignatureEditor createSignatureEditor(PsiElement method) {
return new JavaMethodSignatureEditor(((PsiMethod)method));
}
}
@@ -22,7 +22,7 @@ import com.intellij.refactoring.ui.TypeSelector;
import com.intellij.refactoring.ui.TypeSelectorManager;
import com.intellij.refactoring.ui.TypeSelectorManagerImpl;
import com.intellij.ui.BooleanTableCellRenderer;
import com.intellij.ui.RowEditableTableModel;
import com.intellij.ui.EditableModel;
import com.intellij.ui.TableToolbarDecorator;
import com.intellij.ui.TableUtil;
import com.intellij.ui.components.JBComboBoxLabel;
@@ -285,7 +285,7 @@ public abstract class ParameterTablePanel extends JPanel {
super.setEnabled(enabled);
}
private class MyTableModel extends AbstractTableModel implements RowEditableTableModel {
private class MyTableModel extends AbstractTableModel implements EditableModel {
public static final int CHECKMARK_COLUMN = 0;
public static final int PARAMETER_TYPE_COLUMN = 1;
public static final int PARAMETER_NAME_COLUMN = 2;
@@ -28,7 +28,7 @@ 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.RowEditableTableModel;
import com.intellij.ui.EditableModel;
import com.intellij.ui.TableToolbarDecorator;
import com.intellij.ui.table.TableView;
import com.intellij.util.ui.AbstractTableCellEditor;
@@ -248,7 +248,7 @@ public class DependencyConfigurable extends BaseConfigurable {
}
}
private static class MyTableModel extends ListTableModel<DependencyRule> implements RowEditableTableModel {
private static class MyTableModel extends ListTableModel<DependencyRule> implements EditableModel {
private final Project myProject;
private final boolean myDenyRule;
@@ -1,470 +0,0 @@
/*
* 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.refactoring.changeSignature;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileTypes.LanguageFileType;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.VerticalFlowLayout;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiCodeFragment;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.refactoring.BaseRefactoringProcessor;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.ui.DelegationPanel;
import com.intellij.refactoring.ui.RefactoringDialog;
import com.intellij.refactoring.ui.VisibilityPanelBase;
import com.intellij.refactoring.util.CommonRefactoringUtil;
import com.intellij.ui.*;
import com.intellij.ui.table.TableView;
import com.intellij.ui.treeStructure.Tree;
import com.intellij.util.Alarm;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;
/**
* @author Konstantin Bulenkov
*/
public abstract class AbstractChangeSignatureDialog<PARAM_INFO extends ParameterInfo,
METHOD extends PsiElement,
DESCRIPTOR extends MethodDescriptor<PARAM_INFO>>
extends RefactoringDialog {
protected static final String EXIT_SILENTLY = "";
protected final DESCRIPTOR myMethod;
private final boolean myAllowDelegation;
protected EditorTextField myNameField;
protected EditorTextField myReturnTypeField;
protected TableView<ParameterTableModelItemBase<PARAM_INFO>> myParametersTable;
protected final ParameterTableModelBase<PARAM_INFO> myParametersTableModel;
private JTextArea mySignatureArea;
private final Alarm myUpdateSignatureAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD);
protected VisibilityPanelBase myVisibilityPanel;
protected PsiCodeFragment myReturnTypeCodeFragment;
private DelegationPanel myDelegationPanel;
protected JButton myPropagateParamChangesButton;
protected Set<METHOD> myMethodsToPropagateParameters = null;
private Tree myParameterPropagationTreeToReuse;
protected JPanel myPropagatePanel;
protected final PsiElement myDefaultValueContext;
private boolean myVisibilityAdded = false;
private MethodSignatureEditor<METHOD> mySignatureEditor;
protected abstract LanguageFileType getFileType();
protected abstract ParameterTableModelBase<PARAM_INFO> createParametersInfoModel(MethodDescriptor<PARAM_INFO> method);
protected abstract BaseRefactoringProcessor createRefactoringProcessor();
protected abstract PsiCodeFragment createReturnTypeCodeFragment();
protected abstract CallerChooserBase<METHOD> createCallerChooser(String title, Tree treeToReuse, Consumer<Set<METHOD>> callback);
protected abstract MethodSignatureEditor<METHOD> createSignatureEditor(PsiElement method);
protected abstract String validateAndCommitData();
public AbstractChangeSignatureDialog(Project project, final DESCRIPTOR method, boolean allowDelegation, PsiElement defaultValueContext) {
super(project, true);
myMethod = method;
myDefaultValueContext = defaultValueContext;
myParametersTableModel = createParametersInfoModel(method);
myAllowDelegation = allowDelegation;
setParameterInfos(method.getParameters());
setTitle(ChangeSignatureHandler.REFACTORING_NAME);
init();
//doUpdateSignature();
Disposer.register(myDisposable, new Disposable() {
public void dispose() {
myUpdateSignatureAlarm.cancelAllRequests();
}
});
}
public void setParameterInfos(List<PARAM_INFO> parameterInfos) {
myParametersTableModel.setParameterInfos(parameterInfos);
updateSignature();
}
protected String getMethodName() {
if (myNameField != null) {
return myNameField.getText().trim();
}
else {
return myMethod.getName();
}
}
@Nullable
public METHOD getNewElement() {
return mySignatureEditor == null ? null : mySignatureEditor.createFromString();
}
protected String getVisibility() {
if (myVisibilityPanel != null) {
return myVisibilityPanel.getVisibility();
}
else {
return myMethod.getVisibility();
}
}
public List<PARAM_INFO> getParameters() {
List<PARAM_INFO> result = new ArrayList<PARAM_INFO>(myParametersTableModel.getRowCount());
for (ParameterTableModelItemBase<PARAM_INFO> item : myParametersTableModel.getItems()) {
result.add(item.parameter);
}
return result;
}
public boolean isGenerateDelegate() {
return myAllowDelegation && myDelegationPanel.isGenerateDelegate();
}
public JComponent getPreferredFocusedComponent() {
return mySignatureEditor.getComponent();
}
protected JComponent createNorthPanel() {
JPanel panel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.TOP));
//final JPanel methodPanel = new JPanel(new BorderLayout());
//final JPanel visibilityAndReturnTypePanel = new JPanel(new BorderLayout());
//final JPanel visibilityPanel = createVisibilityPanel();
//final JPanel typePanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.TOP));
//final JPanel namePanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.TOP));
mySignatureEditor = createSignatureEditor(myMethod.getMethod());
panel.add(mySignatureEditor);
JPanel top = new JPanel(new BorderLayout());
if (myAllowDelegation) {
myDelegationPanel = createDelegationPanel();
top.add(myDelegationPanel, BorderLayout.WEST);
}
myPropagateParamChangesButton = new JButton(RefactoringBundle.message("changeSignature.propagate.parameters.title"));
myPropagateParamChangesButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
final Ref<CallerChooserBase<METHOD>> chooser = new Ref<CallerChooserBase<METHOD>>();
Consumer<Set<METHOD>> callback = new Consumer<Set<METHOD>>() {
@Override
public void consume(Set<METHOD> callers) {
myMethodsToPropagateParameters = callers;
myParameterPropagationTreeToReuse = chooser.get().getTree();
}
};
try {
chooser.set(
createCallerChooser(RefactoringBundle.message("changeSignature.parameter.caller.chooser"), myParameterPropagationTreeToReuse,
callback));
} catch (ProcessCanceledException ex) {
// user cancelled initial callers search, don't show dialog
return;
}
chooser.get().show();
}
});
myPropagatePanel = new JPanel();
myPropagatePanel.add(myPropagateParamChangesButton);
top.add(myPropagatePanel, BorderLayout.EAST);
panel.add(top);
//final DocumentListener documentListener = new DocumentAdapter() {
// public void documentChanged(DocumentEvent event) {
// updateSignature();
// }
//};
//if (myMethod.canChangeName()) {
// JLabel namePrompt = new JLabel();
// myNameField = new EditorTextField(myMethod.getName());
// namePrompt.setText(RefactoringBundle.message("name.prompt"));
// namePrompt.setLabelFor(myNameField);
// //panel.add(namePrompt);
// //panel.add(myNameField);
// myNameField.addDocumentListener(documentListener);
// namePanel.add(namePrompt);
// namePanel.add(myNameField);
// methodPanel.add(namePanel, BorderLayout.CENTER);
//}
//if (myMethod.canChangeVisibility() && visibilityPanel instanceof ComboBoxVisibilityPanel) {
// visibilityAndReturnTypePanel.add(visibilityPanel, BorderLayout.WEST);
// myVisibilityAdded = true;
//}
//if (myMethod.canChangeReturnType() != MethodDescriptor.ReadWriteOption.None) {
// JLabel typePrompt = new JLabel();
// myReturnTypeCodeFragment = createReturnTypeCodeFragment();
// final Document document = PsiDocumentManager.getInstance(myProject).getDocument(myReturnTypeCodeFragment);
// myReturnTypeField = createReturnTypeTextField(document);
// typePrompt.setText(RefactoringBundle.message("changeSignature.return.type.prompt"));
// typePrompt.setLabelFor(myReturnTypeField);
// //panel.add(typePrompt);
// //panel.add(myReturnTypeField);
// typePanel.add(typePrompt);
// typePanel.add(myReturnTypeField);
// visibilityAndReturnTypePanel.add(typePanel, BorderLayout.EAST);
//
// if (myMethod.canChangeReturnType() == MethodDescriptor.ReadWriteOption.ReadWrite) {
// myReturnTypeField.addDocumentListener(documentListener);
// }
// else {
// myReturnTypeField.setEnabled(false);
// }
//}
//if (visibilityAndReturnTypePanel.getComponentCount() > 0) {
// methodPanel.add(visibilityAndReturnTypePanel, BorderLayout.WEST);
//}
//panel.add(methodPanel);
return panel;
}
protected EditorTextField createReturnTypeTextField(Document document) {
return new EditorTextField(document, myProject, getFileType());
}
private DelegationPanel createDelegationPanel() {
return new DelegationPanel() {
protected void stateModified() {
myParametersTableModel.fireTableDataChanged();
myParametersTable.repaint();
}
};
}
protected JComponent createCenterPanel() {
final JPanel panel = new JPanel(new BorderLayout());
final JPanel subPanel = new JPanel(new BorderLayout());
if (myMethod.canChangeParameters()) {
subPanel.add(createParametersPanel(), BorderLayout.CENTER);
}
//if (myMethod.canChangeVisibility() && !myVisibilityAdded) {
// final JPanel visibilityPanel = createVisibilityPanel();
// subPanel.add(visibilityPanel, myMethod.canChangeParameters() ? BorderLayout.EAST : BorderLayout.CENTER);
//}
panel.add(subPanel, BorderLayout.CENTER);
//final JPanel bottomPanel = new JPanel(new GridBagLayout());
//final JPanel additionalPanel = createAdditionalPanel();
//int gridX = 0;
//if (additionalPanel != null) {
// bottomPanel.add(additionalPanel, new GridBagConstraints(gridX++,
// 0,
// 1,
// 1,
// 0.5,
// 0.0,
// GridBagConstraints.WEST,
// GridBagConstraints.BOTH,
// new Insets(4, 4, 4, 0),
// 0,
// 0));
//}
//
//bottomPanel.add(createSignaturePanel(), new GridBagConstraints(gridX,
// 0,
// 1,
// 1,
// 0.5,
// 0.0,
// GridBagConstraints.EAST,
// GridBagConstraints.BOTH,
// new Insets(4, 0, 4, 4),
// 0,
// 0));
//panel.add(bottomPanel, BorderLayout.SOUTH);
return panel;
}
protected JPanel createVisibilityPanel() {
myVisibilityPanel = createVisibilityControl();
myVisibilityPanel.setVisibility(myMethod.getVisibility());
myVisibilityPanel.addListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
updateSignature();
}
});
return myVisibilityPanel;
}
protected abstract VisibilityPanelBase createVisibilityControl();
@Nullable
protected JPanel createAdditionalPanel() {
return null;
}
protected String getDimensionServiceKey() {
return "refactoring.ChangeSignatureDialog";
}
private JPanel createParametersPanel() {
myParametersTable = new TableView<ParameterTableModelItemBase<PARAM_INFO>>(myParametersTableModel) {
@Override
public void editingStopped(ChangeEvent e) {
super.editingStopped(e);
repaint(); // to update disabled cells background
}
};
myParametersTable.setCellSelectionEnabled(true);
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(IdeBorderFactory.createTitledBorder(RefactoringBundle.message("parameters.border.title")));
JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(myParametersTable);
JPanel tablePanel = new JPanel(new BorderLayout());
tablePanel.add(scrollPane, BorderLayout.CENTER);
tablePanel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
panel.add(tablePanel, BorderLayout.CENTER);
myParametersTable.setPreferredScrollableViewportSize(new Dimension(450, myParametersTable.getRowHeight() * 8));
myParametersTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
myParametersTable.getSelectionModel().setSelectionInterval(0, 0);
myParametersTable.setSurrendersFocusOnKeystroke(true);
JPanel buttonsPanel = EditableRowTable.createButtonsTable(myParametersTable, myParametersTableModel, true);
panel.add(buttonsPanel, BorderLayout.EAST);
myParametersTableModel.addTableModelListener(
new TableModelListener() {
public void tableChanged(TableModelEvent e) {
updateSignature();
}
}
);
return panel;
}
private JComponent createSignaturePanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createCompoundBorder(
IdeBorderFactory.createTitledBorder(RefactoringBundle.message("signature.preview.border.title")),
IdeBorderFactory.createEmptyBorder(new Insets(4, 4, 4, 4))));
String s = calculateSignature();
s = StringUtil.convertLineSeparators(s);
int height = new StringTokenizer(s, "\n\r").countTokens() + 2;
if (height > 10) height = 10;
mySignatureArea = new JTextArea(height, 50);
mySignatureArea.setEditable(false);
mySignatureArea.setBackground(getContentPane().getBackground());
//mySignatureArea.setFont(myTableFont);
JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(mySignatureArea);
scrollPane.setBorder(IdeBorderFactory.createEmptyBorder(new Insets(0, 0, 0, 0)));
panel.add(scrollPane, BorderLayout.CENTER);
updateSignature();
return panel;
}
protected void updateSignature() {
if (mySignatureArea == null) return;
final Runnable updateRunnable = new Runnable() {
public void run() {
myUpdateSignatureAlarm.cancelAllRequests();
myUpdateSignatureAlarm.addRequest(new Runnable() {
public void run() {
doUpdateSignature();
updatePropagateButtons();
}
}, 100, ModalityState.stateForComponent(mySignatureArea));
}
};
SwingUtilities.invokeLater(updateRunnable);
}
private void doUpdateSignature() {
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
String signature = calculateSignature();
mySignatureArea.setText(signature);
}
protected void updatePropagateButtons() {
myPropagateParamChangesButton.setEnabled(!isGenerateDelegate() && mayPropagateParameters());
}
private boolean mayPropagateParameters() {
final List<PARAM_INFO> infos = getParameters();
if (infos.size() <= myMethod.getParametersCount()) return false;
for (int i = 0; i < myMethod.getParametersCount(); i++) {
if (infos.get(i).getOldIndex() != i) return false;
}
return true;
}
protected abstract String calculateSignature();
protected void doAction() {
if (myParametersTable != null) {
TableUtil.stopEditing(myParametersTable);
}
String message = validateAndCommitData();
if (message != null) {
if (message != EXIT_SILENTLY) {
CommonRefactoringUtil.showErrorMessage(getTitle(), message, getHelpId(), myProject);
}
return;
}
if (myMethodsToPropagateParameters != null && !mayPropagateParameters()) {
Messages.showWarningDialog(myProject, RefactoringBundle.message("changeSignature.parameters.wont.propagate"),
ChangeSignatureHandler.REFACTORING_NAME);
myMethodsToPropagateParameters = null;
}
invokeRefactoring(createRefactoringProcessor());
}
@Override
protected String getHelpId() {
return "refactoring.changeSignature";
}
}
@@ -39,7 +39,7 @@ import java.util.ArrayList;
import java.util.List;
public abstract class ParameterTableModelBase<P extends ParameterInfo> extends ListTableModel<ParameterTableModelItemBase<P>>
implements RowEditableTableModel {
implements EditableModel {
protected final PsiElement myTypeContext;
protected final PsiElement myDefaultValueContext;
@@ -0,0 +1,28 @@
/*
* 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.ui;
/**
* @author Konstantin Bulenkov
* @since 11.0
*/
public interface EditableModel {
void addRow();
void removeRow(int index);
void exchangeRows(int oldIndex, int newIndex);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* 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.
@@ -19,11 +19,13 @@ import javax.swing.table.TableModel;
/**
* @author dsl
* @author Konstantin Bulenkov
*
* @deprecated
* @see EditableModel
*/
public interface RowEditableTableModel extends TableModel {
void addRow();
void removeRow(int index);
void exchangeRows(int index1, int index2);
void exchangeRows(int oldIndex, int newIndex);
}
@@ -30,7 +30,7 @@ public class TableRowsDnDSupport {
private TableRowsDnDSupport() {
}
public static void install(@NotNull final JTable table, @NotNull final RowEditableTableModel model) {
public static void install(@NotNull final JTable table, @NotNull final EditableModel model) {
table.setDragEnabled(true);
//table.setDropMode(DropMode.ON);
DnDSupport.createBuilder(table)
@@ -18,9 +18,11 @@ package com.intellij.ui;
import com.intellij.openapi.actionSystem.ActionToolbarPosition;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.ui.border.CustomLineBorder;
import com.intellij.util.ui.UIUtil;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.TableModel;
@@ -52,24 +54,25 @@ public class TableToolbarDecorator {
private TableToolbarDecorator(JTable table) {
myTable = table;
myTable.setBorder(IdeBorderFactory.createEmptyBorder(0));
myModel = table.getModel();
myToolbarPosition = SystemInfo.isMac ? ActionToolbarPosition.BOTTOM : ActionToolbarPosition.RIGHT;
myBorder = SystemInfo.isMac ? new CustomLineBorder(0,1,1,1) : null;
myAddActionEnabled = myRemoveActionEnabled = myUpActionEnabled = myDownActionEnabled = myModel instanceof RowEditableTableModel;
if (myModel instanceof RowEditableTableModel) {
myBorder = SystemInfo.isMac ? new CustomLineBorder(0,1,1,1) : new CustomLineBorder(0, 1, 0, 0);
myAddActionEnabled = myRemoveActionEnabled = myUpActionEnabled = myDownActionEnabled = myModel instanceof EditableModel;
if (myModel instanceof EditableModel) {
createDefaultActions();
}
}
private void createDefaultActions() {
final JTable table = myTable;
final RowEditableTableModel tableModel = (RowEditableTableModel)myModel;
final EditableModel tableModel = (EditableModel)myModel;
myAddAction = new Runnable() {
public void run() {
TableUtil.stopEditing(table);
tableModel.addRow();
final int index = tableModel.getRowCount() - 1;
final int index = myModel.getRowCount() - 1;
table.editCellAt(index, 0);
table.setRowSelectionInterval(index, index);
table.setColumnSelectionInterval(0, 0);
@@ -87,9 +90,9 @@ public class TableToolbarDecorator {
public void run() {
TableUtil.stopEditing(table);
int index = table.getSelectedRow();
if (0 <= index && index < tableModel.getRowCount()) {
if (0 <= index && index < myModel.getRowCount()) {
tableModel.removeRow(index);
if (index < tableModel.getRowCount()) {
if (index < myModel.getRowCount()) {
table.setRowSelectionInterval(index, index);
}
else {
@@ -109,7 +112,7 @@ public class TableToolbarDecorator {
public void run() {
TableUtil.stopEditing(table);
int index = table.getSelectedRow();
if (0 < index && index < tableModel.getRowCount()) {
if (0 < index && index < myModel.getRowCount()) {
tableModel.exchangeRows(index, index - 1);
table.setRowSelectionInterval(index - 1, index - 1);
}
@@ -121,7 +124,7 @@ public class TableToolbarDecorator {
public void run() {
TableUtil.stopEditing(table);
int index = table.getSelectedRow();
if (0 <= index && index < tableModel.getRowCount() - 1) {
if (0 <= index && index < myModel.getRowCount() - 1) {
tableModel.exchangeRows(index, index + 1);
table.setRowSelectionInterval(index + 1, index + 1);
}
@@ -131,12 +134,12 @@ public class TableToolbarDecorator {
}
private static void updateButtons(final JTable table,
final RowEditableTableModel tableModel,
final EditableModel tableModel,
final AddRemoveUpDownPanel p) {
if (table.isEnabled()) {
final int index = table.getSelectedRow();
if (0 <= index && index < tableModel.getRowCount()) {
final boolean downEnable = index < tableModel.getRowCount() - 1;
if (0 <= index && index < ((TableModel)tableModel).getRowCount()) {
final boolean downEnable = index < ((TableModel)tableModel).getRowCount() - 1;
final boolean upEnable = index > 0;
if (p != null) {
p.setEnabled(AddRemoveUpDownPanel.Buttons.REMOVE, true);
@@ -229,22 +232,24 @@ public class TableToolbarDecorator {
buttons);
myPanel.setBorder(myBorder);
final JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(myTable);
scrollPane.setBorder(IdeBorderFactory.createEmptyBorder(0));
final JPanel panel = new JPanel(new BorderLayout());
panel.add(scrollPane, BorderLayout.CENTER);
panel.add(myPanel, getPlacement());
if (myModel instanceof RowEditableTableModel && buttons.length > 0) {
updateButtons(myTable, (RowEditableTableModel)myModel, myPanel);
if (myModel instanceof EditableModel && buttons.length > 0) {
updateButtons(myTable, (EditableModel)myModel, myPanel);
if (myUpAction != null && myUpActionEnabled && myDownAction != null && myDownActionEnabled) {
TableRowsDnDSupport.install(myTable, (RowEditableTableModel)myModel);
TableRowsDnDSupport.install(myTable, (EditableModel)myModel);
}
myTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
updateButtons(myTable, (RowEditableTableModel)myModel, myPanel);
updateButtons(myTable, (EditableModel)myModel, myPanel);
}
});
}
panel.setBorder(new LineBorder(UIUtil.getBorderColor()));
return panel;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2010 JetBrains s.r.o.
* 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.
@@ -30,6 +30,7 @@ import com.intellij.refactoring.util.CanonicalTypes;
import com.intellij.refactoring.util.CommonRefactoringUtil;
import com.intellij.ui.EditableRowTable;
import com.intellij.ui.EditorTextField;
import com.intellij.ui.TableToolbarDecorator;
import com.intellij.ui.TableUtil;
import com.intellij.ui.table.JBTable;
import com.intellij.util.Function;
@@ -195,7 +196,7 @@ public class GrChangeSignatureDialog extends RefactoringDialog {
myExceptionsTable = new JBTable(myExceptionTableModel);
myExceptionsTable.setPreferredScrollableViewportSize(new Dimension(200, myExceptionsTable.getRowHeight() * 8));
myExceptionsButtonPanel = EditableRowTable.createButtonsTable(myExceptionsTable, myExceptionTableModel, false);
myExceptionsButtonPanel = TableToolbarDecorator.createDecorator(myExceptionsTable).createPanel();
myExceptionsTable.getColumnModel().getColumn(0).setCellRenderer(new CodeFragmentTableCellRenderer(myProject));
myExceptionsTable.getColumnModel().getColumn(0).setCellEditor(new JavaCodeFragmentTableCellEditor(myProject));
@@ -415,4 +416,4 @@ public class GrChangeSignatureDialog extends RefactoringDialog {
public GrParameterTableModel getParameterModel() {
return myParameterModel;
}
}
}