From 583f1f6cc34a2e77961d0367eb0d2df11d50cd70 Mon Sep 17 00:00:00 2001 From: Eugene Vigdorchik Date: Thu, 10 Feb 2005 19:15:42 +0300 Subject: [PATCH] (no message) --- .../inCallers/CallerChooser.java | 166 ++++++++++++++++++ .../changeSignature/inCallers/MethodNode.java | 125 +++++++++++++ source/com/intellij/ui/CheckboxTree.java | 13 +- source/com/intellij/ui/CheckedTreeNode.java | 11 +- 4 files changed, 309 insertions(+), 6 deletions(-) create mode 100644 source/com/intellij/refactoring/changeSignature/inCallers/CallerChooser.java create mode 100644 source/com/intellij/refactoring/changeSignature/inCallers/MethodNode.java diff --git a/source/com/intellij/refactoring/changeSignature/inCallers/CallerChooser.java b/source/com/intellij/refactoring/changeSignature/inCallers/CallerChooser.java new file mode 100644 index 000000000000..a1e358fb5b15 --- /dev/null +++ b/source/com/intellij/refactoring/changeSignature/inCallers/CallerChooser.java @@ -0,0 +1,166 @@ +package com.intellij.refactoring.changeSignature.inCallers; + +import com.intellij.openapi.editor.ex.EditorEx; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.fileTypes.StdFileTypes; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.openapi.ui.Splitter; +import com.intellij.openapi.ui.Messages; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.ui.*; +import com.intellij.util.Alarm; +import com.intellij.util.ui.Tree; + +import javax.swing.*; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.tree.*; +import java.awt.*; +import java.util.Enumeration; +import java.util.ArrayList; + +/** + * @author ven + */ +public class CallerChooser extends DialogWrapper { + PsiMethod myMethod; + private EditorTextField myEditorField; + private Alarm myAlarm = new Alarm(); + private MethodNode myRoot; + private Project myProject; + + public CallerChooser(final PsiMethod method, String title) { + super(true); + myMethod = method; + myProject = myMethod.getProject(); + setTitle(title); + init(); + } + + protected JComponent createCenterPanel() { + Splitter splitter = new Splitter(false, ((float)0.6)); + JPanel result = new JPanel(new BorderLayout()); + final Tree tree = createTree(); + JScrollPane scrollPane = new JScrollPane(tree); + splitter.setFirstComponent(scrollPane); + myEditorField = createCallSitesViewer(); + myEditorField.setText(getText(myMethod)); + myEditorField.setBorder(IdeBorderFactory.createBorder()); + splitter.setSecondComponent(myEditorField); + result.add(splitter); + + tree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() { + public void valueChanged(TreeSelectionEvent e) { + final TreePath path = e.getPath(); + if (path != null) { + MethodNode node = (MethodNode)path.getLastPathComponent(); + final PsiMethod method = node.getMethod(); + myAlarm.cancelAllRequests(); + myAlarm.addRequest(new Runnable() { + public void run() { + myEditorField.setText(getText(method)); + } + }, 300); + } + } + }); + + return result; + } + + private String getText(final PsiMethod method) { + final PsiFile file = method.getContainingFile(); + Document document = PsiDocumentManager.getInstance(myProject).getDocument(file); + final int start = document.getLineStartOffset(document.getLineNumber(method.getTextRange().getStartOffset())); + final int end = document.getLineEndOffset(document.getLineNumber(method.getTextRange().getEndOffset())); + return document.getText().substring(start, end); + } + + private EditorTextField createCallSitesViewer() { + return new EditorTextField("", myProject, StdFileTypes.JAVA) { + protected EditorEx createEditor() { + final EditorEx editor = super.createEditor(); + editor.setOneLineMode(false); + return editor; + } + }; + } + + private Tree createTree() { + final CheckedTreeNode root = new CheckedTreeNode(null); + myRoot = new MethodNode(myMethod); + root.add(myRoot); + final CheckboxTree.CheckboxTreeCellRenderer cellRenderer = new CheckboxTree.CheckboxTreeCellRenderer() { + public void customizeCellRenderer(JTree tree, + Object value, + boolean selected, + boolean expanded, + boolean leaf, + int row, + boolean hasFocus) { + if (value instanceof MethodNode) { + ((MethodNode)value).customizeRenderer(getTextRenderer()); + } + } + }; + Tree tree = new CheckboxTree(cellRenderer, root) { + protected void checkNode(CheckedTreeNode node, boolean checked) { + super.checkNode(node, checked); + updateChildren(node, !checked); + } + }; + tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); + tree.getSelectionModel().setSelectionPath(new TreePath(myRoot.getPath())); + return tree; + } + + private void updateChildren(final CheckedTreeNode node, boolean toEnable) { + final Enumeration children = node.children(); + while (children.hasMoreElements()) { + MethodNode child = (MethodNode)children.nextElement(); + child.setEnabled(toEnable); + updateChildren(child, toEnable); + } + } + + public PsiMethod[] getSelectedMethods () { + MethodNode node = myRoot; + ArrayList result = new ArrayList(); + getSelectedMethodsInner(node, result); + return result.toArray(new PsiMethod[result.size()]); + } + + private void getSelectedMethodsInner(final MethodNode node, final ArrayList methods) { + if (node.isChecked()) { + methods.add(node.getMethod()); + } else { + final Enumeration children = node.children(); + while (children.hasMoreElements()) { + getSelectedMethodsInner((MethodNode)children.nextElement(), methods); + } + } + } + + protected void doOKAction() { + if (!verifyPaths(myRoot)) { + Messages.showErrorDialog(myProject, "Not all paths to refactored method are selected", "Change Signature"); + return; + } + + super.doOKAction(); + } + + private boolean verifyPaths(final MethodNode node) { + if (node.isChecked()) return true; + final Enumeration children = node.children(); + if (!children.hasMoreElements()) return false; + + while (children.hasMoreElements()) { + if (!verifyPaths((MethodNode)children.nextElement())) return false; + } + return true; + } +} diff --git a/source/com/intellij/refactoring/changeSignature/inCallers/MethodNode.java b/source/com/intellij/refactoring/changeSignature/inCallers/MethodNode.java new file mode 100644 index 000000000000..88beedd3fa8d --- /dev/null +++ b/source/com/intellij/refactoring/changeSignature/inCallers/MethodNode.java @@ -0,0 +1,125 @@ +package com.intellij.refactoring.changeSignature.inCallers; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Iconable; +import com.intellij.psi.*; +import com.intellij.psi.presentation.java.ClassPresentationUtil; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.search.PsiSearchHelper; +import com.intellij.psi.util.PsiFormatUtil; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.ui.CheckedTreeNode; +import com.intellij.ui.ColoredTreeCellRenderer; +import com.intellij.ui.SimpleTextAttributes; +import com.intellij.util.ui.IdeaUIManager; + +import javax.swing.tree.TreeNode; +import java.awt.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Vector; + +/** + * @author ven + */ +public class MethodNode extends CheckedTreeNode { + private PsiMethod myMethod; + private boolean myOldChecked; + + public MethodNode(final PsiMethod method) { + super(method); + myMethod = method; + isChecked = false; + } + + public PsiMethod getMethod() { + return myMethod; + } + + //IMPORTANT: do not build children in children() + private void buildChildren () { + if (children == null) { + final PsiMethod[] callers = findCallers(); + if (callers.length > 0) { + children = new Vector(callers.length); + for (int i = 0; i < callers.length; i++) { + PsiMethod caller = callers[i]; + children.add(new MethodNode(caller)); + } + } + } + } + + public TreeNode getChildAt(int index) { + buildChildren(); + return super.getChildAt(index); + } + + public int getChildCount() { + buildChildren(); + return super.getChildCount(); + } + + public int getIndex(TreeNode aChild) { + buildChildren(); + return super.getIndex(aChild); + } + + private PsiMethod[] findCallers() { + final Project project = myMethod.getProject(); + final PsiSearchHelper searchHelper = PsiManager.getInstance(project).getSearchHelper(); + final PsiReference[] refs = searchHelper.findReferencesIncludingOverriding(myMethod, GlobalSearchScope.allScope(project), true); + List callers = new ArrayList(); + for (int i = 0; i < refs.length; i++) { + final PsiElement element = refs[i].getElement(); + if (element instanceof PsiReferenceExpression && element.getParent() instanceof PsiMethodCallExpression) { + final PsiElement enclosingContext = PsiTreeUtil.getParentOfType(element, new Class[]{PsiMethod.class, PsiClass.class}); + if (enclosingContext instanceof PsiMethod) callers.add((PsiMethod)enclosingContext); + } + } + return callers.toArray(new PsiMethod[callers.size()]); + } + + public void customizeRenderer (ColoredTreeCellRenderer renderer) { + int flags = Iconable.ICON_FLAG_VISIBILITY | Iconable.ICON_FLAG_READ_STATUS; + renderer.setIcon(myMethod.getIcon(flags)); + + final StringBuffer buffer = new StringBuffer(128); + final PsiClass containingClass = myMethod.getContainingClass(); + if (containingClass != null) { + buffer.append(ClassPresentationUtil.getNameForClass(containingClass, false)); + buffer.append('.'); + } + final String methodText = PsiFormatUtil.formatMethod( + myMethod, + PsiSubstitutor.EMPTY, PsiFormatUtil.SHOW_NAME | PsiFormatUtil.SHOW_PARAMETERS, + PsiFormatUtil.SHOW_TYPE + ); + buffer.append(methodText); + + final int style = isEnabled() ? SimpleTextAttributes.STYLE_PLAIN : SimpleTextAttributes.STYLE_STRIKEOUT; + renderer.append(buffer.toString(), new SimpleTextAttributes(style, IdeaUIManager.getTreeForegroung())); + + final String packageName = getPackageName(myMethod.getContainingClass()); + renderer.append(" (" + packageName + ")", new SimpleTextAttributes(SimpleTextAttributes.STYLE_ITALIC, Color.GRAY)); + } + + private String getPackageName(final PsiClass aClass) { + final PsiFile file = aClass.getContainingFile(); + if (file instanceof PsiJavaFile) { + return ((PsiJavaFile)file).getPackageName(); + } + return null; + } + + public void setEnabled(final boolean enabled) { + super.setEnabled(enabled); + if (!enabled) { + myOldChecked = isChecked(); + setChecked(false); + } + else { + setChecked(myOldChecked); + } + } +} diff --git a/source/com/intellij/ui/CheckboxTree.java b/source/com/intellij/ui/CheckboxTree.java index fea9acff7b91..061b0f0016f3 100644 --- a/source/com/intellij/ui/CheckboxTree.java +++ b/source/com/intellij/ui/CheckboxTree.java @@ -39,9 +39,11 @@ public class CheckboxTree extends Tree { if (checkBounds.contains(e.getPoint())) { CheckedTreeNode node = (CheckedTreeNode) getPathForRow(row).getLastPathComponent(); - toggleNode(node); - e.consume(); - setSelectionRow(row); + if (node.isEnabled()) { + toggleNode(node); + e.consume(); + setSelectionRow(row); + } } } } @@ -114,6 +116,7 @@ public class CheckboxTree extends Tree { invalidate(); if (value instanceof CheckedTreeNode) { CheckedTreeNode node = (CheckedTreeNode)value; + myCheckbox.setEnabled(node.isEnabled()); myCheckbox.setSelected(node.isChecked()); myCheckbox.setBackground(null); @@ -139,8 +142,8 @@ public class CheckboxTree extends Tree { boolean hasFocus ); - public SimpleColoredComponent getTextRenderer () { return myTextRenderer; } - public JCheckBox getCheckbox() { return myCheckbox; } + public ColoredTreeCellRenderer getTextRenderer () { return myTextRenderer; } + public JCheckBox getCheckbox() { return myCheckbox; } } diff --git a/source/com/intellij/ui/CheckedTreeNode.java b/source/com/intellij/ui/CheckedTreeNode.java index a4aa965e81d0..4ab41e80bb30 100644 --- a/source/com/intellij/ui/CheckedTreeNode.java +++ b/source/com/intellij/ui/CheckedTreeNode.java @@ -8,7 +8,8 @@ import javax.swing.tree.DefaultMutableTreeNode; * Time: 5:14:07 PM */ public class CheckedTreeNode extends DefaultMutableTreeNode { - private boolean isChecked = true; + protected boolean isChecked = true; + private boolean isEnabled = true; public CheckedTreeNode(Object userObject) { super(userObject); } @@ -21,4 +22,12 @@ public class CheckedTreeNode extends DefaultMutableTreeNode { public void setChecked(boolean checked) { isChecked = checked; } + + public void setEnabled(final boolean enabled) { + isEnabled = enabled; + } + + public boolean isEnabled() { + return isEnabled; + } }