diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/FileAppearanceServiceImpl.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/FileAppearanceServiceImpl.java new file mode 100644 index 000000000000..277e35f16030 --- /dev/null +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/FileAppearanceServiceImpl.java @@ -0,0 +1,94 @@ +/* + * Copyright 2000-2011 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 com.intellij.openapi.roots.ui; + +import com.intellij.openapi.fileTypes.FileType; +import com.intellij.openapi.fileTypes.FileTypeManager; +import com.intellij.openapi.roots.ui.util.*; +import com.intellij.openapi.vfs.JarFileSystem; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileSystem; +import com.intellij.openapi.vfs.ex.http.HttpFileSystem; +import com.intellij.ui.HtmlListCellRenderer; +import com.intellij.ui.SimpleColoredComponent; +import com.intellij.util.PlatformIcons; +import org.jetbrains.annotations.NotNull; + +import java.io.File; + +public class FileAppearanceServiceImpl extends FileAppearanceService { + private static CellAppearanceEx EMPTY = new CellAppearanceEx() { + @Override + public void customize(SimpleColoredComponent component) { } + + @Override + public void customize(@NotNull HtmlListCellRenderer renderer) { } + + @Override + public String getText() { return ""; } + }; + + @NotNull + @Override + public CellAppearanceEx empty() { + return EMPTY; + } + + @NotNull + @Override + public CellAppearanceEx forVirtualFile(@NotNull final VirtualFile file) { + if (!file.isValid()) { + return forInvalidUrl(file.getPresentableUrl()); + } + + final VirtualFileSystem fileSystem = file.getFileSystem(); + if (fileSystem.getProtocol().equals(JarFileSystem.PROTOCOL)) { + return new JarSubfileCellAppearance(file); + } + if (fileSystem instanceof HttpFileSystem) { + return new HttpUrlCellAppearance(file); + } + if (file.isDirectory()) { + return SimpleTextCellAppearance.regular(file.getPresentableUrl(), PlatformIcons.FOLDER_ICON); + } + return new ValidFileCellAppearance(file); + } + + @NotNull + @Override + public CellAppearanceEx forIoFile(@NotNull final File file) { + final String absolutePath = file.getAbsolutePath(); + if (!file.exists()) { + return forInvalidUrl(absolutePath); + } + + if (file.isDirectory()) { + return SimpleTextCellAppearance.regular(absolutePath, PlatformIcons.FOLDER_ICON); + } + + final String name = file.getName(); + final FileType fileType = FileTypeManager.getInstance().getFileTypeByFileName(name); + final File parent = file.getParentFile(); + final CompositeAppearance appearance = CompositeAppearance.textComment(name, parent.getAbsolutePath()); + appearance.setIcon(fileType.getIcon()); + return appearance; + } + + @NotNull + public CellAppearanceEx forInvalidUrl(@NotNull final String text) { + return SimpleTextCellAppearance.invalid(text, PlatformIcons.INVALID_ENTRY_ICON); + } +} diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/OrderEntryAppearanceServiceImpl.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/OrderEntryAppearanceServiceImpl.java new file mode 100644 index 000000000000..e54f7796b3dd --- /dev/null +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/OrderEntryAppearanceServiceImpl.java @@ -0,0 +1,217 @@ +/* + * Copyright 2000-2011 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 com.intellij.openapi.roots.ui; + +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleType; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.ProjectBundle; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.roots.*; +import com.intellij.openapi.roots.libraries.Library; +import com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurable; +import com.intellij.openapi.roots.ui.configuration.libraries.LibraryPresentationManager; +import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext; +import com.intellij.openapi.roots.ui.util.CompositeAppearance; +import com.intellij.openapi.roots.ui.util.SimpleTextCellAppearance; +import com.intellij.openapi.util.IconLoader; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.JarFileSystem; +import com.intellij.openapi.vfs.VfsUtilCore; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileManager; +import com.intellij.ui.SimpleTextAttributes; +import com.intellij.util.PathUtil; +import com.intellij.util.PlatformIcons; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.awt.*; +import java.io.File; + +public class OrderEntryAppearanceServiceImpl extends OrderEntryAppearanceService { + private static final Icon EXCLUDE_FOLDER_ICON = IconLoader.getDisabledIcon(PlatformIcons.FOLDER_ICON); + + private static final String NO_JDK = ProjectBundle.message("jdk.missing.item"); + + private final Project myProject; + + public OrderEntryAppearanceServiceImpl(@NotNull final Project project) { + myProject = project; + } + + @NotNull + @Override + public CellAppearanceEx forOrderEntry(@NotNull final OrderEntry orderEntry, final boolean selected) { + if (orderEntry instanceof JdkOrderEntry) { + JdkOrderEntry jdkLibraryEntry = (JdkOrderEntry)orderEntry; + Sdk jdk = jdkLibraryEntry.getJdk(); + if (!orderEntry.isValid()) { + final String oldJdkName = jdkLibraryEntry.getJdkName(); + return FileAppearanceService.getInstance().forInvalidUrl(oldJdkName != null ? oldJdkName : NO_JDK); + } + return forJdk(jdk, false, selected, true); + } + else if (!orderEntry.isValid()) { + return FileAppearanceService.getInstance().forInvalidUrl(orderEntry.getPresentableName()); + } + else if (orderEntry instanceof LibraryOrderEntry) { + LibraryOrderEntry libraryOrderEntry = (LibraryOrderEntry)orderEntry; + if (!libraryOrderEntry.isValid()) { //library can be removed + return FileAppearanceService.getInstance().forInvalidUrl(orderEntry.getPresentableName()); + } + Library library = libraryOrderEntry.getLibrary(); + assert library != null : libraryOrderEntry; + return forLibrary(library, false); + } + else if (orderEntry.isSynthetic()) { + String presentableName = orderEntry.getPresentableName(); + Icon icon = orderEntry instanceof ModuleSourceOrderEntry ? sourceFolderIcon(false) : null; + return new SimpleTextCellAppearance(presentableName, icon, SimpleTextAttributes.SYNTHETIC_ATTRIBUTES); + } + else if (orderEntry instanceof ModuleOrderEntry) { + final Icon icon = ModuleType.get(((ModuleOrderEntry)orderEntry).getModule()).getNodeIcon(false); + return SimpleTextCellAppearance.regular(orderEntry.getPresentableName(), icon); + } + else { + return CompositeAppearance.single(orderEntry.getPresentableName()); + } + } + + @NotNull + @Override + public CellAppearanceEx forLibrary(@NotNull final Library library, final boolean hasInvalidRoots) { + final StructureConfigurableContext context = ProjectStructureConfigurable.getInstance(myProject).getContext(); + final Icon icon = LibraryPresentationManager.getInstance().getCustomIcon(library, context); + + final String name = library.getName(); + if (name != null) { + return normalOrRedWaved(name, (icon != null ? icon : PlatformIcons.LIBRARY_ICON), hasInvalidRoots); + } + + final String[] files = library.getUrls(OrderRootType.CLASSES); + if (files.length == 0) { + return SimpleTextCellAppearance.invalid(ProjectBundle.message("library.empty.library.item"), PlatformIcons.LIBRARY_ICON); + } + else if (files.length == 1) { + return forVirtualFilePointer(new LightFilePointer(files[0])); + } + + final String url = StringUtil.trimEnd(files[0], JarFileSystem.JAR_SEPARATOR); + return SimpleTextCellAppearance.regular(PathUtil.getFileName(url), PlatformIcons.LIBRARY_ICON); + } + + @NotNull + @Override + public CellAppearanceEx forJdk(@Nullable final Sdk jdk, final boolean isInComboBox, final boolean selected, final boolean showVersion) { + if (jdk == null) { + return FileAppearanceService.getInstance().forInvalidUrl(NO_JDK); + } + + String name = jdk.getName(); + CompositeAppearance appearance = new CompositeAppearance(); + appearance.setIcon(jdk.getSdkType().getIcon()); + VirtualFile homeDirectory = jdk.getHomeDirectory(); + SimpleTextAttributes attributes = getTextAttributes(homeDirectory != null && homeDirectory.isValid(), selected); + CompositeAppearance.DequeEnd ending = appearance.getEnding(); + ending.addText(name, attributes); + + if (showVersion) { + String versionString = jdk.getVersionString(); + if (versionString != null && !versionString.equals(name)) { + SimpleTextAttributes textAttributes = isInComboBox ? SimpleTextAttributes.SYNTHETIC_ATTRIBUTES : SimpleTextAttributes.GRAY_ATTRIBUTES; + ending.addComment(versionString, textAttributes); + } + } + + return ending.getAppearance(); + } + + private static SimpleTextAttributes getTextAttributes(final boolean valid, final boolean selected) { + if (!valid) { + return SimpleTextAttributes.ERROR_ATTRIBUTES; + } + else if (selected) { + return SimpleTextAttributes.SELECTED_SIMPLE_CELL_ATTRIBUTES; + } + else { + return SimpleTextAttributes.SIMPLE_CELL_ATTRIBUTES; + } + } + + @NotNull + @Override + public CellAppearanceEx forContentFolder(@NotNull final ContentFolder folder) { + if (folder instanceof SourceFolder) { + return formatRelativePath(folder, PlatformIcons.FOLDER_ICON); + } + else if (folder instanceof ExcludeFolder) { + return formatRelativePath(folder, EXCLUDE_FOLDER_ICON); + } + else { + throw new RuntimeException(folder.getClass().getName()); + } + } + + @NotNull + @Override + public CellAppearanceEx forModule(@NotNull final Module module) { + return SimpleTextCellAppearance.regular(module.getName(), ModuleType.get(module).getNodeIcon(false)); + } + + @NotNull + private static Icon sourceFolderIcon(final boolean testSource) { + return testSource ? PlatformIcons.TEST_SOURCE_FOLDER : PlatformIcons.SOURCE_FOLDERS_ICON; + } + + @NotNull + private static CellAppearanceEx normalOrRedWaved(@NotNull final String text, @Nullable final Icon icon, final boolean waved) { + return waved ? new SimpleTextCellAppearance(text, icon, new SimpleTextAttributes(SimpleTextAttributes.STYLE_WAVED, null, Color.RED)) + : SimpleTextCellAppearance.regular(text, icon); + } + + @NotNull + private static CellAppearanceEx forVirtualFilePointer(@NotNull final LightFilePointer filePointer) { + final VirtualFile file = filePointer.getFile(); + return file != null ? FileAppearanceService.getInstance().forVirtualFile(file) + : FileAppearanceService.getInstance().forInvalidUrl(filePointer.getPresentableUrl()); + } + + @NotNull + private static CellAppearanceEx formatRelativePath(@NotNull final ContentFolder folder, @NotNull final Icon icon) { + LightFilePointer folderFile = new LightFilePointer(folder.getUrl()); + VirtualFile file = VirtualFileManager.getInstance().findFileByUrl(folder.getContentEntry().getUrl()); + if (file == null) return FileAppearanceService.getInstance().forInvalidUrl(folderFile.getPresentableUrl()); + + String contentPath = file.getPath(); + String relativePath; + SimpleTextAttributes textAttributes; + VirtualFile folderFileFile = folderFile.getFile(); + if (folderFileFile == null) { + String absolutePath = folderFile.getPresentableUrl(); + relativePath = absolutePath.startsWith(contentPath) ? absolutePath.substring(contentPath.length()) : absolutePath; + textAttributes = SimpleTextAttributes.ERROR_ATTRIBUTES; + } + else { + relativePath = VfsUtilCore.getRelativePath(folderFileFile, file, File.separatorChar); + textAttributes = SimpleTextAttributes.REGULAR_ATTRIBUTES; + } + + relativePath = StringUtil.isEmpty(relativePath) ? "." + File.separatorChar : relativePath; + return new SimpleTextCellAppearance(relativePath, icon, textAttributes); + } +} diff --git a/platform/lang-api/src/com/intellij/openapi/roots/ui/OrderEntryAppearanceService.java b/platform/lang-api/src/com/intellij/openapi/roots/ui/OrderEntryAppearanceService.java new file mode 100644 index 000000000000..b7359020ca04 --- /dev/null +++ b/platform/lang-api/src/com/intellij/openapi/roots/ui/OrderEntryAppearanceService.java @@ -0,0 +1,47 @@ +/* + * Copyright 2000-2011 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 com.intellij.openapi.roots.ui; + +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.openapi.roots.ContentFolder; +import com.intellij.openapi.roots.OrderEntry; +import com.intellij.openapi.roots.libraries.Library; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public abstract class OrderEntryAppearanceService { + public static OrderEntryAppearanceService getInstance(@NotNull final Project project) { + return ServiceManager.getService(project, OrderEntryAppearanceService.class); + } + + @NotNull + public abstract CellAppearanceEx forOrderEntry(@NotNull OrderEntry orderEntry, boolean selected); + + @NotNull + public abstract CellAppearanceEx forLibrary(@NotNull Library library, boolean hasInvalidRoots); + + @NotNull + public abstract CellAppearanceEx forJdk(@Nullable Sdk jdk, boolean isInComboBox, boolean selected, boolean showVersion); + + @NotNull + public abstract CellAppearanceEx forContentFolder(@NotNull ContentFolder folder); + + @NotNull + public abstract CellAppearanceEx forModule(@NotNull Module module); +} diff --git a/platform/platform-api/src/com/intellij/openapi/roots/ui/CellAppearanceEx.java b/platform/platform-api/src/com/intellij/openapi/roots/ui/CellAppearanceEx.java new file mode 100644 index 000000000000..bfc7d948c870 --- /dev/null +++ b/platform/platform-api/src/com/intellij/openapi/roots/ui/CellAppearanceEx.java @@ -0,0 +1,24 @@ +/* + * Copyright 2000-2011 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 com.intellij.openapi.roots.ui; + +import com.intellij.openapi.roots.ui.util.CellAppearance; +import com.intellij.ui.HtmlListCellRenderer; +import org.jetbrains.annotations.NotNull; + +public interface CellAppearanceEx extends CellAppearance { + void customize(@NotNull HtmlListCellRenderer renderer); +} diff --git a/platform/platform-api/src/com/intellij/openapi/roots/ui/FileAppearanceService.java b/platform/platform-api/src/com/intellij/openapi/roots/ui/FileAppearanceService.java new file mode 100644 index 000000000000..e1ef1a89d917 --- /dev/null +++ b/platform/platform-api/src/com/intellij/openapi/roots/ui/FileAppearanceService.java @@ -0,0 +1,40 @@ +/* + * Copyright 2000-2011 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 com.intellij.openapi.roots.ui; + +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; + +import java.io.File; + +public abstract class FileAppearanceService { + public static FileAppearanceService getInstance() { + return ServiceManager.getService(FileAppearanceService.class); + } + + @NotNull + public abstract CellAppearanceEx empty(); + + @NotNull + public abstract CellAppearanceEx forVirtualFile(@NotNull VirtualFile file); + + @NotNull + public abstract CellAppearanceEx forIoFile(@NotNull File file); + + @NotNull + public abstract CellAppearanceEx forInvalidUrl(@NotNull String url); +} diff --git a/platform/platform-resources/src/META-INF/PlatformExtensions.xml b/platform/platform-resources/src/META-INF/PlatformExtensions.xml index 69ca6878ffac..aaf13708ec78 100644 --- a/platform/platform-resources/src/META-INF/PlatformExtensions.xml +++ b/platform/platform-resources/src/META-INF/PlatformExtensions.xml @@ -130,6 +130,9 @@ + + + serviceImplementation="com.intellij.execution.testframework.export.ExportTestResultsConfiguration"/> + serviceImplementation="com.intellij.execution.testframework.autotest.AutoTestManager"/> + + +