minor fix
[fedora-idea.git] / dom / openapi / src / com / intellij / util / xml / tree / BaseDomElementNode.java
blob715f9a222ff3879094699ed9de515afef76dfb38
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;
23 import java.util.*;
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) {
53 inputEvent.consume();
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));
84 else {
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());
98 else {
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;
117 @Nullable
118 protected Comparator<AbstractDomElementNode> getDefaultComparator(DomElement element) {
119 final XmlTag tag = element.getXmlTag();
120 if (tag != null) {
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());
133 return null;
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)) {
139 return i;
142 return -1;
145 @NotNull
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);
155 return consolidated;
158 public Object[] getEqualityObjects() {
159 return new Object[]{myDomElement};
162 protected void doUpdate() {
163 if (!myDomElement.isValid()) return;
165 setUniformIcon(getNodeIcon());
166 clearColoredText();
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);
179 else if (folder) {
180 addColoredFragment(getNodeName(), SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
181 final int childrenCount = getChildren().length;
182 addColoredFragment(" (" + childrenCount + ')', SimpleTextAttributes.GRAY_ITALIC_ATTRIBUTES);
184 else {
185 addColoredFragment(getNodeName(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
189 protected boolean isMarkedType(Type type, Key<List<Class>> key) {
190 if (type == null) {
191 return false;
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);
198 return false;
201 protected boolean highlightIfChildrenHaveProblems() {
202 return true;
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() {
213 return myTagName;
216 public DomElement getDomElement() {
217 return myDomElement;
220 public boolean isAutoExpandNode() {
221 return getParent() == null;
224 public boolean expandOnDoubleClick() {
225 return false;