From 1a2ac0a2d36858227f11b9ca74943b9fbd93faec Mon Sep 17 00:00:00 2001 From: Sergey Vasiliev Date: Tue, 4 Apr 2006 16:22:10 +0400 Subject: [PATCH] dom elements highlighting --- .../daemon/impl/analysis/XmlHighlightVisitor.java | 60 ++++++------ icons/src/general/exclMark.png | Bin 0 -> 272 bytes .../highlighting/DomElementAnnotationsManager.java | 3 + .../highlighting/DomElementsProblemsHolder.java | 4 + .../util/xml/ui/ChildGenericValueColumnInfo.java | 19 +++- .../src/com/intellij/util/xml/ui/DomTableView.java | 7 +- .../util/xml/ui/ErrorableTableCellRenderer.java | 102 +++++++++++++++++++++ resources/src/componentSets/UICore.xml | 4 + .../com/intellij/ide/commander/CommanderPanel.java | 2 +- .../DomElementAnnotationsManagerImpl.java | 45 +++++---- .../DomElementProblemDescriptorImpl.java | 24 ++++- .../DomElementsProblemsHolderImpl.java | 58 +++++++++++- .../util/xml/tree/AbstractDomElementNode.java | 9 ++ .../intellij/util/xml/tree/BaseDomElementNode.java | 10 +- .../util/xml/tree/DomElementsGroupNode.java | 19 +++- .../util/xml/tree/DomModelTreeStructure.java | 6 +- .../intellij/util/xml/tree/DomModelTreeView.java | 21 +++++ ui/impl/com/intellij/ui/ListToolTipHandler.java | 7 +- ui/impl/com/intellij/ui/TableToolTipHandler.java | 2 +- .../intellij/ui/ToolTipHandlerProviderImpl.java | 42 +++++++++ .../com/intellij/ui/ToolTipHandlerProvider.java | 20 ++-- 21 files changed, 389 insertions(+), 75 deletions(-) create mode 100644 icons/src/general/exclMark.png create mode 100644 openapi/src/com/intellij/util/xml/ui/ErrorableTableCellRenderer.java create mode 100644 ui/impl/com/intellij/ui/ToolTipHandlerProviderImpl.java copy openapi/src/com/intellij/util/xml/highlighting/DomElementsProblemsHolder.java => ui/openapi/com/intellij/ui/ToolTipHandlerProvider.java (54%) diff --git a/codeInsight/impl/com/intellij/codeInsight/daemon/impl/analysis/XmlHighlightVisitor.java b/codeInsight/impl/com/intellij/codeInsight/daemon/impl/analysis/XmlHighlightVisitor.java index b4967b7880..973f610304 100644 --- a/codeInsight/impl/com/intellij/codeInsight/daemon/impl/analysis/XmlHighlightVisitor.java +++ b/codeInsight/impl/com/intellij/codeInsight/daemon/impl/analysis/XmlHighlightVisitor.java @@ -67,7 +67,7 @@ import java.text.MessageFormat; import java.util.*; /** - * @author Mike + * @author Mike */ public class XmlHighlightVisitor extends PsiElementVisitor implements Validator.ValidationHost { private static final Logger LOG = LoggerFactory.getInstance().getLoggerInstance( @@ -836,31 +836,8 @@ public class XmlHighlightVisitor extends PsiElementVisitor implements Validator. for (final PsiReference reference : references) { if (reference != null) { if (!reference.isSoft()) { - boolean hasBadResolve; - - if (reference instanceof PsiPolyVariantReference) { - hasBadResolve = ((PsiPolyVariantReference)reference).multiResolve(false).length == 0; - } else { - hasBadResolve = reference.resolve() == null; - } - - if(hasBadResolve) { - String message; - if (reference instanceof EmptyResolveMessageProvider) { - message = ((EmptyResolveMessageProvider)reference).getUnresolvedMessagePattern(); - } - else { - message = XmlErrorMessages.message("cannot.resolve.symbol"); - } - - String description; - try { - description = MessageFormat.format(message, reference.getCanonicalText()); - } catch(IllegalArgumentException ex) { - // unresolvedMessage provided by third-party reference contains wrong format string (e.g. {}), tolerate it - description = message; - LOG.warn(XmlErrorMessages.message("plugin.reference.message.problem",reference.getClass().getName(),message)); - } + if(hasBadResolve(reference)) { + String description = getErrorDescription(reference); HighlightInfo info = HighlightInfo.createHighlightInfo( getTagProblemInfoType(PsiTreeUtil.getParentOfType(value, XmlTag.class)), @@ -881,6 +858,37 @@ public class XmlHighlightVisitor extends PsiElementVisitor implements Validator. } } + public static String getErrorDescription(final PsiReference reference) { + String message; + if (reference instanceof EmptyResolveMessageProvider) { + message = ((EmptyResolveMessageProvider)reference).getUnresolvedMessagePattern(); + } + else { + message = XmlErrorMessages.message("cannot.resolve.symbol"); + } + + String description; + try { + description = MessageFormat.format(message, reference.getCanonicalText()); + } catch(IllegalArgumentException ex) { + // unresolvedMessage provided by third-party reference contains wrong format string (e.g. {}), tolerate it + description = message; + LOG.warn(XmlErrorMessages.message("plugin.reference.message.problem",reference.getClass().getName(),message)); + } + return description; + } + + public static boolean hasBadResolve(final PsiReference reference) { + boolean hasBadResolve; + + if (reference instanceof PsiPolyVariantReference) { + hasBadResolve = ((PsiPolyVariantReference)reference).multiResolve(false).length == 0; + } else { + hasBadResolve = reference.resolve() == null; + } + return hasBadResolve; + } + public void visitXmlDoctype(XmlDoctype xmlDoctype) { if (xmlDoctype.getUserData(DO_NOT_VALIDATE_KEY) != null) return; final PsiReference[] references = xmlDoctype.getReferences(); diff --git a/icons/src/general/exclMark.png b/icons/src/general/exclMark.png new file mode 100644 index 0000000000000000000000000000000000000000..a07b8f0f34c9a8b253c1bacb8b49327846d09681 GIT binary patch literal 272 zcwXxa@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Ea{HEjtmUzPnffIy#(?lOI#yL zg7ec#$`gxH85~pclTsBta}(23gHjVyDhp4h+5ip4-h8YqX zEDVe;8yOiGTP`=qo5i>{{;(H#e getProblems(DomElement domElement); + public abstract List getProblems(DomElement domElement, boolean includeXmlProblems); + public abstract List getProblems(DomElement domElement, boolean includeXmlProblems, boolean withChildren); + public abstract List getDomElementsAnnotators(DomElement domElement); public abstract void registerDomElementsAnnotator(DomElementsAnnotator annotator, Class aClass); diff --git a/openapi/src/com/intellij/util/xml/highlighting/DomElementsProblemsHolder.java b/openapi/src/com/intellij/util/xml/highlighting/DomElementsProblemsHolder.java index 8e32c79d6d..9c1905a1c1 100644 --- a/openapi/src/com/intellij/util/xml/highlighting/DomElementsProblemsHolder.java +++ b/openapi/src/com/intellij/util/xml/highlighting/DomElementsProblemsHolder.java @@ -29,5 +29,9 @@ public interface DomElementsProblemsHolder { List getProblems(DomElement domElement); + List getProblems(DomElement domElement, boolean includeXmlProblems); + + List getProblems(DomElement domElement, boolean includeXmlProblems, boolean withChildren); + List getProblems(DomElement domElement, ProblemHighlightType severity); } diff --git a/openapi/src/com/intellij/util/xml/ui/ChildGenericValueColumnInfo.java b/openapi/src/com/intellij/util/xml/ui/ChildGenericValueColumnInfo.java index c36be2de74..f950421965 100644 --- a/openapi/src/com/intellij/util/xml/ui/ChildGenericValueColumnInfo.java +++ b/openapi/src/com/intellij/util/xml/ui/ChildGenericValueColumnInfo.java @@ -16,11 +16,14 @@ import javax.swing.table.TableCellRenderer; /** * @author peter */ -public class ChildGenericValueColumnInfo extends DomColumnInfo { +public class ChildGenericValueColumnInfo extends DomColumnInfo { private final TableCellEditor myEditor; private final DomFixedChildDescription myChildDescription; - public ChildGenericValueColumnInfo(final String name, final DomFixedChildDescription description, final TableCellRenderer renderer, final TableCellEditor editor) { + public ChildGenericValueColumnInfo(final String name, + final DomFixedChildDescription description, + final TableCellRenderer renderer, + final TableCellEditor editor) { super(name, renderer); myEditor = editor; myChildDescription = description; @@ -38,6 +41,15 @@ public class ChildGenericValueColumnInfo extends DomColumn return (Class)DomUtil.getRawType(myChildDescription.getType()); } + public TableCellRenderer getCustomizedRenderer(final T domElement, final TableCellRenderer renderer) { + return getErroableCellRenderer(renderer, domElement); + + } + + public DefaultTableCellRenderer getErroableCellRenderer(final TableCellRenderer renderer, final T domElement) { + return new ErrorableTableCellRenderer(getGenericValue(domElement), renderer, domElement); + } + public void setValue(final T o, final String aValue) { getGenericValue(o).setStringValue(aValue); } @@ -49,7 +61,7 @@ public class ChildGenericValueColumnInfo extends DomColumn public final String valueOf(T object) { if (!object.isValid()) return null; final String stringValue = getGenericValue(object).getStringValue(); - return StringUtil.isEmpty(stringValue) ? getEmptyValuePresentation(object): stringValue; + return StringUtil.isEmpty(stringValue) ? getEmptyValuePresentation(object) : stringValue; } protected final DomFixedChildDescription getChildDescription() { @@ -59,4 +71,5 @@ public class ChildGenericValueColumnInfo extends DomColumn protected String getEmptyValuePresentation(T object) { return ""; } + } diff --git a/openapi/src/com/intellij/util/xml/ui/DomTableView.java b/openapi/src/com/intellij/util/xml/ui/DomTableView.java index b408c300e7..10e4489f8f 100644 --- a/openapi/src/com/intellij/util/xml/ui/DomTableView.java +++ b/openapi/src/com/intellij/util/xml/ui/DomTableView.java @@ -14,9 +14,11 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; import com.intellij.ui.PopupHandler; import com.intellij.ui.ScrollPaneFactory; +import com.intellij.ui.ToolTipHandlerProvider; import com.intellij.ui.table.TableView; import com.intellij.util.ui.ColumnInfo; import com.intellij.util.ui.ListTableModel; +import com.intellij.util.ui.treetable.ListTreeTableModelOnColumns; import com.intellij.util.Icons; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; @@ -71,7 +73,9 @@ public abstract class DomTableView extends JPanel { private final JPanel myInnerPanel; protected TableCellRenderer getTableCellRenderer(final int row, final int column, final TableCellRenderer superRenderer, final Object value) { - return new StripeTableCellRenderer(superRenderer); + final ColumnInfo columnInfo = (getTableModel()).getColumnInfos()[column]; + + return columnInfo.getCustomizedRenderer(value, new StripeTableCellRenderer(superRenderer)); } protected DomTableView() { @@ -85,6 +89,7 @@ public abstract class DomTableView extends JPanel { myEmptyPaneText = emptyPaneText; myHelpID = helpID; + ToolTipHandlerProvider.getToolTipHandlerProvider().install(myTable); final JTableHeader header = myTable.getTableHeader(); header.addMouseMotionListener(new MouseMotionAdapter() { diff --git a/openapi/src/com/intellij/util/xml/ui/ErrorableTableCellRenderer.java b/openapi/src/com/intellij/util/xml/ui/ErrorableTableCellRenderer.java new file mode 100644 index 0000000000..a1abb33ebc --- /dev/null +++ b/openapi/src/com/intellij/util/xml/ui/ErrorableTableCellRenderer.java @@ -0,0 +1,102 @@ +/* + * Copyright 2000-2006 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.intellij.util.xml.ui; + +import com.intellij.util.xml.highlighting.DomElementProblemDescription; +import com.intellij.util.xml.highlighting.DomElementAnnotationsManager; +import com.intellij.util.xml.DomElement; +import com.intellij.openapi.util.IconLoader; + +import javax.swing.table.DefaultTableCellRenderer; +import javax.swing.table.TableCellRenderer; +import javax.swing.*; +import java.awt.*; + +public class ErrorableTableCellRenderer extends DefaultTableCellRenderer { + private final TableCellRenderer myRenderer; + private final T myRowDomElement; + private T myCellValueDomElement; + + + public ErrorableTableCellRenderer(final T cellValueDomElement, + final TableCellRenderer renderer, + final T rowDomElement) { + myCellValueDomElement = cellValueDomElement; + myRenderer = renderer; + myRowDomElement = rowDomElement; + + } + + public Component getTableCellRendererComponent(JTable table, + Object value, + boolean isSelected, + boolean hasFocus, + int row, + int column) { + final Component component = myRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + + final java.util.List problems = + DomElementAnnotationsManager.getInstance().getProblems(myCellValueDomElement, true); + + final boolean hasErrors = problems.size() > 0; + if (hasErrors) { + component.setForeground(Color.RED); + } + else { + component.setForeground(isSelected ? table.getSelectionForeground() : table.getForeground()); + } + + + final java.util.List problemDescriptions = + DomElementAnnotationsManager.getInstance().getProblems(myRowDomElement, true, true); + + if (table.getModel().getColumnCount() - 1 == column && problemDescriptions.size() > 0) { + final JPanel wrapper = new JPanel(new BorderLayout()); + wrapper.add(component, BorderLayout.CENTER); + + wrapper.setBackground(component.getBackground()); + + final JLabel errorLabel = new JLabel(getErrorIcon()); + + ToolTipManager.sharedInstance().registerComponent(errorLabel); + + wrapper.setToolTipText(TooltipUtils.getTooltipText(problemDescriptions)); + + wrapper.add(errorLabel, BorderLayout.EAST); + + if(component instanceof JComponent) { + wrapper.setBorder(((JComponent)component).getBorder()); + ((JComponent)component).setBorder(BorderFactory.createEmptyBorder()); + } + + + return wrapper; + } + else { + if (component instanceof JComponent) { + ((JComponent)component).setToolTipText(hasErrors ? TooltipUtils.getTooltipText(problemDescriptions) : null); + } + + return component; + } + } + + private static Icon getErrorIcon() { + return IconLoader.getIcon("/general/exclMark.png"); + } +} diff --git a/resources/src/componentSets/UICore.xml b/resources/src/componentSets/UICore.xml index 6ce27bf756..87401b9449 100644 --- a/resources/src/componentSets/UICore.xml +++ b/resources/src/componentSets/UICore.xml @@ -63,6 +63,10 @@ com.intellij.openapi.ui.popup.JBPopupFactory com.intellij.ui.popup.PopupFactoryImpl + + com.intellij.ui.ToolTipHandlerProvider + com.intellij.ui.ToolTipHandlerProviderImpl + diff --git a/source/com/intellij/ide/commander/CommanderPanel.java b/source/com/intellij/ide/commander/CommanderPanel.java index 2052ee499b..32c656afc6 100644 --- a/source/com/intellij/ide/commander/CommanderPanel.java +++ b/source/com/intellij/ide/commander/CommanderPanel.java @@ -185,7 +185,7 @@ public class CommanderPanel extends JPanel { } ); - new ListToolTipHandler(myList); + ListToolTipHandler.install(myList); } private void updateHistory(boolean elementExpanded) { diff --git a/source/com/intellij/util/xml/highlighting/DomElementAnnotationsManagerImpl.java b/source/com/intellij/util/xml/highlighting/DomElementAnnotationsManagerImpl.java index daf4268932..e01e87ec24 100644 --- a/source/com/intellij/util/xml/highlighting/DomElementAnnotationsManagerImpl.java +++ b/source/com/intellij/util/xml/highlighting/DomElementAnnotationsManagerImpl.java @@ -11,42 +11,53 @@ import com.intellij.psi.util.CachedValueProvider; import com.intellij.psi.util.CachedValue; import com.intellij.psi.util.CachedValuesManager; import com.intellij.psi.PsiManager; +import com.intellij.psi.PsiReference; +import com.intellij.codeInspection.ProblemHighlightType; +import com.intellij.codeInsight.daemon.impl.analysis.XmlHighlightVisitor; import org.jetbrains.annotations.NonNls; -import java.util.List; -import java.util.Map; -import java.util.HashMap; -import java.util.ArrayList; +import java.util.*; public class DomElementAnnotationsManagerImpl extends DomElementAnnotationsManager implements ApplicationComponent { private Map> myClass2Annotator = new HashMap>(); - private Map> myCache = new HashMap>(); + private Map> myCache = + new HashMap>(); public List getProblems(final DomElement domElement) { - if(myCache.get(domElement.getRoot()) == null) { - myCache.put(domElement.getRoot(), getCachedValue(domElement)); + return getProblems(domElement, false); + } + + public List getProblems(DomElement domElement, boolean includeXmlProblems) { + return getProblems(domElement, includeXmlProblems, true); + } + + public List getProblems(DomElement domElement, boolean includeXmlProblems, boolean withChildren) { + if(domElement == null) return Collections.emptyList(); + + if (myCache.get(domElement.getRoot()) == null) { + myCache.put(domElement.getRoot(), getCachedValue(domElement)); } - return myCache.get(domElement.getRoot()).getValue().getProblems(domElement); + return myCache.get(domElement.getRoot()).getValue().getProblems(domElement, includeXmlProblems, withChildren); } private CachedValue getCachedValue(final DomElement domElement) { final CachedValuesManager cachedValuesManager = PsiManager.getInstance(domElement.getManager().getProject()).getCachedValuesManager(); return cachedValuesManager.createCachedValue(new CachedValueProvider() { - public Result compute() { - final DomElementsProblemsHolder holder = new DomElementsProblemsHolderImpl(); + public Result compute() { + final DomElementsProblemsHolder holder = new DomElementsProblemsHolderImpl(); - final List annotators = getDomElementsAnnotators(domElement); + final List annotators = getDomElementsAnnotators(domElement); - for (DomElementsAnnotator annotator : annotators) { - annotator.annotate((DomElement)domElement.getRoot().getRootElement(), holder); - } + for (DomElementsAnnotator annotator : annotators) { + annotator.annotate((DomElement)domElement.getRoot().getRootElement(), holder); + } - return new Result(holder, domElement.getRoot().getFile()); - } - }, false); + return new Result(holder, domElement.getRoot().getFile()); + } + }, false); } public List getDomElementsAnnotators(DomElement domElement) { diff --git a/source/com/intellij/util/xml/highlighting/DomElementProblemDescriptorImpl.java b/source/com/intellij/util/xml/highlighting/DomElementProblemDescriptorImpl.java index da64b93ad6..df21cc1a87 100644 --- a/source/com/intellij/util/xml/highlighting/DomElementProblemDescriptorImpl.java +++ b/source/com/intellij/util/xml/highlighting/DomElementProblemDescriptorImpl.java @@ -4,10 +4,9 @@ package com.intellij.util.xml.highlighting; -import com.intellij.util.xml.DomElement; -import com.intellij.codeInspection.ProblemHighlightType; -import com.intellij.codeInspection.QuickFix; import com.intellij.codeInspection.LocalQuickFix; +import com.intellij.codeInspection.ProblemHighlightType; +import com.intellij.util.xml.DomElement; import org.jetbrains.annotations.NotNull; public class DomElementProblemDescriptorImpl implements DomElementProblemDescription { @@ -38,10 +37,27 @@ public class DomElementProblemDescriptorImpl implements DomElementProblemDescrip @NotNull public String getDescriptionTemplate() { - return myMessage; + return myMessage == null? "": myMessage; } public LocalQuickFix[] getFixes() { return myFixes; } + + + public int hashCode() { + if(myDomElement == null) return super.hashCode(); + + return 241*getDomElement().hashCode() + 29*getDescriptionTemplate().hashCode() + getHighlightType().hashCode(); + } + + public boolean equals(Object obj) { + if ((obj instanceof DomElementProblemDescription)) return super.equals(obj); + if (getDomElement() == null) return super.equals(obj); + + DomElementProblemDescription other = (DomElementProblemDescription)obj; + return getDomElement().equals(other.getDomElement()) + && getDescriptionTemplate().equals(other.getDescriptionTemplate()) + && getHighlightType().equals(other.getHighlightType()); + } } diff --git a/source/com/intellij/util/xml/highlighting/DomElementsProblemsHolderImpl.java b/source/com/intellij/util/xml/highlighting/DomElementsProblemsHolderImpl.java index 29deb4ff82..214cf80aae 100644 --- a/source/com/intellij/util/xml/highlighting/DomElementsProblemsHolderImpl.java +++ b/source/com/intellij/util/xml/highlighting/DomElementsProblemsHolderImpl.java @@ -7,11 +7,13 @@ package com.intellij.util.xml.highlighting; import com.intellij.codeInspection.ProblemHighlightType; import com.intellij.util.SmartList; import com.intellij.util.xml.DomElement; +import com.intellij.util.xml.DomElementVisitor; +import com.intellij.psi.PsiReference; +import com.intellij.codeInsight.daemon.impl.analysis.XmlHighlightVisitor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.List; +import java.util.*; public class DomElementsProblemsHolderImpl extends SmartList implements DomElementsProblemsHolder { @@ -24,17 +26,43 @@ public class DomElementsProblemsHolderImpl extends SmartList problems = new ArrayList(); for (DomElementProblemDescription problemDescription : this) { final DomElement domElement1 = problemDescription.getDomElement(); - if(domElement1.equals(domElement)) { + if (domElement1.equals(domElement)) { problems.add(problemDescription); } } return problems; } + public List getProblems(final DomElement domElement, boolean includeXmlProblems) { + List problems = getProblems(domElement); + if (includeXmlProblems) { + problems.addAll(getXmlProblems(domElement)); + } + + return problems; + } + + public List getProblems(final DomElement domElement, + final boolean includeXmlProblems, + final boolean withChildren) { + if (!withChildren) return getProblems(domElement); + + final Set problems = new HashSet(); + + domElement.accept(new DomElementVisitor() { + public void visitDomElement(DomElement element) { + problems.addAll(getProblems(element, includeXmlProblems)); + element.acceptChildren(this); + } + }); + + return new ArrayList(problems); + } + public List getProblems(DomElement domElement, ProblemHighlightType severity) { final List problems = new ArrayList(); for (DomElementProblemDescription problemDescription : this) { - if(problemDescription.getDomElement().equals(domElement) && problemDescription.getHighlightType().equals(severity)) { + if (problemDescription.getDomElement().equals(domElement) && problemDescription.getHighlightType().equals(severity)) { problems.add(problemDescription); } } @@ -45,4 +73,26 @@ public class DomElementsProblemsHolderImpl extends SmartList getXmlProblems(DomElement domElement) { + Collection problems = new ArrayList(); + if (domElement.getXmlTag() != null) { + problems.addAll(getResolveProblems(domElement)); + + } + return problems; + } + + private static Collection getResolveProblems(final DomElement domElement) { + Collection problems = new ArrayList(); + if (domElement.getXmlTag() != null) { + for (PsiReference reference : domElement.getXmlTag().getReferences()) { + if (XmlHighlightVisitor.hasBadResolve(reference)) { + problems.add(new DomElementProblemDescriptorImpl(domElement, XmlHighlightVisitor.getErrorDescription(reference), + ProblemHighlightType.GENERIC_ERROR_OR_WARNING)); + } + } + } + return problems; + } } diff --git a/source/com/intellij/util/xml/tree/AbstractDomElementNode.java b/source/com/intellij/util/xml/tree/AbstractDomElementNode.java index d6acd74d26..6fe775ebb5 100644 --- a/source/com/intellij/util/xml/tree/AbstractDomElementNode.java +++ b/source/com/intellij/util/xml/tree/AbstractDomElementNode.java @@ -11,6 +11,7 @@ import java.util.*; abstract public class AbstractDomElementNode extends SimpleNode { public static final Key> TREE_NODES_HIDERS_KEY = Key.create("TREE_NODES_HIDERS_KEY"); + private boolean isExpanded; protected AbstractDomElementNode() { super(); @@ -58,4 +59,12 @@ abstract public class AbstractDomElementNode extends SimpleNode { return hiders.get(classes[0]).booleanValue(); } + + public boolean isExpanded() { + return isExpanded; + } + + public void setExpanded(final boolean expanded) { + isExpanded = expanded; + } } diff --git a/source/com/intellij/util/xml/tree/BaseDomElementNode.java b/source/com/intellij/util/xml/tree/BaseDomElementNode.java index 81fdd391f1..a88d0e4ea7 100644 --- a/source/com/intellij/util/xml/tree/BaseDomElementNode.java +++ b/source/com/intellij/util/xml/tree/BaseDomElementNode.java @@ -23,6 +23,7 @@ public class BaseDomElementNode extends AbstractDomElementNode { private final DomElement myDomElement; private final String myTagName; + public BaseDomElementNode(final DomElement modelElement) { this(modelElement, null); } @@ -89,10 +90,11 @@ public class BaseDomElementNode extends AbstractDomElementNode { setUniformIcon(getNodeIcon()); clearColoredText(); + boolean isExpanded = isExpanded(); - final List problems = DomElementAnnotationsManager.getInstance().getProblems(myDomElement); + final List problems = DomElementAnnotationsManager.getInstance().getProblems(myDomElement, true, highlightIfChildrenHasProblems()); if (problems.size() > 0) { - addColoredFragment(getNodeName(), TooltipUtils.getTooltipText(problems), SimpleTextAttributes.ERROR_ATTRIBUTES); + addColoredFragment(getNodeName(), TooltipUtils.getTooltipText(problems), SimpleTextAttributes.ERROR_ATTRIBUTES); //new SimpleTextAttributes(SimpleTextAttributes.STYLE_WAVED, Color.BLACK, Color.RED) } else if (myDomElement.getXmlTag() != null) { addColoredFragment(getNodeName(), SimpleTextAttributes.REGULAR_ATTRIBUTES); } else { @@ -102,6 +104,10 @@ public class BaseDomElementNode extends AbstractDomElementNode { return true; } + protected boolean highlightIfChildrenHasProblems() { + return true; + } + public String getNodeName() { final String name = myDomElement.getPresentation().getElementName(); return name != null ? name : getPropertyName(); diff --git a/source/com/intellij/util/xml/tree/DomElementsGroupNode.java b/source/com/intellij/util/xml/tree/DomElementsGroupNode.java index 55cd54abfc..df1870881c 100644 --- a/source/com/intellij/util/xml/tree/DomElementsGroupNode.java +++ b/source/com/intellij/util/xml/tree/DomElementsGroupNode.java @@ -2,9 +2,11 @@ package com.intellij.util.xml.tree; import com.intellij.javaee.model.ElementPresentation; import com.intellij.javaee.model.ElementPresentationManager; +import com.intellij.javaee.J2EEBundle; import com.intellij.ui.SimpleTextAttributes; import com.intellij.util.xml.DomElement; import com.intellij.util.xml.DomUtil; +import com.intellij.util.xml.highlighting.DomElementAnnotationsManager; import com.intellij.util.xml.reflect.DomCollectionChildDescription; import jetbrains.fabrique.ui.treeStructure.SimpleNode; @@ -45,13 +47,26 @@ public class DomElementsGroupNode extends AbstractDomElementNode { setUniformIcon(getNodeIcon()); clearColoredText(); - addColoredFragment(getNodeName(), new SimpleTextAttributes(Font.BOLD, Color.black)); + + final boolean showErrors = !isExpanded() && hasErrors(); + + addColoredFragment(getNodeName(), + new SimpleTextAttributes(SimpleTextAttributes.STYLE_BOLD, showErrors? SimpleTextAttributes.ERROR_ATTRIBUTES.getFgColor() : SimpleTextAttributes.REGULAR_ATTRIBUTES.getFgColor())); + final int childrenCount = getChildren().length; - addColoredFragment(" (" + childrenCount + ')', new SimpleTextAttributes(Font.ITALIC, Color.gray)); + addColoredFragment(" (" + childrenCount + ')', showErrors ? J2EEBundle.message("dom.elements.tree.childs.contain.errors") : null, new SimpleTextAttributes(Font.ITALIC, Color.gray)); return true; } + private boolean hasErrors() { + for (DomElement domElement : myChildDescription.getValues(myParentElement)) { + if (DomElementAnnotationsManager.getInstance().getProblems(domElement, true).size() > 0) return true; + } + + return false; + } + public String getNodeName() { return myChildDescription.getCommonPresentableName(myParentElement); } diff --git a/source/com/intellij/util/xml/tree/DomModelTreeStructure.java b/source/com/intellij/util/xml/tree/DomModelTreeStructure.java index 8b0b10fc7e..90a5fe68fe 100644 --- a/source/com/intellij/util/xml/tree/DomModelTreeStructure.java +++ b/source/com/intellij/util/xml/tree/DomModelTreeStructure.java @@ -12,7 +12,11 @@ public class DomModelTreeStructure extends SimpleTreeStructure { } protected AbstractDomElementNode createRoot(DomElement rootElement) { - return new BaseDomElementNode(myDomElement); + return new BaseDomElementNode(myDomElement){ + protected boolean highlightIfChildrenHasProblems() { + return false; + } + }; } public AbstractDomElementNode getRootElement() { diff --git a/source/com/intellij/util/xml/tree/DomModelTreeView.java b/source/com/intellij/util/xml/tree/DomModelTreeView.java index 0cb02b0696..dd67e612bb 100644 --- a/source/com/intellij/util/xml/tree/DomModelTreeView.java +++ b/source/com/intellij/util/xml/tree/DomModelTreeView.java @@ -14,6 +14,8 @@ import jetbrains.fabrique.ui.treeStructure.actions.CollapseAllAction; import jetbrains.fabrique.ui.treeStructure.actions.ExpandAllAction; import javax.swing.*; +import javax.swing.event.TreeExpansionListener; +import javax.swing.event.TreeExpansionEvent; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import java.awt.*; @@ -57,6 +59,25 @@ public class DomModelTreeView extends Wrapper implements DataProvider { add(myTree, BorderLayout.CENTER); + myTree.addTreeExpansionListener(new TreeExpansionListener() { + public void treeExpanded(TreeExpansionEvent event) { + final SimpleNode simpleNode = myTree.getNodeFor(event.getPath()); + + if(simpleNode instanceof AbstractDomElementNode) { + ((AbstractDomElementNode)simpleNode).setExpanded(true); + } + } + + public void treeCollapsed(TreeExpansionEvent event) { + final SimpleNode simpleNode = myTree.getNodeFor(event.getPath()); + + if(simpleNode instanceof AbstractDomElementNode) { + ((AbstractDomElementNode)simpleNode).setExpanded(false); + simpleNode.update(); + } + } + }); + myDomEventListener = new DomEventListener() { public void eventOccured(DomEvent event) { myBuilder.updateFromRoot(false); diff --git a/ui/impl/com/intellij/ui/ListToolTipHandler.java b/ui/impl/com/intellij/ui/ListToolTipHandler.java index 7f73aac6b5..9058c09ed2 100644 --- a/ui/impl/com/intellij/ui/ListToolTipHandler.java +++ b/ui/impl/com/intellij/ui/ListToolTipHandler.java @@ -8,7 +8,8 @@ import javax.swing.event.ListSelectionListener; import java.awt.*; public final class ListToolTipHandler extends AbstractToolTipHandler{ - public ListToolTipHandler(JList list) { + + protected ListToolTipHandler(JList list) { super(list); list.getSelectionModel().addListSelectionListener( @@ -36,6 +37,10 @@ public final class ListToolTipHandler extends AbstractToolTipHandler { - public TableToolTipHandler(JTable table) { + protected TableToolTipHandler(JTable table) { super(table); } diff --git a/ui/impl/com/intellij/ui/ToolTipHandlerProviderImpl.java b/ui/impl/com/intellij/ui/ToolTipHandlerProviderImpl.java new file mode 100644 index 0000000000..953d09ee00 --- /dev/null +++ b/ui/impl/com/intellij/ui/ToolTipHandlerProviderImpl.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2000-2006 JetBrains s.r.o. All Rights Reserved. + */ + +package com.intellij.ui; + +import com.intellij.openapi.components.ApplicationComponent; + +import javax.swing.*; + +import org.jetbrains.annotations.NonNls; + +public class ToolTipHandlerProviderImpl extends ToolTipHandlerProvider implements ApplicationComponent { + public void install(JComponent component) { + if (component instanceof JTree) { + TreeToolTipHandler.install((JTree)component); + } + else if (component instanceof JTable) { + TableToolTipHandler.install((JTable)component); + } + else if (component instanceof JList) { + ListToolTipHandler.install((JList)component); + } + else { + ToolTipManager.sharedInstance().registerComponent(component); + } + } + + + @NonNls + public String getComponentName() { + return "ToolTipHandlerProvider"; + } + + public void initComponent() { + + } + + public void disposeComponent() { + + } +} diff --git a/openapi/src/com/intellij/util/xml/highlighting/DomElementsProblemsHolder.java b/ui/openapi/com/intellij/ui/ToolTipHandlerProvider.java similarity index 54% copy from openapi/src/com/intellij/util/xml/highlighting/DomElementsProblemsHolder.java copy to ui/openapi/com/intellij/ui/ToolTipHandlerProvider.java index 8e32c79d6d..a67d3e0889 100644 --- a/openapi/src/com/intellij/util/xml/highlighting/DomElementsProblemsHolder.java +++ b/ui/openapi/com/intellij/ui/ToolTipHandlerProvider.java @@ -12,22 +12,18 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * */ -package com.intellij.util.xml.highlighting; - -import com.intellij.codeInspection.ProblemHighlightType; -import com.intellij.util.xml.DomElement; -import org.jetbrains.annotations.Nullable; - -import java.util.List; +package com.intellij.ui; -public interface DomElementsProblemsHolder { +import com.intellij.openapi.application.ApplicationManager; - void createProblem(DomElement domElement, @Nullable String message); +import javax.swing.*; - List getProblems(DomElement domElement); +public abstract class ToolTipHandlerProvider { + public static ToolTipHandlerProvider getToolTipHandlerProvider() { + return ApplicationManager.getApplication().getComponent(ToolTipHandlerProvider.class); + } - List getProblems(DomElement domElement, ProblemHighlightType severity); + public abstract void install(JComponent component); } -- 2.11.4.GIT