update copyright
[fedora-idea.git] / java / java-impl / src / com / intellij / refactoring / changeSignature / inCallers / CallerChooser.java
blobb10eeaa8e6d4823c314686ce77a19f92ef10d837
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.refactoring.changeSignature.inCallers;
18 import com.intellij.codeInsight.highlighting.HighlightManager;
19 import com.intellij.ide.highlighter.HighlighterFactory;
20 import com.intellij.openapi.application.ApplicationManager;
21 import com.intellij.openapi.editor.Document;
22 import com.intellij.openapi.editor.Editor;
23 import com.intellij.openapi.editor.EditorFactory;
24 import com.intellij.openapi.editor.colors.EditorColors;
25 import com.intellij.openapi.editor.colors.EditorColorsManager;
26 import com.intellij.openapi.editor.ex.EditorEx;
27 import com.intellij.openapi.editor.markup.TextAttributes;
28 import com.intellij.openapi.fileTypes.StdFileTypes;
29 import com.intellij.openapi.project.Project;
30 import com.intellij.openapi.ui.DialogWrapper;
31 import com.intellij.openapi.ui.Splitter;
32 import com.intellij.psi.*;
33 import com.intellij.psi.search.LocalSearchScope;
34 import com.intellij.psi.search.searches.ReferencesSearch;
35 import com.intellij.refactoring.RefactoringBundle;
36 import com.intellij.ui.CheckboxTree;
37 import com.intellij.ui.CheckedTreeNode;
38 import com.intellij.ui.IdeBorderFactory;
39 import com.intellij.ui.treeStructure.Tree;
40 import com.intellij.util.Alarm;
41 import com.intellij.util.containers.HashSet;
42 import org.jetbrains.annotations.NotNull;
44 import javax.swing.*;
45 import javax.swing.event.TreeSelectionEvent;
46 import javax.swing.event.TreeSelectionListener;
47 import javax.swing.tree.TreePath;
48 import javax.swing.tree.TreeSelectionModel;
49 import java.awt.*;
50 import java.util.Enumeration;
51 import java.util.Set;
53 /**
54 * @author ven
56 public abstract class CallerChooser extends DialogWrapper {
57 PsiMethod myMethod;
58 private final Alarm myAlarm = new Alarm();
59 private MethodNode myRoot;
60 private final Project myProject;
61 private Tree myTree;
62 private TreeSelectionListener myTreeSelectionListener;
63 private Editor myCallerEditor;
64 private Editor myCalleeEditor;
66 public Tree getTree() {
67 return myTree;
70 public CallerChooser(final PsiMethod method, String title, Tree previousTree) {
71 super(true);
72 myMethod = method;
73 myProject = myMethod.getProject();
74 myTree = previousTree;
75 setTitle(title);
76 init();
79 protected JComponent createCenterPanel() {
80 Splitter splitter = new Splitter(false, (float)0.6);
81 JPanel result = new JPanel(new BorderLayout());
82 if (myTree == null) {
83 myTree = createTree();
85 else {
86 final CheckedTreeNode root = (CheckedTreeNode)myTree.getModel().getRoot();
87 myRoot = (MethodNode)root.getFirstChild();
89 myTreeSelectionListener = new TreeSelectionListener() {
90 public void valueChanged(TreeSelectionEvent e) {
91 final TreePath path = e.getPath();
92 if (path != null) {
93 final MethodNode node = (MethodNode)path.getLastPathComponent();
94 myAlarm.cancelAllRequests();
95 myAlarm.addRequest(new Runnable() {
96 public void run() {
97 updateEditorTexts(node);
99 }, 300);
103 myTree.getSelectionModel().addTreeSelectionListener(myTreeSelectionListener);
105 JScrollPane scrollPane = new JScrollPane(myTree);
106 splitter.setFirstComponent(scrollPane);
107 final JComponent callSitesViewer = createCallSitesViewer();
108 TreePath selectionPath = myTree.getSelectionPath();
109 if (selectionPath == null) {
110 selectionPath = new TreePath(myRoot.getPath());
111 myTree.getSelectionModel().addSelectionPath(selectionPath);
114 final MethodNode node = (MethodNode)selectionPath.getLastPathComponent();
115 updateEditorTexts(node);
117 splitter.setSecondComponent(callSitesViewer);
118 result.add(splitter);
119 return result;
122 private void updateEditorTexts(final MethodNode node) {
123 final MethodNode parentNode = (MethodNode)node.getParent();
124 final String callerText = node != myRoot ? getText(node.getMethod()) : "";
125 final Document callerDocument = myCallerEditor.getDocument();
126 final String calleeText = node != myRoot ? getText(parentNode.getMethod()) : "";
127 final Document calleeDocument = myCalleeEditor.getDocument();
129 ApplicationManager.getApplication().runWriteAction(new Runnable() {
130 public void run() {
131 callerDocument.setText(callerText);
132 calleeDocument.setText(calleeText);
136 final PsiMethod caller = node.getMethod();
137 final PsiMethod callee = parentNode != null ? parentNode.getMethod() : null;
138 if (caller != null && callee != null) {
139 HighlightManager highlighter = HighlightManager.getInstance(myProject);
140 EditorColorsManager colorManager = EditorColorsManager.getInstance();
141 TextAttributes attributes = colorManager.getGlobalScheme().getAttributes(EditorColors.TEXT_SEARCH_RESULT_ATTRIBUTES);
142 int start = getStartOffset(caller);
143 for (PsiReference ref : ReferencesSearch.search(callee, new LocalSearchScope(caller), false)) {
144 final PsiElement element = ref.getElement();
145 if (element != null) {
146 highlighter.addRangeHighlight(myCallerEditor, element.getTextRange().getStartOffset() - start,
147 element.getTextRange().getEndOffset() - start, attributes, false, null);
153 public void dispose() {
154 myTree.removeTreeSelectionListener(myTreeSelectionListener);
155 EditorFactory.getInstance().releaseEditor(myCallerEditor);
156 EditorFactory.getInstance().releaseEditor(myCalleeEditor);
157 super.dispose();
160 private String getText(final PsiMethod method) {
161 if (method == null) return "";
162 final PsiFile file = method.getContainingFile();
163 Document document = PsiDocumentManager.getInstance(myProject).getDocument(file);
164 final int start = document.getLineStartOffset(document.getLineNumber(method.getTextRange().getStartOffset()));
165 final int end = document.getLineEndOffset(document.getLineNumber(method.getTextRange().getEndOffset()));
166 return document.getText().substring(start, end);
169 private int getStartOffset (@NotNull final PsiMethod method) {
170 final PsiFile file = method.getContainingFile();
171 Document document = PsiDocumentManager.getInstance(myProject).getDocument(file);
172 return document.getLineStartOffset(document.getLineNumber(method.getTextRange().getStartOffset()));
175 private JComponent createCallSitesViewer() {
176 Splitter splitter = new Splitter(true);
177 myCallerEditor = createEditor();
178 myCalleeEditor = createEditor();
179 final JComponent callerComponent = myCallerEditor.getComponent();
180 callerComponent.setBorder(IdeBorderFactory.createTitledBorder(RefactoringBundle.message("caller.chooser.caller.method")));
181 splitter.setFirstComponent(callerComponent);
182 final JComponent calleeComponent = myCalleeEditor.getComponent();
183 calleeComponent.setBorder(IdeBorderFactory.createTitledBorder(RefactoringBundle.message("caller.chooser.callee.method")));
184 splitter.setSecondComponent(calleeComponent);
185 splitter.setBorder(IdeBorderFactory.createBorder());
186 return splitter;
189 private Editor createEditor() {
190 final EditorFactory editorFactory = EditorFactory.getInstance();
191 final Document document = editorFactory.createDocument("");
192 final Editor editor = editorFactory.createViewer(document, myProject);
193 ((EditorEx)editor).setHighlighter(HighlighterFactory.createHighlighter(myProject, StdFileTypes.JAVA));
194 return editor;
197 private Tree createTree() {
198 final CheckedTreeNode root = new MethodNode(null, new HashSet<PsiMethod>());
199 myRoot = new MethodNode(myMethod, new HashSet<PsiMethod>());
200 root.add(myRoot);
201 final CheckboxTree.CheckboxTreeCellRenderer cellRenderer = new CheckboxTree.CheckboxTreeCellRenderer() {
202 public void customizeCellRenderer(JTree tree,
203 Object value,
204 boolean selected,
205 boolean expanded,
206 boolean leaf,
207 int row,
208 boolean hasFocus) {
209 if (value instanceof MethodNode) {
210 ((MethodNode)value).customizeRenderer(getTextRenderer());
214 Tree tree = new CheckboxTree(cellRenderer, root);
215 tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
216 tree.getSelectionModel().setSelectionPath(new TreePath(myRoot.getPath()));
218 return tree;
221 private void getSelectedMethods(Set<PsiMethod> methods) {
222 MethodNode node = myRoot;
223 getSelectedMethodsInner(node, methods);
224 methods.remove(node.getMethod());
227 private static void getSelectedMethodsInner(final MethodNode node, final Set<PsiMethod> allMethods) {
228 if (node.isChecked()) {
229 PsiMethod method = node.getMethod();
230 final PsiMethod[] superMethods = method.findDeepestSuperMethods();
231 if (superMethods.length == 0) {
232 allMethods.add(method);
233 } else {
234 for (PsiMethod superMethod : superMethods) {
235 allMethods.add(superMethod);
239 final Enumeration children = node.children();
240 while (children.hasMoreElements()) {
241 getSelectedMethodsInner((MethodNode)children.nextElement(), allMethods);
246 protected void doOKAction() {
247 final Set<PsiMethod> selectedMethods = new HashSet<PsiMethod>();
248 getSelectedMethods(selectedMethods);
249 callersChosen(selectedMethods);
250 super.doOKAction();
253 abstract protected void callersChosen(Set<PsiMethod> callers);