| /* |
| * Copyright 2000-2009 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. |
| */ |
| |
| /** |
| * class ViewerTreeStructure |
| * created Aug 25, 2001 |
| * @author Jeka |
| */ |
| package com.intellij.internal.psiView; |
| |
| import com.intellij.ide.util.treeView.AbstractTreeStructure; |
| import com.intellij.ide.util.treeView.NodeDescriptor; |
| import com.intellij.lang.ASTNode; |
| import com.intellij.lang.injection.InjectedLanguageManager; |
| import com.intellij.openapi.application.ApplicationManager; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.psi.*; |
| import com.intellij.psi.impl.source.SourceTreeToPsiMap; |
| import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; |
| import com.intellij.psi.util.PsiUtilCore; |
| import com.intellij.util.ArrayUtil; |
| import org.jetbrains.annotations.NotNull; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| public class ViewerTreeStructure extends AbstractTreeStructure { |
| private boolean myShowWhiteSpaces = true; |
| private boolean myShowTreeNodes = true; |
| |
| private final Project myProject; |
| private PsiElement myRootPsiElement = null; |
| private final Object myRootElement = new Object(); |
| |
| public ViewerTreeStructure(Project project) { |
| myProject = project; |
| } |
| |
| public void setRootPsiElement(PsiElement rootPsiElement) { |
| myRootPsiElement = rootPsiElement; |
| } |
| |
| public PsiElement getRootPsiElement() { |
| return myRootPsiElement; |
| } |
| |
| @Override |
| public Object getRootElement() { |
| return myRootElement; |
| } |
| |
| @Override |
| public Object[] getChildElements(final Object element) { |
| if (myRootElement == element) { |
| if (myRootPsiElement == null) { |
| return ArrayUtil.EMPTY_OBJECT_ARRAY; |
| } |
| if (!(myRootPsiElement instanceof PsiFile)) { |
| return new Object[]{myRootPsiElement}; |
| } |
| List<PsiFile> files = ((PsiFile)myRootPsiElement).getViewProvider().getAllFiles(); |
| return PsiUtilCore.toPsiFileArray(files); |
| } |
| final Object[][] children = new Object[1][]; |
| children[0] = ArrayUtil.EMPTY_OBJECT_ARRAY; |
| ApplicationManager.getApplication().runReadAction(new Runnable() { |
| @Override |
| public void run() { |
| final Object[] result; |
| if (myShowTreeNodes) { |
| final ArrayList<Object> list = new ArrayList<Object>(); |
| ASTNode root = element instanceof PsiElement? SourceTreeToPsiMap.psiElementToTree((PsiElement)element) : |
| element instanceof ASTNode? (ASTNode)element : null; |
| if (element instanceof Inject) { |
| root = SourceTreeToPsiMap.psiElementToTree(((Inject)element).getPsi()); |
| } |
| |
| if (root != null) { |
| ASTNode child = root.getFirstChildNode(); |
| while (child != null) { |
| if (myShowWhiteSpaces || child.getElementType() != TokenType.WHITE_SPACE) { |
| final PsiElement childElement = child.getPsi(); |
| list.add(childElement == null ? child : childElement); |
| } |
| child = child.getTreeNext(); |
| } |
| final PsiElement psi = root.getPsi(); |
| if (psi instanceof PsiLanguageInjectionHost) { |
| InjectedLanguageUtil.enumerate(psi, new PsiLanguageInjectionHost.InjectedPsiVisitor() { |
| @Override |
| public void visit(@NotNull PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) { |
| list.add(new Inject(psi, injectedPsi)); |
| } |
| }); |
| } |
| } |
| result = ArrayUtil.toObjectArray(list); |
| } |
| else { |
| final PsiElement[] elementChildren = ((PsiElement)element).getChildren(); |
| if (!myShowWhiteSpaces) { |
| final List<PsiElement> childrenList = new ArrayList<PsiElement>(elementChildren.length); |
| for (PsiElement psiElement : elementChildren) { |
| if (!myShowWhiteSpaces && psiElement instanceof PsiWhiteSpace) { |
| continue; |
| } |
| childrenList.add(psiElement); |
| } |
| result = PsiUtilCore.toPsiElementArray(childrenList); |
| } |
| else { |
| result = elementChildren; |
| } |
| } |
| children[0] = result; |
| } |
| }); |
| return children[0]; |
| } |
| |
| @Override |
| public Object getParentElement(Object element) { |
| if (element == myRootElement) { |
| return null; |
| } |
| if (element == myRootPsiElement) { |
| return myRootElement; |
| } |
| if (element instanceof PsiFile && |
| InjectedLanguageManager.getInstance(((PsiFile)element).getProject()).getInjectionHost(((PsiFile)element)) != null) { |
| return new Inject(InjectedLanguageManager.getInstance(((PsiFile)element).getProject()).getInjectionHost(((PsiFile)element)), |
| (PsiElement)element); |
| } |
| return element instanceof Inject ? ((Inject)element).getParent() : ((PsiElement)element).getContext(); |
| } |
| |
| @Override |
| public void commit() { |
| } |
| |
| @Override |
| public boolean hasSomethingToCommit() { |
| return false; |
| } |
| |
| @Override |
| @NotNull |
| public NodeDescriptor createDescriptor(Object element, NodeDescriptor parentDescriptor) { |
| if (element == myRootElement) { |
| return new NodeDescriptor(myProject, null) { |
| @Override |
| public boolean update() { |
| return false; |
| } |
| @Override |
| public Object getElement() { |
| return myRootElement; |
| } |
| }; |
| } |
| return new ViewerNodeDescriptor(myProject, element, parentDescriptor); |
| } |
| |
| public boolean isShowWhiteSpaces() { |
| return myShowWhiteSpaces; |
| } |
| |
| public void setShowWhiteSpaces(boolean showWhiteSpaces) { |
| myShowWhiteSpaces = showWhiteSpaces; |
| } |
| |
| public boolean isShowTreeNodes() { |
| return myShowTreeNodes; |
| } |
| |
| public void setShowTreeNodes(final boolean showTreeNodes) { |
| myShowTreeNodes = showTreeNodes; |
| } |
| |
| static class Inject { |
| private final PsiElement myParent; |
| private final PsiElement myPsi; |
| |
| Inject(PsiElement parent, PsiElement psi) { |
| myParent = parent; |
| myPsi = psi; |
| } |
| |
| public PsiElement getParent() { |
| return myParent; |
| } |
| |
| public PsiElement getPsi() { |
| return myPsi; |
| } |
| |
| @Override |
| public String toString() { |
| return "INJECTION " + myPsi.getLanguage(); |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (this == o) return true; |
| if (o == null || getClass() != o.getClass()) return false; |
| |
| Inject inject = (Inject)o; |
| |
| if (!myParent.equals(inject.myParent)) return false; |
| if (!myPsi.equals(inject.myPsi)) return false; |
| |
| return true; |
| } |
| |
| @Override |
| public int hashCode() { |
| int result = myParent.hashCode(); |
| result = 31 * result + myPsi.hashCode(); |
| return result; |
| } |
| } |
| } |