blob: e566c43544b0535490cbd42ab56ed4922ee8a19e [file] [log] [blame]
/*
* Copyright 2000-2014 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 org.jetbrains.plugins.groovy.mvc.projectView;
import com.intellij.ide.IconProvider;
import com.intellij.ide.projectView.PresentationData;
import com.intellij.ide.projectView.ViewSettings;
import com.intellij.ide.util.treeView.AbstractTreeNode;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
import javax.swing.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* @author Dmitry Krasilschikov
*/
public class AbstractFolderNode extends AbstractMvcPsiNodeDescriptor {
@Nullable private final String myLocationMark;
private final String myPresentableText;
protected AbstractFolderNode(@NotNull final Module module,
@NotNull final PsiDirectory directory,
@NotNull String presentableText,
@Nullable final String locationMark,
final ViewSettings viewSettings, int weight) {
super(module, viewSettings, new NodeId(directory, locationMark), weight);
myLocationMark = locationMark;
myPresentableText = presentableText;
}
@Override
protected String getTestPresentationImpl(@NotNull final NodeId nodeId, @NotNull final PsiElement psiElement) {
final VirtualFile virtualFile = getVirtualFile();
assert virtualFile != null;
return "Folder: " + virtualFile.getPresentableName();
}
@NotNull
protected PsiDirectory getPsiDirectory() {
return (PsiDirectory)extractPsiFromValue();
}
@Override
@Nullable
protected Collection<AbstractTreeNode> getChildrenImpl() {
final PsiDirectory directory = getPsiDirectory();
if (!directory.isValid()) {
return Collections.emptyList();
}
final List<AbstractTreeNode> children = new ArrayList<AbstractTreeNode>();
// scan folder's children
for (PsiDirectory subDir : directory.getSubdirectories()) {
children.add(createFolderNode(subDir));
}
for (PsiFile file : directory.getFiles()) {
processNotDirectoryFile(children, file);
}
return children;
}
private AbstractFolderNode createFolderNode(PsiDirectory directory) {
PsiDirectory realDirectory = directory;
StringBuilder textBuilder = null;
if (getSettings().isHideEmptyMiddlePackages()) {
do {
if (realDirectory.getFiles().length > 0) break;
PsiDirectory[] subdirectories = realDirectory.getSubdirectories();
if (subdirectories.length != 1) break;
if (textBuilder == null) {
textBuilder = new StringBuilder();
textBuilder.append(realDirectory.getName());
}
realDirectory = subdirectories[0];
textBuilder.append('.').append(realDirectory.getName());
} while (true);
}
String presentableText = textBuilder == null ? directory.getName() : textBuilder.toString();
return new AbstractFolderNode(getModule(), realDirectory, presentableText, myLocationMark, getSettings(), FOLDER) {
@Override
protected void processNotDirectoryFile(List<AbstractTreeNode> nodes, PsiFile file) {
AbstractFolderNode.this.processNotDirectoryFile(nodes, file);
}
@Override
protected AbstractTreeNode createClassNode(GrTypeDefinition typeDefinition) {
return AbstractFolderNode.this.createClassNode(typeDefinition);
}
};
}
@Override
protected void updateImpl(final PresentationData data) {
final PsiDirectory psiDirectory = getPsiDirectory();
data.setPresentableText(myPresentableText);
for (final IconProvider provider : Extensions.getExtensions(IconProvider.EXTENSION_POINT_NAME)) {
final Icon icon = provider.getIcon(psiDirectory, 0);
if (icon != null) {
data.setIcon(icon);
return;
}
}
}
@Override
protected boolean containsImpl(@NotNull final VirtualFile file) {
final PsiElement psiElement = extractPsiFromValue();
if (psiElement == null || !psiElement.isValid()) {
return false;
}
final VirtualFile valueFile = ((PsiDirectory)psiElement).getVirtualFile();
if (!VfsUtil.isAncestor(valueFile, file, false)) {
return false;
}
final Project project = psiElement.getProject();
final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
final Module module = fileIndex.getModuleForFile(valueFile);
if (module == null) {
return fileIndex.getModuleForFile(file) == null;
}
return ModuleRootManager.getInstance(module).getFileIndex().isInContent(file);
}
protected void processNotDirectoryFile(final List<AbstractTreeNode> nodes, final PsiFile file) {
if (file instanceof GroovyFile) {
final GrTypeDefinition[] definitions = ((GroovyFile)file).getTypeDefinitions();
if (definitions.length > 0) {
for (final GrTypeDefinition typeDefinition : definitions) {
nodes.add(createClassNode(typeDefinition));
}
return;
}
}
nodes.add(new FileNode(getModule(), file, myLocationMark, getSettings()));
}
protected AbstractTreeNode createClassNode(final GrTypeDefinition typeDefinition) {
final NodeId nodeId = getValue();
assert nodeId != null;
return new ClassNode(getModule(), typeDefinition, nodeId.getLocationRootMark(), getSettings());
}
}