IdentityFilePointer should be removed from myUrlToIdentity cache on dispose
[idea/community.git] / java / idea-ui / src / com / intellij / openapi / roots / ui / OrderEntryAppearanceServiceImpl.java
1 /*
2  * Copyright 2000-2012 JetBrains s.r.o.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 package com.intellij.openapi.roots.ui;
17
18 import com.intellij.openapi.module.Module;
19 import com.intellij.openapi.module.ModuleType;
20 import com.intellij.openapi.project.Project;
21 import com.intellij.openapi.project.ProjectBundle;
22 import com.intellij.openapi.projectRoots.Sdk;
23 import com.intellij.openapi.projectRoots.SdkType;
24 import com.intellij.openapi.roots.*;
25 import com.intellij.openapi.roots.impl.libraries.LibraryEx;
26 import com.intellij.openapi.roots.libraries.Library;
27 import com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurable;
28 import com.intellij.openapi.roots.ui.configuration.libraries.LibraryPresentationManager;
29 import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext;
30 import com.intellij.openapi.roots.ui.util.CompositeAppearance;
31 import com.intellij.openapi.roots.ui.util.SimpleTextCellAppearance;
32 import com.intellij.openapi.util.IconLoader;
33 import com.intellij.openapi.util.SystemInfo;
34 import com.intellij.openapi.util.text.StringUtil;
35 import com.intellij.openapi.vfs.JarFileSystem;
36 import com.intellij.openapi.vfs.VfsUtilCore;
37 import com.intellij.openapi.vfs.VirtualFile;
38 import com.intellij.openapi.vfs.VirtualFileManager;
39 import com.intellij.openapi.vfs.impl.LightFilePointer;
40 import com.intellij.ui.JBColor;
41 import com.intellij.ui.SimpleTextAttributes;
42 import com.intellij.util.PathUtil;
43 import com.intellij.util.PlatformIcons;
44 import org.jetbrains.annotations.NotNull;
45 import org.jetbrains.annotations.Nullable;
46
47 import javax.swing.*;
48 import java.awt.*;
49 import java.io.File;
50
51 public class OrderEntryAppearanceServiceImpl extends OrderEntryAppearanceService {
52   private static final Icon EXCLUDE_FOLDER_ICON = IconLoader.getDisabledIcon(PlatformIcons.FOLDER_ICON);
53
54   private static final String NO_JDK = ProjectBundle.message("jdk.missing.item");
55
56   @NotNull
57   @Override
58   public CellAppearanceEx forOrderEntry(Project project, @NotNull final OrderEntry orderEntry, final boolean selected) {
59     if (orderEntry instanceof JdkOrderEntry) {
60       JdkOrderEntry jdkLibraryEntry = (JdkOrderEntry)orderEntry;
61       Sdk jdk = jdkLibraryEntry.getJdk();
62       if (!orderEntry.isValid()) {
63         final String oldJdkName = jdkLibraryEntry.getJdkName();
64         return FileAppearanceService.getInstance().forInvalidUrl(oldJdkName != null ? oldJdkName : NO_JDK);
65       }
66       return forJdk(jdk, false, selected, true);
67     }
68     else if (!orderEntry.isValid()) {
69       return FileAppearanceService.getInstance().forInvalidUrl(orderEntry.getPresentableName());
70     }
71     else if (orderEntry instanceof LibraryOrderEntry) {
72       LibraryOrderEntry libraryOrderEntry = (LibraryOrderEntry)orderEntry;
73       if (!libraryOrderEntry.isValid()) { //library can be removed
74         return FileAppearanceService.getInstance().forInvalidUrl(orderEntry.getPresentableName());
75       }
76       Library library = libraryOrderEntry.getLibrary();
77       assert library != null : libraryOrderEntry;
78       return forLibrary(project, library, !((LibraryEx)library).getInvalidRootUrls(OrderRootType.CLASSES).isEmpty());
79     }
80     else if (orderEntry.isSynthetic()) {
81       String presentableName = orderEntry.getPresentableName();
82       Icon icon = orderEntry instanceof ModuleSourceOrderEntry ? sourceFolderIcon(false) : null;
83       return new SimpleTextCellAppearance(presentableName, icon, SimpleTextAttributes.SYNTHETIC_ATTRIBUTES);
84     }
85     else if (orderEntry instanceof ModuleOrderEntry) {
86       final Icon icon = ModuleType.get(((ModuleOrderEntry)orderEntry).getModule()).getIcon();
87       return SimpleTextCellAppearance.regular(orderEntry.getPresentableName(), icon);
88     }
89     else {
90       return CompositeAppearance.single(orderEntry.getPresentableName());
91     }
92   }
93
94   @NotNull
95   @Override
96   public CellAppearanceEx forLibrary(Project project, @NotNull final Library library, final boolean hasInvalidRoots) {
97     final StructureConfigurableContext context = ProjectStructureConfigurable.getInstance(project).getContext();
98     final Icon icon = LibraryPresentationManager.getInstance().getCustomIcon(library, context);
99
100     final String name = library.getName();
101     if (name != null) {
102       return normalOrRedWaved(name, (icon != null ? icon : PlatformIcons.LIBRARY_ICON), hasInvalidRoots);
103     }
104
105     final String[] files = library.getUrls(OrderRootType.CLASSES);
106     if (files.length == 0) {
107       return SimpleTextCellAppearance.invalid(ProjectBundle.message("library.empty.library.item"), PlatformIcons.LIBRARY_ICON);
108     }
109     else if (files.length == 1) {
110       return forVirtualFilePointer(new LightFilePointer(files[0]));
111     }
112
113     final String url = StringUtil.trimEnd(files[0], JarFileSystem.JAR_SEPARATOR);
114     String text = ProjectBundle.message("library.unnamed.text", PathUtil.getFileName(url), files.length - 1);
115     return SimpleTextCellAppearance.regular(text, PlatformIcons.LIBRARY_ICON);
116   }
117
118   @NotNull
119   @Override
120   public CellAppearanceEx forJdk(@Nullable final Sdk jdk, final boolean isInComboBox, final boolean selected, final boolean showVersion) {
121     if (jdk == null) {
122       return FileAppearanceService.getInstance().forInvalidUrl(NO_JDK);
123     }
124
125     String name = jdk.getName();
126     CompositeAppearance appearance = new CompositeAppearance();
127     SdkType sdkType = (SdkType)jdk.getSdkType();
128     appearance.setIcon(sdkType.getIcon());
129     SimpleTextAttributes attributes = getTextAttributes(sdkType.sdkHasValidPath(jdk), selected);
130     CompositeAppearance.DequeEnd ending = appearance.getEnding();
131     ending.addText(name, attributes);
132
133     if (showVersion) {
134       String versionString = jdk.getVersionString();
135       if (versionString != null && !versionString.equals(name)) {
136         SimpleTextAttributes textAttributes = isInComboBox && !selected ? SimpleTextAttributes.SYNTHETIC_ATTRIBUTES :
137                                               SystemInfo.isMac && selected ? new SimpleTextAttributes(SimpleTextAttributes.STYLE_PLAIN, 
138                                                                                                       Color.WHITE): SimpleTextAttributes.GRAY_ATTRIBUTES;
139         ending.addComment(versionString, textAttributes);
140       }
141     }
142
143     return ending.getAppearance();
144   }
145
146   private static SimpleTextAttributes getTextAttributes(final boolean valid, final boolean selected) {
147     if (!valid) {
148       return SimpleTextAttributes.ERROR_ATTRIBUTES;
149     }
150     else if (selected && !(SystemInfo.isWinVistaOrNewer && UIManager.getLookAndFeel().getName().contains("Windows"))) {
151       return SimpleTextAttributes.SELECTED_SIMPLE_CELL_ATTRIBUTES;
152     }
153     else {
154       return SimpleTextAttributes.SIMPLE_CELL_ATTRIBUTES;
155     }
156   }
157
158   @NotNull
159   @Override
160   public CellAppearanceEx forContentFolder(@NotNull final ContentFolder folder) {
161     if (folder instanceof SourceFolder) {
162       return formatRelativePath(folder, PlatformIcons.FOLDER_ICON);
163     }
164     else if (folder instanceof ExcludeFolder) {
165       return formatRelativePath(folder, EXCLUDE_FOLDER_ICON);
166     }
167     else {
168       throw new RuntimeException(folder.getClass().getName());
169     }
170   }
171
172   @NotNull
173   @Override
174   public CellAppearanceEx forModule(@NotNull final Module module) {
175     return SimpleTextCellAppearance.regular(module.getName(), ModuleType.get(module).getIcon());
176   }
177
178   @NotNull
179   private static Icon sourceFolderIcon(final boolean testSource) {
180     return testSource ? PlatformIcons.TEST_SOURCE_FOLDER : PlatformIcons.SOURCE_FOLDERS_ICON;
181   }
182
183   @NotNull
184   private static CellAppearanceEx normalOrRedWaved(@NotNull final String text, @Nullable final Icon icon, final boolean waved) {
185     return waved ? new SimpleTextCellAppearance(text, icon, new SimpleTextAttributes(SimpleTextAttributes.STYLE_WAVED, null, JBColor.RED))
186                  : SimpleTextCellAppearance.regular(text, icon);
187   }
188
189   @NotNull
190   private static CellAppearanceEx forVirtualFilePointer(@NotNull final LightFilePointer filePointer) {
191     final VirtualFile file = filePointer.getFile();
192     return file != null ? FileAppearanceService.getInstance().forVirtualFile(file)
193                         : FileAppearanceService.getInstance().forInvalidUrl(filePointer.getPresentableUrl());
194   }
195
196   @NotNull
197   private static CellAppearanceEx formatRelativePath(@NotNull final ContentFolder folder, @NotNull final Icon icon) {
198     LightFilePointer folderFile = new LightFilePointer(folder.getUrl());
199     VirtualFile file = VirtualFileManager.getInstance().findFileByUrl(folder.getContentEntry().getUrl());
200     if (file == null) return FileAppearanceService.getInstance().forInvalidUrl(folderFile.getPresentableUrl());
201
202     String contentPath = file.getPath();
203     String relativePath;
204     SimpleTextAttributes textAttributes;
205     VirtualFile folderFileFile = folderFile.getFile();
206     if (folderFileFile == null) {
207       String absolutePath = folderFile.getPresentableUrl();
208       relativePath = absolutePath.startsWith(contentPath) ? absolutePath.substring(contentPath.length()) : absolutePath;
209       textAttributes = SimpleTextAttributes.ERROR_ATTRIBUTES;
210     }
211     else {
212       relativePath = VfsUtilCore.getRelativePath(folderFileFile, file, File.separatorChar);
213       textAttributes = SimpleTextAttributes.REGULAR_ATTRIBUTES;
214     }
215
216     relativePath = StringUtil.isEmpty(relativePath) ? "." + File.separatorChar : relativePath;
217     return new SimpleTextCellAppearance(relativePath, icon, textAttributes);
218   }
219 }