2 * Copyright 2000-2015 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.ide.projectView.impl.nodes;
18 import com.intellij.ide.IconProvider;
19 import com.intellij.ide.bookmarks.Bookmark;
20 import com.intellij.ide.bookmarks.BookmarkManager;
21 import com.intellij.ide.projectView.PresentationData;
22 import com.intellij.ide.projectView.ProjectView;
23 import com.intellij.ide.projectView.ViewSettings;
24 import com.intellij.ide.projectView.impl.ProjectRootsUtil;
25 import com.intellij.ide.projectView.impl.ProjectViewImpl;
26 import com.intellij.ide.util.treeView.AbstractTreeNode;
27 import com.intellij.idea.ActionsBundle;
28 import com.intellij.openapi.extensions.Extensions;
29 import com.intellij.openapi.fileTypes.FileTypeRegistry;
30 import com.intellij.openapi.module.Module;
31 import com.intellij.openapi.module.ModuleUtil;
32 import com.intellij.openapi.project.Project;
33 import com.intellij.openapi.roots.OrderEntry;
34 import com.intellij.openapi.roots.ProjectFileIndex;
35 import com.intellij.openapi.roots.ProjectRootManager;
36 import com.intellij.openapi.roots.libraries.LibraryUtil;
37 import com.intellij.openapi.roots.ui.configuration.ProjectSettingsService;
38 import com.intellij.openapi.util.Comparing;
39 import com.intellij.openapi.util.registry.Registry;
40 import com.intellij.openapi.vfs.LocalFileSystem;
41 import com.intellij.openapi.vfs.VFileProperty;
42 import com.intellij.openapi.vfs.VfsUtilCore;
43 import com.intellij.openapi.vfs.VirtualFile;
44 import com.intellij.pom.NavigatableWithText;
45 import com.intellij.projectImport.ProjectAttachProcessor;
46 import com.intellij.psi.PsiDirectory;
47 import com.intellij.psi.impl.file.PsiDirectoryFactory;
48 import com.intellij.ui.LayeredIcon;
49 import com.intellij.ui.RowIcon;
50 import com.intellij.ui.SimpleTextAttributes;
51 import com.intellij.util.IconUtil;
52 import com.intellij.util.PathUtil;
53 import com.intellij.util.PlatformIcons;
54 import com.intellij.util.PlatformUtils;
55 import org.jetbrains.annotations.NotNull;
58 import java.util.Collection;
60 public class PsiDirectoryNode extends BasePsiNode<PsiDirectory> implements NavigatableWithText {
61 public PsiDirectoryNode(Project project, PsiDirectory value, ViewSettings viewSettings) {
62 super(project, value, viewSettings);
65 protected boolean shouldShowModuleName() {
66 return !PlatformUtils.isCidr();
69 protected boolean shouldShowSourcesRoot() {
74 protected void updateImpl(PresentationData data) {
75 Project project = getProject();
76 assert project != null : this;
77 PsiDirectory psiDirectory = getValue();
78 assert psiDirectory != null : this;
79 VirtualFile directoryFile = psiDirectory.getVirtualFile();
80 Object parentValue = getParentValue();
82 if (ProjectRootsUtil.isModuleContentRoot(directoryFile, project)) {
83 ProjectFileIndex fi = ProjectRootManager.getInstance(project).getFileIndex();
84 Module module = fi.getModuleForFile(directoryFile);
86 data.setPresentableText(directoryFile.getName());
88 if (!(parentValue instanceof Module)) {
89 if (!shouldShowModuleName()) {
90 data.addText(directoryFile.getName() + " ", SimpleTextAttributes.REGULAR_ATTRIBUTES);
92 else if (Comparing.equal(module.getName(), directoryFile.getName())) {
93 data.addText(directoryFile.getName(), SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
96 data.addText(directoryFile.getName() + " ", SimpleTextAttributes.REGULAR_ATTRIBUTES);
97 data.addText("[" + module.getName() + "]", SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
101 data.addText(directoryFile.getName(), SimpleTextAttributes.REGULAR_ATTRIBUTES);
104 data.setLocationString(ProjectViewDirectoryHelper.getInstance(project).getLocationString(psiDirectory, true, shouldShowSourcesRoot()));
105 setupIcon(data, psiDirectory);
111 String name = parentValue instanceof Project
112 ? psiDirectory.getVirtualFile().getPresentableUrl()
113 : ProjectViewDirectoryHelper.getInstance(psiDirectory.getProject()).getNodeName(getSettings(), parentValue, psiDirectory);
119 data.setPresentableText(name);
120 data.setLocationString(ProjectViewDirectoryHelper.getInstance(project).getLocationString(psiDirectory, false, false));
122 setupIcon(data, psiDirectory);
125 protected void setupIcon(PresentationData data, PsiDirectory psiDirectory) {
126 final VirtualFile virtualFile = psiDirectory.getVirtualFile();
127 if (PlatformUtils.isAppCode()) {
128 final Icon icon = IconUtil.getIcon(virtualFile, 0, myProject);
130 data.setIcon(patchIcon(icon, virtualFile));
134 for (final IconProvider provider : Extensions.getExtensions(IconProvider.EXTENSION_POINT_NAME)) {
135 final Icon icon = provider.getIcon(psiDirectory, 0);
137 data.setIcon(patchIcon(icon, virtualFile));
145 public Collection<AbstractTreeNode> getChildrenImpl() {
146 return ProjectViewDirectoryHelper.getInstance(myProject).getDirectoryChildren(getValue(), getSettings(), true);
150 @SuppressWarnings("deprecation")
151 public String getTestPresentation() {
152 return "PsiDirectory: " + getValue().getName();
155 public boolean isFQNameShown() {
156 return ProjectViewDirectoryHelper.getInstance(getProject()).isShowFQName(getSettings(), getParentValue(), getValue());
160 public boolean contains(@NotNull VirtualFile file) {
161 final PsiDirectory value = getValue();
166 VirtualFile directory = value.getVirtualFile();
167 if (directory.getFileSystem() instanceof LocalFileSystem) {
168 file = PathUtil.getLocalFile(file);
171 if (!VfsUtilCore.isAncestor(directory, file, false)) {
175 if (Registry.is("ide.hide.excluded.files")) {
176 final Project project = value.getProject();
177 final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
178 return !fileIndex.isExcluded(file);
181 return !FileTypeRegistry.getInstance().isFileIgnored(file);
186 public VirtualFile getVirtualFile() {
187 PsiDirectory directory = getValue();
188 if (directory == null) return null;
189 return directory.getVirtualFile();
193 public boolean canRepresent(final Object element) {
194 if (super.canRepresent(element)) return true;
195 PsiDirectory directory = getValue();
196 if (directory == null) return false;
197 return ProjectViewDirectoryHelper.getInstance(getProject()).canRepresent(element, directory);
201 public boolean canNavigate() {
202 VirtualFile file = getVirtualFile();
203 Project project = getProject();
205 ProjectSettingsService service = ProjectSettingsService.getInstance(myProject);
206 return file != null && ((ProjectRootsUtil.isModuleContentRoot(file, project) && service.canOpenModuleSettings()) ||
207 (ProjectRootsUtil.isModuleSourceRoot(file, project) && service.canOpenContentEntriesSettings()) ||
208 (ProjectRootsUtil.isLibraryRoot(file, project) && service.canOpenModuleLibrarySettings()));
212 public boolean canNavigateToSource() {
217 public void navigate(final boolean requestFocus) {
218 Module module = ModuleUtil.findModuleForPsiElement(getValue());
219 if (module != null) {
220 final VirtualFile file = getVirtualFile();
221 final Project project = getProject();
222 ProjectSettingsService service = ProjectSettingsService.getInstance(myProject);
223 if (ProjectRootsUtil.isModuleContentRoot(file, project)) {
224 service.openModuleSettings(module);
226 else if (ProjectRootsUtil.isLibraryRoot(file, project)) {
227 final OrderEntry orderEntry = LibraryUtil.findLibraryEntry(file, module.getProject());
228 if (orderEntry != null) {
229 service.openLibraryOrSdkSettings(orderEntry);
233 service.openContentEntriesSettings(module);
239 public String getNavigateActionText(boolean focusEditor) {
240 VirtualFile file = getVirtualFile();
241 Project project = getProject();
243 if (file != null && project != null) {
244 if (ProjectRootsUtil.isModuleContentRoot(file, project) || ProjectRootsUtil.isModuleSourceRoot(file, project)) {
245 return ActionsBundle.message("action.ModuleSettings.navigate");
247 if (ProjectRootsUtil.isLibraryRoot(file, project)) {
248 return ActionsBundle.message("action.LibrarySettings.navigate");
256 public int getWeight() {
257 final ProjectView projectView = ProjectView.getInstance(myProject);
258 if (projectView instanceof ProjectViewImpl && !((ProjectViewImpl)projectView).isFoldersAlwaysOnTop()) {
261 return isFQNameShown() ? 70 : 0;
265 public String getTitle() {
266 final PsiDirectory directory = getValue();
267 if (directory != null) {
268 return PsiDirectoryFactory.getInstance(getProject()).getQualifiedName(directory, true);
270 return super.getTitle();
273 protected Icon patchIcon(Icon original, VirtualFile file) {
274 Icon icon = original;
276 final Bookmark bookmarkAtFile = BookmarkManager.getInstance(myProject).findFileBookmark(file);
277 if (bookmarkAtFile != null) {
278 final RowIcon composite = new RowIcon(2, RowIcon.Alignment.CENTER);
279 composite.setIcon(icon, 0);
280 composite.setIcon(bookmarkAtFile.getIcon(), 1);
284 if (!file.isWritable()) {
285 icon = LayeredIcon.create(icon, PlatformIcons.LOCKED_ICON);
288 if (file.is(VFileProperty.SYMLINK)) {
289 icon = LayeredIcon.create(icon, PlatformIcons.SYMLINK_ICON);
296 public Comparable getSortKey() {
297 if (ProjectAttachProcessor.canAttachToProject()) {
298 // primary module is always on top; attached modules are sorted alphabetically
299 final VirtualFile file = getVirtualFile();
300 if (Comparing.equal(file, myProject.getBaseDir())) {
301 return ""; // sorts before any other name
309 public Comparable getTypeSortKey() {
310 VirtualFile file = getVirtualFile();
312 String extension = file.getExtension();
313 if (extension != null) {
314 return new PsiFileNode.ExtensionSortKey(extension);
321 public String getQualifiedNameSortKey() {
322 final PsiDirectoryFactory factory = PsiDirectoryFactory.getInstance(getProject());
323 return factory.getQualifiedName(getValue(), true);
327 public int getTypeSortWeight(final boolean sortByType) {
332 public boolean shouldDrillDownOnEmptyElement() {
337 public boolean isAlwaysShowPlus() {
338 final VirtualFile file = getVirtualFile();
339 return file == null || file.getChildren().length > 0;