1 package com
.intellij
.util
.xml
.tree
;
3 import com
.intellij
.lang
.annotation
.HighlightSeverity
;
4 import com
.intellij
.openapi
.util
.Key
;
5 import com
.intellij
.psi
.xml
.XmlTag
;
6 import com
.intellij
.ui
.SimpleTextAttributes
;
7 import com
.intellij
.ui
.treeStructure
.SimpleNode
;
8 import com
.intellij
.ui
.treeStructure
.SimpleTree
;
9 import com
.intellij
.util
.xml
.*;
10 import com
.intellij
.util
.xml
.highlighting
.DomElementAnnotationsManager
;
11 import com
.intellij
.util
.xml
.highlighting
.DomElementProblemDescriptor
;
12 import com
.intellij
.util
.xml
.highlighting
.DomElementsProblemsHolder
;
13 import com
.intellij
.util
.xml
.reflect
.DomCollectionChildDescription
;
14 import com
.intellij
.util
.xml
.reflect
.DomFixedChildDescription
;
15 import com
.intellij
.util
.xml
.ui
.TooltipUtils
;
16 import com
.intellij
.xml
.XmlElementDescriptor
;
17 import org
.jetbrains
.annotations
.NotNull
;
18 import org
.jetbrains
.annotations
.Nullable
;
20 import java
.awt
.event
.InputEvent
;
21 import java
.awt
.event
.MouseEvent
;
22 import java
.lang
.reflect
.Type
;
26 public class BaseDomElementNode
extends AbstractDomElementNode
{
27 public static final Key
<Comparator
<AbstractDomElementNode
>> COMPARATOR_KEY
= Key
.create("COMPARATOR_KEY");
28 public static final Key
<List
<Class
>> CONSOLIDATED_NODES_KEY
= Key
.create("CONSOLIDATED_NODES_KEY");
29 public static final Key
<List
<Class
>> FOLDER_NODES_KEY
= Key
.create("FOLDER_NODES_KEY");
31 private final DomElement myDomElement
;
32 private final String myTagName
;
33 private final boolean folder
;
35 public BaseDomElementNode(final DomElement modelElement
) {
36 this(modelElement
, null);
39 public BaseDomElementNode(final DomElement modelElement
, SimpleNode parent
) {
40 super(modelElement
, parent
);
42 myDomElement
= modelElement
;
43 myTagName
= modelElement
.getXmlElementName();
44 folder
= isMarkedType(modelElement
.getDomElementType(), FOLDER_NODES_KEY
);
47 public SimpleNode
[] getChildren() {
48 return doGetChildren(myDomElement
);
51 public void handleDoubleClickOrEnter(SimpleTree tree
, InputEvent inputEvent
) {
52 if (inputEvent
instanceof MouseEvent
) {
55 final DomElement domElement
= getDomElement();
56 if (domElement
.isValid()) {
57 final DomElementNavigationProvider provider
= DomElementsNavigationManager
.getManager(domElement
.getManager().getProject())
58 .getDomElementsNavigateProvider(DomElementsNavigationManager
.DEFAULT_PROVIDER_NAME
);
60 provider
.navigate(domElement
, true);
64 protected final SimpleNode
[] doGetChildren(final DomElement element
) {
65 if (!element
.isValid()) return NO_CHILDREN
;
67 List
<SimpleNode
> children
= new ArrayList
<SimpleNode
>();
68 final XmlTag tag
= element
.getXmlTag();
69 final XmlElementDescriptor xmlElementDescriptor
= tag
== null ?
null : tag
.getDescriptor();
70 final XmlElementDescriptor
[] xmlDescriptors
= xmlElementDescriptor
== null ?
null : xmlElementDescriptor
.getElementsDescriptors(tag
);
72 for (DomFixedChildDescription description
: element
.getGenericInfo().getFixedChildrenDescriptions()) {
73 String childName
= description
.getXmlElementName();
74 if (xmlDescriptors
!= null) {
75 if (findDescriptor(xmlDescriptors
, childName
) == -1) continue;
77 final List
<?
extends DomElement
> values
= description
.getStableValues(element
);
78 if (shouldBeShown(description
.getType())) {
79 if (DomUtil
.isGenericValueType(description
.getType())) {
80 for (DomElement value
: values
) {
81 children
.add(new GenericValueNode((GenericDomValue
)value
, this));
85 for (DomElement domElement
: values
) {
86 children
.add(new BaseDomElementNode(domElement
, this));
92 for (DomCollectionChildDescription description
: element
.getGenericInfo().getCollectionChildrenDescriptions()) {
93 if (shouldBeShown(description
.getType())) {
94 DomElementsGroupNode groupNode
= new DomElementsGroupNode(element
, description
, this);
95 if (isMarkedType(description
.getType(), CONSOLIDATED_NODES_KEY
)) {
96 Collections
.addAll(children
, groupNode
.getChildren());
99 children
.add(groupNode
);
104 AbstractDomElementNode
[] childrenNodes
= children
.toArray(new AbstractDomElementNode
[children
.size()]);
106 Comparator
<AbstractDomElementNode
> comparator
= myDomElement
.getRoot().getFile().getUserData(COMPARATOR_KEY
);
107 if (comparator
== null) {
108 comparator
= getDefaultComparator(element
);
110 if (comparator
!= null) {
111 Arrays
.sort(childrenNodes
, comparator
);
114 return childrenNodes
;
118 protected Comparator
<AbstractDomElementNode
> getDefaultComparator(DomElement element
) {
119 final XmlTag tag
= element
.getXmlTag();
121 final XmlElementDescriptor descriptor
= tag
.getDescriptor();
122 if (descriptor
!= null) {
123 final XmlElementDescriptor
[] childDescriptors
= descriptor
.getElementsDescriptors(tag
);
124 if (childDescriptors
!= null && childDescriptors
.length
> 1) {
125 return new Comparator
<AbstractDomElementNode
>() {
126 public int compare(final AbstractDomElementNode o1
, final AbstractDomElementNode o2
) {
127 return findDescriptor(childDescriptors
, o1
.getTagName()) - findDescriptor(childDescriptors
, o2
.getTagName());
136 protected static int findDescriptor(XmlElementDescriptor
[] descriptors
, String name
) {
137 for (int i
= 0; i
< descriptors
.length
; i
++) {
138 if (descriptors
[i
].getDefaultName().equals(name
)) {
146 public List
<DomCollectionChildDescription
> getConsolidatedChildrenDescriptions() {
147 if (!myDomElement
.isValid()) return Collections
.emptyList();
149 final List
<DomCollectionChildDescription
> consolidated
= new ArrayList
<DomCollectionChildDescription
>();
150 for (DomCollectionChildDescription description
: myDomElement
.getGenericInfo().getCollectionChildrenDescriptions()) {
151 if (isMarkedType(description
.getType(), CONSOLIDATED_NODES_KEY
)) {
152 consolidated
.add(description
);
158 public Object
[] getEqualityObjects() {
159 return new Object
[]{myDomElement
};
162 protected void doUpdate() {
163 if (!myDomElement
.isValid()) return;
165 setUniformIcon(getNodeIcon());
168 final DomElementAnnotationsManager manager
= DomElementAnnotationsManager
.getInstance(myDomElement
.getManager().getProject());
169 final DomElementsProblemsHolder holder
= manager
.getCachedProblemHolder(myDomElement
);
170 final List
<DomElementProblemDescriptor
> problems
=
171 holder
.getProblems(myDomElement
, true, highlightIfChildrenHaveProblems(), HighlightSeverity
.ERROR
);
173 if (problems
.size() > 0) {
174 addColoredFragment(getNodeName(), TooltipUtils
.getTooltipText(problems
), getWavedAttributes(SimpleTextAttributes
.STYLE_PLAIN
));
176 else if (myDomElement
.getXmlTag() == null && !(myDomElement
instanceof DomFileElement
)) {
177 addColoredFragment(getNodeName(), folder ? SimpleTextAttributes
.GRAYED_BOLD_ATTRIBUTES
: SimpleTextAttributes
.GRAYED_ATTRIBUTES
);
180 addColoredFragment(getNodeName(), SimpleTextAttributes
.REGULAR_BOLD_ATTRIBUTES
);
181 final int childrenCount
= getChildren().length
;
182 addColoredFragment(" (" + childrenCount
+ ')', SimpleTextAttributes
.GRAY_ITALIC_ATTRIBUTES
);
185 addColoredFragment(getNodeName(), SimpleTextAttributes
.REGULAR_ATTRIBUTES
);
189 protected boolean isMarkedType(Type type
, Key
<List
<Class
>> key
) {
193 final List
<Class
> classes
= getDomElement().getRoot().getFile().getUserData(key
);
194 if (classes
!= null) {
195 Class clazz
= DomReflectionUtil
.getRawType(type
);
196 return classes
.contains(clazz
);
201 protected boolean highlightIfChildrenHaveProblems() {
205 public String
getNodeName() {
206 if (!myDomElement
.isValid()) return "";
208 final String name
= myDomElement
.getPresentation().getElementName();
209 return name
!= null && name
.trim().length() > 0 ? name
: getPropertyName();
212 public String
getTagName() {
216 public DomElement
getDomElement() {
220 public boolean isAutoExpandNode() {
221 return getParent() == null;
224 public boolean expandOnDoubleClick() {