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
.method
;
18 import com
.intellij
.ide
.IdeBundle
;
19 import com
.intellij
.ide
.hierarchy
.HierarchyNodeDescriptor
;
20 import com
.intellij
.ide
.hierarchy
.JavaHierarchyUtil
;
21 import com
.intellij
.openapi
.editor
.markup
.TextAttributes
;
22 import com
.intellij
.openapi
.project
.Project
;
23 import com
.intellij
.openapi
.roots
.ui
.util
.CompositeAppearance
;
24 import com
.intellij
.openapi
.util
.Comparing
;
25 import com
.intellij
.openapi
.util
.IconLoader
;
26 import com
.intellij
.openapi
.util
.Iconable
;
27 import com
.intellij
.psi
.PsiClass
;
28 import com
.intellij
.psi
.PsiElement
;
29 import com
.intellij
.psi
.PsiMethod
;
30 import com
.intellij
.psi
.PsiModifier
;
31 import com
.intellij
.psi
.presentation
.java
.ClassPresentationUtil
;
32 import com
.intellij
.ui
.LayeredIcon
;
33 import com
.intellij
.ui
.RowIcon
;
38 public final class MethodHierarchyNodeDescriptor
extends HierarchyNodeDescriptor
{
39 private static final Icon METHOD_DEFINED_ICON
= IconLoader
.getIcon("/hierarchy/methodDefined.png");
40 private static final Icon METHOD_NOT_DEFINED_ICON
= IconLoader
.getIcon("/hierarchy/methodNotDefined.png");
41 private static final Icon SHOULD_DEFINE_METHOD_ICON
= IconLoader
.getIcon("/hierarchy/shouldDefineMethod.png");
43 private Icon myRawIcon
;
44 private Icon myStateIcon
;
45 private MethodHierarchyTreeStructure myTreeStructure
;
47 public MethodHierarchyNodeDescriptor(
48 final Project project
,
49 final HierarchyNodeDescriptor parentDescriptor
,
50 final PsiClass aClass
,
52 final MethodHierarchyTreeStructure treeStructure
54 super(project
, parentDescriptor
, aClass
, isBase
);
55 myTreeStructure
= treeStructure
;
58 public final void setTreeStructure(final MethodHierarchyTreeStructure treeStructure
) {
59 myTreeStructure
= treeStructure
;
62 private PsiMethod
getMethod(final PsiClass aClass
, final boolean checkBases
) {
63 return MethodHierarchyUtil
.findBaseMethodInClass(myTreeStructure
.getBaseMethod(), aClass
, checkBases
);
66 public final PsiClass
getPsiClass() {
67 return (PsiClass
)myElement
;
71 * Element for OpenFileDescriptor
73 public final PsiElement
getTargetElement() {
74 final PsiClass aClass
= getPsiClass();
75 if (aClass
== null || !aClass
.isValid()) return null;
76 final PsiMethod method
= getMethod(aClass
, false);
77 if (method
!= null) return method
;
81 public final boolean isValid() {
82 final PsiClass aClass
= getPsiClass();
83 return aClass
!= null && aClass
.isValid();
86 public final boolean update() {
87 int flags
= Iconable
.ICON_FLAG_VISIBILITY
;
88 if (isMarkReadOnly()){
89 flags
|= Iconable
.ICON_FLAG_READ_STATUS
;
92 boolean changes
= super.update();
94 final PsiClass psiClass
= getPsiClass();
96 if (psiClass
== null){
97 final String invalidPrefix
= IdeBundle
.message("node.hierarchy.invalid");
98 if (!myHighlightedText
.getText().startsWith(invalidPrefix
)) {
99 myHighlightedText
.getBeginning().addText(invalidPrefix
, HierarchyNodeDescriptor
.getInvalidPrefixAttributes());
104 final Icon newRawIcon
= psiClass
.getIcon(flags
);
105 final Icon newStateIcon
= calculateState(psiClass
);
107 if (newRawIcon
!= myRawIcon
|| newStateIcon
!= myStateIcon
) {
110 myRawIcon
= newRawIcon
;
111 myStateIcon
= newStateIcon
;
113 myOpenIcon
= myRawIcon
;
116 final LayeredIcon icon
= new LayeredIcon(2);
117 icon
.setIcon(myOpenIcon
, 0);
118 icon
.setIcon(BASE_POINTER_ICON
, 1, -BASE_POINTER_ICON
.getIconWidth() / 2, 0);
122 if (myStateIcon
!= null) {
123 final RowIcon icon
= new RowIcon(2);
124 icon
.setIcon(myStateIcon
, 0);
125 icon
.setIcon(myOpenIcon
, 1);
129 myClosedIcon
= myOpenIcon
;
132 final CompositeAppearance oldText
= myHighlightedText
;
134 myHighlightedText
= new CompositeAppearance();
135 TextAttributes classNameAttributes
= null;
136 if (myColor
!= null) {
137 classNameAttributes
= new TextAttributes(myColor
, null, null, null, Font
.PLAIN
);
139 myHighlightedText
.getEnding().addText(ClassPresentationUtil
.getNameForClass(psiClass
, false), classNameAttributes
);
140 myHighlightedText
.getEnding().addText(" (" + JavaHierarchyUtil
.getPackageName(psiClass
) + ")", HierarchyNodeDescriptor
.getPackageNameAttributes());
141 myName
= myHighlightedText
.getText();
143 if (!Comparing
.equal(myHighlightedText
, oldText
)) {
149 private Icon
calculateState(final PsiClass psiClass
) {
150 final PsiMethod method
= getMethod(psiClass
, false);
151 if (method
!= null) {
152 if (method
.hasModifierProperty(PsiModifier
.ABSTRACT
)) {
155 return METHOD_DEFINED_ICON
;
158 if (myTreeStructure
.isSuperClassForBaseClass(psiClass
)) {
159 return METHOD_NOT_DEFINED_ICON
;
162 final boolean isAbstractClass
= psiClass
.hasModifierProperty(PsiModifier
.ABSTRACT
);
164 // was it implemented is in superclasses?
165 final PsiMethod baseClassMethod
= getMethod(psiClass
, true);
167 final boolean hasBaseImplementation
= baseClassMethod
!= null && !baseClassMethod
.hasModifierProperty(PsiModifier
.ABSTRACT
);
169 if (hasBaseImplementation
|| isAbstractClass
) {
170 return METHOD_NOT_DEFINED_ICON
;
173 return SHOULD_DEFINE_METHOD_ICON
;