update copyright
[fedora-idea.git] / xml / dom-openapi / src / com / intellij / util / xml / tree / BaseDomElementNode.java
blobb24e352313a147bab323771f239a92f96782c19a
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.
17 package com.intellij.util.xml.tree;
19 import com.intellij.lang.annotation.HighlightSeverity;
20 import com.intellij.openapi.project.Project;
21 import com.intellij.openapi.util.Key;
22 import com.intellij.psi.xml.XmlFile;
23 import com.intellij.psi.xml.XmlTag;
24 import com.intellij.ui.SimpleTextAttributes;
25 import com.intellij.ui.treeStructure.SimpleNode;
26 import com.intellij.ui.treeStructure.SimpleTree;
27 import com.intellij.util.ReflectionUtil;
28 import com.intellij.util.xml.*;
29 import com.intellij.util.xml.highlighting.DomElementAnnotationsManager;
30 import com.intellij.util.xml.highlighting.DomElementProblemDescriptor;
31 import com.intellij.util.xml.highlighting.DomElementsProblemsHolder;
32 import com.intellij.util.xml.reflect.DomCollectionChildDescription;
33 import com.intellij.util.xml.reflect.DomFixedChildDescription;
34 import com.intellij.util.xml.ui.TooltipUtils;
35 import com.intellij.xml.XmlElementDescriptor;
36 import org.jetbrains.annotations.NotNull;
37 import org.jetbrains.annotations.Nullable;
39 import java.awt.event.InputEvent;
40 import java.awt.event.MouseEvent;
41 import java.lang.reflect.Type;
42 import java.util.*;
45 public class BaseDomElementNode extends AbstractDomElementNode {
46 public static final Key<Comparator<AbstractDomElementNode>> COMPARATOR_KEY = Key.create("COMPARATOR_KEY");
47 public static final Key<List<Class>> CONSOLIDATED_NODES_KEY = Key.create("CONSOLIDATED_NODES_KEY");
48 public static final Key<List<Class>> FOLDER_NODES_KEY = Key.create("FOLDER_NODES_KEY");
50 private final DomElement myRootDomElement;
51 private final DomElement myDomElement;
52 private final String myTagName;
53 private final boolean folder;
55 public BaseDomElementNode(final DomElement modelElement) {
56 this(modelElement, modelElement, null);
59 public BaseDomElementNode(final DomElement modelElement, final DomElement modelRootElement, SimpleNode parent) {
60 super(modelElement, parent);
62 myDomElement = modelElement;
63 myRootDomElement = modelRootElement;
64 myTagName = modelElement.getXmlElementName();
65 folder = isMarkedType(modelElement.getDomElementType(), FOLDER_NODES_KEY);
68 public SimpleNode[] getChildren() {
69 return doGetChildren(myDomElement);
72 public void handleDoubleClickOrEnter(SimpleTree tree, InputEvent inputEvent) {
73 if (inputEvent instanceof MouseEvent) {
74 inputEvent.consume();
76 final DomElement domElement = getDomElement();
77 if (domElement.isValid()) {
78 final DomElementNavigationProvider provider = DomElementsNavigationManager.getManager(domElement.getManager().getProject())
79 .getDomElementsNavigateProvider(DomElementsNavigationManager.DEFAULT_PROVIDER_NAME);
81 provider.navigate(domElement, true);
85 protected final SimpleNode[] doGetChildren(final DomElement element) {
86 if (!element.isValid()) return NO_CHILDREN;
88 List<SimpleNode> children = new ArrayList<SimpleNode>();
89 final XmlTag tag = element.getXmlTag();
91 if (tag != null && !(tag.getContainingFile() instanceof XmlFile)) return NO_CHILDREN;
92 final XmlElementDescriptor xmlElementDescriptor = tag == null ? null : tag.getDescriptor();
93 final XmlElementDescriptor[] xmlDescriptors = xmlElementDescriptor == null ? null : xmlElementDescriptor.getElementsDescriptors(tag);
95 for (DomFixedChildDescription description : element.getGenericInfo().getFixedChildrenDescriptions()) {
96 String childName = description.getXmlElementName();
97 if (xmlDescriptors != null) {
98 if (findDescriptor(xmlDescriptors, childName) == -1) continue;
100 final List<? extends DomElement> values = description.getStableValues(element);
101 if (shouldBeShown(description.getType())) {
102 if (DomUtil.isGenericValueType(description.getType())) {
103 for (DomElement value : values) {
104 children.add(new GenericValueNode((GenericDomValue)value, this));
107 else {
108 for (DomElement domElement : values) {
109 children.add(new BaseDomElementNode(domElement, myRootDomElement, this));
115 for (DomCollectionChildDescription description : element.getGenericInfo().getCollectionChildrenDescriptions()) {
116 if (shouldBeShown(description.getType())) {
117 DomElementsGroupNode groupNode = new DomElementsGroupNode(element, description, this, myRootDomElement);
118 if (isMarkedType(description.getType(), CONSOLIDATED_NODES_KEY)) {
119 Collections.addAll(children, groupNode.getChildren());
121 else {
122 children.add(groupNode);
127 AbstractDomElementNode[] childrenNodes = children.toArray(new AbstractDomElementNode[children.size()]);
129 Comparator<AbstractDomElementNode> comparator = DomUtil.getFile(myDomElement).getUserData(COMPARATOR_KEY);
130 if (comparator == null) {
131 comparator = getDefaultComparator(element);
133 if (comparator != null) {
134 Arrays.sort(childrenNodes, comparator);
137 return childrenNodes;
140 @Nullable
141 protected Comparator<AbstractDomElementNode> getDefaultComparator(DomElement element) {
142 final XmlTag tag = element.getXmlTag();
143 if (tag != null) {
144 final XmlElementDescriptor descriptor = tag.getDescriptor();
145 if (descriptor != null) {
146 final XmlElementDescriptor[] childDescriptors = descriptor.getElementsDescriptors(tag);
147 if (childDescriptors != null && childDescriptors.length > 1) {
148 return new Comparator<AbstractDomElementNode>() {
149 public int compare(final AbstractDomElementNode o1, final AbstractDomElementNode o2) {
150 return findDescriptor(childDescriptors, o1.getTagName()) - findDescriptor(childDescriptors, o2.getTagName());
156 return null;
159 protected static int findDescriptor(XmlElementDescriptor[] descriptors, String name) {
160 for (int i = 0; i < descriptors.length; i++) {
161 if (descriptors[i].getDefaultName().equals(name)) {
162 return i;
165 return -1;
168 @NotNull
169 public List<DomCollectionChildDescription> getConsolidatedChildrenDescriptions() {
170 if (!myDomElement.isValid()) return Collections.emptyList();
172 final List<DomCollectionChildDescription> consolidated = new ArrayList<DomCollectionChildDescription>();
173 for (DomCollectionChildDescription description : myDomElement.getGenericInfo().getCollectionChildrenDescriptions()) {
174 if (isMarkedType(description.getType(), CONSOLIDATED_NODES_KEY)) {
175 consolidated.add(description);
178 return consolidated;
181 public Object[] getEqualityObjects() {
182 return new Object[]{myDomElement};
185 protected void doUpdate() {
186 if (!myDomElement.isValid()) return;
187 final Project project = myDomElement.getManager().getProject();
188 if (project.isDisposed()) return;
190 setUniformIcon(getNodeIcon());
191 clearColoredText();
193 final DomElementAnnotationsManager manager = DomElementAnnotationsManager.getInstance(project);
194 final DomElementsProblemsHolder holder = manager.getCachedProblemHolder(myDomElement);
195 final List<DomElementProblemDescriptor> problems =
196 holder.getProblems(myDomElement, highlightIfChildrenHaveProblems(), HighlightSeverity.ERROR);
198 if (problems.size() > 0) {
199 final String toolTip = TooltipUtils.getTooltipText(problems);
200 addColoredFragment(getNodeName(), toolTip, getWavedAttributes(SimpleTextAttributes.STYLE_PLAIN));
201 if (isShowContainingFileInfo()) {
202 addColoredFragment(" (" + DomUtil.getFile(myDomElement).getName() + ")", toolTip, SimpleTextAttributes.GRAY_ATTRIBUTES);
205 else if (myDomElement.getXmlTag() == null && !(myDomElement instanceof DomFileElement)) {
206 addColoredFragment(getNodeName(), folder ? SimpleTextAttributes.GRAYED_BOLD_ATTRIBUTES : SimpleTextAttributes.GRAYED_ATTRIBUTES);
208 else if (folder) {
209 addColoredFragment(getNodeName(), SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
210 final int childrenCount = getChildren().length;
211 addColoredFragment(" (" + childrenCount + ')', SimpleTextAttributes.GRAY_ATTRIBUTES);
213 else {
214 addColoredFragment(getNodeName(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
216 if (isShowContainingFileInfo()) {
217 addColoredFragment(" (" + DomUtil.getFile(myDomElement).getName() + ")", SimpleTextAttributes.GRAY_ATTRIBUTES);
222 protected boolean isMarkedType(Type type, Key<List<Class>> key) {
223 if (type == null) {
224 return false;
226 final List<Class> classes = DomUtil.getFile(getDomElement()).getUserData(key);
227 if (classes != null) {
228 Class clazz = ReflectionUtil.getRawType(type);
229 return classes.contains(clazz);
231 return false;
234 protected boolean highlightIfChildrenHaveProblems() {
235 return true;
238 public String getNodeName() {
239 if (!myDomElement.isValid()) return "";
241 final String name = myDomElement.getPresentation().getElementName();
242 return name != null && name.trim().length() > 0 ? name : getPropertyName();
245 public String getTagName() {
246 return myTagName;
249 public DomElement getDomElement() {
250 return myDomElement;
253 public boolean isAutoExpandNode() {
254 return getParent() == null;
257 public boolean expandOnDoubleClick() {
258 return true;
261 public boolean isShowContainingFileInfo() {
262 if (!myRootDomElement.isValid()) return false;
263 DomElement root = myRootDomElement;
264 while (root instanceof StableElement) {
265 root = ((StableElement<DomElement>) root).getWrappedElement();
267 return root instanceof MergedObject && ((MergedObject)root).getImplementations().size() > 1;