update copyright
[fedora-idea.git] / java / java-impl / src / com / intellij / ide / hierarchy / call / CallHierarchyNodeDescriptor.java
blob3d1be3755c6ff2341afb4d9636be396763cbd854
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.ide.hierarchy.call;
18 import com.intellij.codeInsight.highlighting.HighlightManager;
19 import com.intellij.ide.IdeBundle;
20 import com.intellij.ide.hierarchy.HierarchyNodeDescriptor;
21 import com.intellij.ide.hierarchy.JavaHierarchyUtil;
22 import com.intellij.openapi.editor.Editor;
23 import com.intellij.openapi.editor.colors.EditorColors;
24 import com.intellij.openapi.editor.colors.EditorColorsManager;
25 import com.intellij.openapi.editor.markup.RangeHighlighter;
26 import com.intellij.openapi.editor.markup.TextAttributes;
27 import com.intellij.openapi.fileEditor.FileEditor;
28 import com.intellij.openapi.fileEditor.FileEditorManager;
29 import com.intellij.openapi.fileEditor.TextEditor;
30 import com.intellij.openapi.project.Project;
31 import com.intellij.openapi.roots.ui.util.CompositeAppearance;
32 import com.intellij.openapi.util.Comparing;
33 import com.intellij.openapi.util.Iconable;
34 import com.intellij.openapi.util.TextRange;
35 import com.intellij.pom.Navigatable;
36 import com.intellij.psi.*;
37 import com.intellij.psi.impl.source.jsp.jspJava.JspHolderMethod;
38 import com.intellij.psi.jsp.JspFile;
39 import com.intellij.psi.presentation.java.ClassPresentationUtil;
40 import com.intellij.psi.util.PsiFormatUtil;
41 import com.intellij.psi.util.PsiTreeUtil;
42 import com.intellij.ui.LayeredIcon;
43 import org.jetbrains.annotations.Nullable;
45 import javax.swing.*;
46 import java.awt.*;
47 import java.util.ArrayList;
48 import java.util.List;
50 public final class CallHierarchyNodeDescriptor extends HierarchyNodeDescriptor implements Navigatable {
51 private int myUsageCount = 1;
52 private final List<PsiReference> myReferences = new ArrayList<PsiReference>();
53 private final boolean myNavigateToReference;
55 public CallHierarchyNodeDescriptor(
56 final Project project,
57 final HierarchyNodeDescriptor parentDescriptor,
58 final PsiElement element,
59 final boolean isBase,
60 final boolean navigateToReference){
61 super(project, parentDescriptor, element, isBase);
62 myNavigateToReference = navigateToReference;
65 /**
66 * @return PsiMethod or PsiClass or JspFile
68 public final PsiMember getEnclosingElement(){
69 return myElement == null ? null : getEnclosingElement(myElement);
72 static PsiMember getEnclosingElement(final PsiElement element){
73 return PsiTreeUtil.getNonStrictParentOfType(element, PsiMethod.class, PsiClass.class);
76 public final void incrementUsageCount(){
77 myUsageCount++;
80 /**
81 * Element for OpenFileDescriptor
83 public final PsiElement getTargetElement(){
84 return myElement;
87 public final boolean isValid(){
88 final PsiElement element = getEnclosingElement();
89 return element != null && element.isValid();
92 public final boolean update(){
93 final CompositeAppearance oldText = myHighlightedText;
94 final Icon oldOpenIcon = myOpenIcon;
96 int flags = Iconable.ICON_FLAG_VISIBILITY;
97 if (isMarkReadOnly()) {
98 flags |= Iconable.ICON_FLAG_READ_STATUS;
101 boolean changes = super.update();
103 final PsiElement enclosingElement = getEnclosingElement();
105 if (enclosingElement == null) {
106 final String invalidPrefix = IdeBundle.message("node.hierarchy.invalid");
107 if (!myHighlightedText.getText().startsWith(invalidPrefix)) {
108 myHighlightedText.getBeginning().addText(invalidPrefix, HierarchyNodeDescriptor.getInvalidPrefixAttributes());
110 return true;
113 myOpenIcon = enclosingElement.getIcon(flags);
114 if (changes && myIsBase) {
115 final LayeredIcon icon = new LayeredIcon(2);
116 icon.setIcon(myOpenIcon, 0);
117 icon.setIcon(BASE_POINTER_ICON, 1, -BASE_POINTER_ICON.getIconWidth() / 2, 0);
118 myOpenIcon = icon;
120 myClosedIcon = myOpenIcon;
122 myHighlightedText = new CompositeAppearance();
123 TextAttributes mainTextAttributes = null;
124 if (myColor != null) {
125 mainTextAttributes = new TextAttributes(myColor, null, null, null, Font.PLAIN);
127 if (enclosingElement instanceof PsiMethod) {
128 if (enclosingElement instanceof JspHolderMethod) {
129 PsiFile file = enclosingElement.getContainingFile();
130 myHighlightedText.getEnding().addText(file != null ? file.getName() : IdeBundle.message("node.call.hierarchy.unknown.jsp"), mainTextAttributes);
132 else {
133 final PsiMethod method = (PsiMethod)enclosingElement;
134 final StringBuilder buffer = new StringBuilder(128);
135 final PsiClass containingClass = method.getContainingClass();
136 if (containingClass != null) {
137 buffer.append(ClassPresentationUtil.getNameForClass(containingClass, false));
138 buffer.append('.');
140 final String methodText = PsiFormatUtil.formatMethod(
141 method,
142 PsiSubstitutor.EMPTY, PsiFormatUtil.SHOW_NAME | PsiFormatUtil.SHOW_PARAMETERS,
143 PsiFormatUtil.SHOW_TYPE
145 buffer.append(methodText);
147 myHighlightedText.getEnding().addText(buffer.toString(), mainTextAttributes);
150 else if (JspPsiUtil.isInJspFile(enclosingElement) && enclosingElement instanceof PsiFile) {
151 final JspFile file = JspPsiUtil.getJspFile(enclosingElement);
152 myHighlightedText.getEnding().addText(file.getName(), mainTextAttributes);
154 else {
155 myHighlightedText.getEnding().addText(ClassPresentationUtil.getNameForClass((PsiClass)enclosingElement, false), mainTextAttributes);
157 if (myUsageCount > 1) {
158 myHighlightedText.getEnding().addText(IdeBundle.message("node.call.hierarchy.N.usages", myUsageCount), HierarchyNodeDescriptor.getUsageCountPrefixAttributes());
160 if (!(JspPsiUtil.isInJspFile(enclosingElement) && enclosingElement instanceof PsiFile)) {
161 final String packageName = JavaHierarchyUtil.getPackageName(enclosingElement instanceof PsiMethod ? ((PsiMethod)enclosingElement).getContainingClass() : (PsiClass)enclosingElement);
162 myHighlightedText.getEnding().addText(" (" + packageName + ")", HierarchyNodeDescriptor.getPackageNameAttributes());
164 myName = myHighlightedText.getText();
166 if (
167 !Comparing.equal(myHighlightedText, oldText) ||
168 !Comparing.equal(myOpenIcon, oldOpenIcon)
170 changes = true;
172 return changes;
175 public void addReference(final PsiReference reference) {
176 myReferences.add(reference);
179 public void navigate(boolean requestFocus) {
180 if (!myNavigateToReference) {
181 if (myElement instanceof Navigatable && ((Navigatable)myElement).canNavigate()) {
182 ((Navigatable)myElement).navigate(requestFocus);
184 return;
187 final PsiReference firstReference = myReferences.get(0);
188 final PsiElement element = firstReference.getElement();
189 if (element == null) return;
190 final PsiElement callElement = element.getParent();
191 if (callElement instanceof Navigatable && ((Navigatable)callElement).canNavigate()) {
192 ((Navigatable)callElement).navigate(requestFocus);
193 } else {
194 final PsiFile psiFile = callElement.getContainingFile();
195 if (psiFile == null || psiFile.getVirtualFile() == null) return;
196 FileEditorManager.getInstance(myProject).openFile(psiFile.getVirtualFile(), requestFocus);
199 Editor editor = getEditor(callElement);
201 if (editor != null) {
203 HighlightManager highlightManager = HighlightManager.getInstance(myProject);
204 EditorColorsManager colorManager = EditorColorsManager.getInstance();
205 TextAttributes attributes = colorManager.getGlobalScheme().getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES);
206 ArrayList<RangeHighlighter> highlighters = new ArrayList<RangeHighlighter>();
207 for (PsiReference psiReference : myReferences) {
208 final PsiElement eachElement = psiReference.getElement();
209 if (eachElement != null) {
210 final PsiElement eachMethodCall = eachElement.getParent();
211 if (eachMethodCall != null) {
212 final TextRange textRange = eachMethodCall.getTextRange();
213 highlightManager.addRangeHighlight(editor, textRange.getStartOffset(), textRange.getEndOffset(), attributes, false, highlighters);
220 @Nullable
221 private Editor getEditor(final PsiElement callElement) {
222 final FileEditor editor = FileEditorManager.getInstance(myProject).getSelectedEditor(callElement.getContainingFile().getVirtualFile());
223 if (editor instanceof TextEditor) {
224 return ((TextEditor)editor).getEditor();
225 } else {
226 return null;
230 public boolean canNavigate() {
231 if (!myNavigateToReference) {
232 return myElement instanceof Navigatable && ((Navigatable) myElement).canNavigate();
234 if (myReferences.isEmpty()) return false;
235 final PsiReference firstReference = myReferences.get(0);
236 final PsiElement callElement = firstReference.getElement().getParent();
237 if (callElement == null || !callElement.isValid()) return false;
238 if (!(callElement instanceof Navigatable) || !((Navigatable)callElement).canNavigate()) {
239 final PsiFile psiFile = callElement.getContainingFile();
240 if (psiFile == null) return false;
242 return true;
245 public boolean canNavigateToSource() {
246 return canNavigate();