blob: 5900238771447a42c876793731f474464fe0d4b2 [file] [log] [blame]
/*
* Copyright 2000-2012 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.openapi.roots.ui.configuration.artifacts.nodes;
import com.intellij.ide.projectView.PresentationData;
import com.intellij.openapi.editor.markup.EffectType;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.roots.ui.configuration.artifacts.ArtifactEditorImpl;
import com.intellij.openapi.roots.ui.configuration.artifacts.ArtifactProblemDescription;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureProblemType;
import com.intellij.openapi.util.MultiValuesMap;
import com.intellij.packaging.elements.CompositePackagingElement;
import com.intellij.packaging.elements.PackagingElement;
import com.intellij.packaging.ui.ArtifactEditorContext;
import com.intellij.ui.JBColor;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.ui.treeStructure.SimpleNode;
import com.intellij.util.ArrayUtil;
import com.intellij.util.SmartList;
import com.intellij.util.StringBuilderSpinAllocator;
import com.intellij.xml.util.XmlStringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
/**
* @author nik
*/
public class PackagingElementNode<E extends PackagingElement<?>> extends ArtifactsTreeNode {
private final List<E> myPackagingElements;
private final Map<PackagingElement<?>, CompositePackagingElement<?>> myParentElements = new HashMap<PackagingElement<?>, CompositePackagingElement<?>>(1);
private final MultiValuesMap<PackagingElement<?>, PackagingNodeSource> myNodeSources = new MultiValuesMap<PackagingElement<?>, PackagingNodeSource>();
private final CompositePackagingElementNode myParentNode;
public PackagingElementNode(@NotNull E packagingElement, ArtifactEditorContext context, @Nullable CompositePackagingElementNode parentNode,
@Nullable CompositePackagingElement<?> parentElement,
@NotNull Collection<PackagingNodeSource> nodeSources) {
super(context, parentNode, packagingElement.createPresentation(context));
myParentNode = parentNode;
myParentElements.put(packagingElement, parentElement);
myNodeSources.putAll(packagingElement, nodeSources);
myPackagingElements = new SmartList<E>();
doAddElement(packagingElement);
}
private void doAddElement(E packagingElement) {
myPackagingElements.add(packagingElement);
}
@Nullable
public CompositePackagingElement<?> getParentElement(PackagingElement<?> element) {
return myParentElements.get(element);
}
@Nullable
public CompositePackagingElementNode getParentNode() {
return myParentNode;
}
public List<E> getPackagingElements() {
return myPackagingElements;
}
@Nullable
public E getElementIfSingle() {
return myPackagingElements.size() == 1 ? myPackagingElements.get(0) : null;
}
@NotNull
@Override
public Object[] getEqualityObjects() {
return ArrayUtil.toObjectArray(myPackagingElements);
}
@Override
protected SimpleNode[] buildChildren() {
return NO_CHILDREN;
}
public E getFirstElement() {
return myPackagingElements.get(0);
}
@Override
protected void update(PresentationData presentation) {
final Collection<ArtifactProblemDescription> problems = ((ArtifactEditorImpl)myContext.getThisArtifactEditor()).getValidationManager().getProblems(this);
if (problems == null || problems.isEmpty()) {
super.update(presentation);
return;
}
StringBuilder buffer = StringBuilderSpinAllocator.alloc();
final String tooltip;
boolean isError = false;
try {
for (ArtifactProblemDescription problem : problems) {
isError |= problem.getSeverity() == ProjectStructureProblemType.Severity.ERROR;
buffer.append(problem.getMessage(false)).append("<br>");
}
tooltip = XmlStringUtil.wrapInHtml(buffer);
}
finally {
StringBuilderSpinAllocator.dispose(buffer);
}
getElementPresentation().render(presentation, addErrorHighlighting(isError, SimpleTextAttributes.REGULAR_ATTRIBUTES),
addErrorHighlighting(isError, SimpleTextAttributes.GRAY_ATTRIBUTES));
presentation.setTooltip(tooltip);
}
private static SimpleTextAttributes addErrorHighlighting(boolean error, SimpleTextAttributes attributes) {
final TextAttributes textAttributes = attributes.toTextAttributes();
textAttributes.setEffectType(EffectType.WAVE_UNDERSCORE);
textAttributes.setEffectColor(error ? JBColor.RED : JBColor.GRAY);
return SimpleTextAttributes.fromTextAttributes(textAttributes);
}
void addElement(PackagingElement<?> element, CompositePackagingElement parentElement, Collection<PackagingNodeSource> nodeSource) {
doAddElement((E)element);
myParentElements.put(element, parentElement);
myNodeSources.putAll(element, nodeSource);
}
@NotNull
public Collection<PackagingNodeSource> getNodeSources() {
return myNodeSources.values();
}
@NotNull
public Collection<PackagingNodeSource> getNodeSource(@NotNull PackagingElement<?> element) {
final Collection<PackagingNodeSource> nodeSources = myNodeSources.get(element);
return nodeSources != null ? nodeSources : Collections.<PackagingNodeSource>emptyList();
}
public ArtifactEditorContext getContext() {
return myContext;
}
@Nullable
public CompositePackagingElementNode findCompositeChild(@NotNull String name) {
final SimpleNode[] children = getChildren();
for (SimpleNode child : children) {
if (child instanceof CompositePackagingElementNode) {
final CompositePackagingElementNode composite = (CompositePackagingElementNode)child;
if (name.equals(composite.getFirstElement().getName())) {
return composite;
}
}
}
return null;
}
public List<PackagingElementNode<?>> getNodesByPath(List<PackagingElement<?>> pathToPlace) {
List<PackagingElementNode<?>> result = new ArrayList<PackagingElementNode<?>>();
PackagingElementNode<?> current = this;
int i = 0;
result.add(current);
while (current != null && i < pathToPlace.size()) {
final SimpleNode[] children = current.getCached();
if (children == null) {
break;
}
PackagingElementNode<?> next = null;
final PackagingElement<?> element = pathToPlace.get(i);
search:
for (SimpleNode child : children) {
if (child instanceof PackagingElementNode<?>) {
PackagingElementNode<?> childNode = (PackagingElementNode<?>)child;
for (PackagingElement<?> childElement : childNode.getPackagingElements()) {
if (childElement.isEqualTo(element)) {
next = childNode;
break search;
}
}
for (PackagingNodeSource nodeSource : childNode.getNodeSources()) {
if (nodeSource.getSourceElement().isEqualTo(element)) {
next = current;
break search;
}
}
}
}
current = next;
if (current != null) {
result.add(current);
}
i++;
}
return result;
}
}