53629ec33922c1fae198b3bfda1af51af54d2ee8
[idea/community.git] / platform / lang-impl / src / com / intellij / psi / impl / file / SourceRootIconProvider.java
1 // Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2
3 package com.intellij.psi.impl.file;
4
5 import com.intellij.icons.AllIcons;
6 import com.intellij.ide.IconLayerProvider;
7 import com.intellij.ide.IconProvider;
8 import com.intellij.ide.projectView.impl.ProjectRootsUtil;
9 import com.intellij.openapi.project.DumbAware;
10 import com.intellij.openapi.project.Project;
11 import com.intellij.openapi.roots.ProjectFileIndex;
12 import com.intellij.openapi.roots.ProjectRootManager;
13 import com.intellij.openapi.roots.SourceFolder;
14 import com.intellij.openapi.roots.impl.ProjectFileIndexImpl;
15 import com.intellij.openapi.roots.ui.configuration.SourceRootPresentation;
16 import com.intellij.openapi.util.Iconable;
17 import com.intellij.openapi.util.registry.Registry;
18 import com.intellij.openapi.vfs.VirtualFile;
19 import com.intellij.psi.PsiDirectory;
20 import com.intellij.psi.PsiElement;
21 import com.intellij.psi.PsiFile;
22 import com.intellij.psi.util.CachedValueProvider;
23 import com.intellij.psi.util.CachedValuesManager;
24 import com.intellij.util.ObjectUtils;
25 import com.intellij.util.PlatformIcons;
26 import org.jetbrains.annotations.NotNull;
27 import org.jetbrains.annotations.Nullable;
28
29 import javax.swing.*;
30
31 public class SourceRootIconProvider {
32   @NotNull
33   public static Icon getDirectoryIcon(VirtualFile vFile, Project project) {
34     SourceFolder sourceFolder = ProjectRootsUtil.getModuleSourceRoot(vFile, project);
35     if (sourceFolder != null) {
36       return SourceRootPresentation.getSourceRootIcon(sourceFolder);
37     }
38     else {
39       Icon excludedIcon = getIconIfExcluded(project, vFile);
40       return excludedIcon != null ? excludedIcon : PlatformIcons.FOLDER_ICON;
41     }
42   }
43   
44   @Nullable
45   public static Icon getIconIfExcluded(@NotNull Project project, @NotNull VirtualFile vFile) {
46     if (!Registry.is("ide.hide.excluded.files")) {
47       boolean ignored = ProjectRootManager.getInstance(project).getFileIndex().isExcluded(vFile);
48       if (ignored) {
49         return AllIcons.Modules.ExcludeRoot;
50       }
51     }
52     return null;
53   }
54
55   @Nullable
56   private static Icon calcFileLayerIcon(VirtualFile vFile, Project project) {
57     ProjectFileIndex index = ProjectFileIndex.getInstance(project);
58     if (vFile != null) {
59       VirtualFile parent = vFile.getParent();
60       
61       if (index.isExcluded(vFile)) {
62         //If the parent directory is also excluded it'll have a special icon (see DirectoryIconProvider), so it makes no sense to add
63         // additional marks for all files under it.
64         if (parent == null || !index.isExcluded(parent)) {
65           return AllIcons.Nodes.ExcludedFromCompile;
66         }
67       }
68       else {
69         ProjectFileIndexImpl indexImpl = ObjectUtils.tryCast(index, ProjectFileIndexImpl.class);
70         SourceFolder sourceFolder = indexImpl != null ? indexImpl.getSourceFolder(vFile) : null;
71         if (sourceFolder != null && vFile.equals(sourceFolder.getFile())) {
72           SourceFolder parentSourceFolder = parent == null ? null : indexImpl.getSourceFolder(parent);
73
74           // do not mark files under folder of the same root type (e.g. test root file under test root dir)
75           // but mark file if they are under different root type (e.g. test root file under source root dir)
76           if (parentSourceFolder == null || !sourceFolder.equals(parentSourceFolder)) {
77             return SourceRootPresentation.getSourceRootFileLayerIcon(sourceFolder);
78           }
79         }
80       }
81     }
82     return null;
83   }
84
85   public static class DirectoryProvider extends IconProvider implements DumbAware {
86     @Override
87     public Icon getIcon(@NotNull final PsiElement element, final int flags) {
88       if (element instanceof PsiDirectory) {
89         final PsiDirectory psiDirectory = (PsiDirectory)element;
90         return getDirectoryIcon(psiDirectory.getVirtualFile(), psiDirectory.getProject());
91       }
92       return null;
93     }
94   }
95   
96   public static class FileLayerProvider implements IconLayerProvider, DumbAware {
97     @Nullable
98     @Override
99     public Icon getLayerIcon(@NotNull Iconable element, boolean isLocked) {
100       if (element instanceof PsiFile) {
101         Project project = ((PsiFile)element).getProject();
102         VirtualFile virtualFile = ((PsiFile)element).getVirtualFile();
103         return CachedValuesManager.getCachedValue((PsiElement)element,
104                                                   () -> CachedValueProvider.Result.create(calcFileLayerIcon(virtualFile, project),
105                                                                                           ProjectRootManager.getInstance(project)));
106       }
107       return null;
108     }
109   
110     @NotNull
111     @Override
112     public String getLayerDescription() {
113       return "Source root files";
114     }
115   }
116 }