/*
* Copyright 2000-2009 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.fileTypes.impl;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.INativeFileType;
import com.intellij.openapi.fileTypes.UnknownFileType;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ui.update.ComparableObject;
import consulo.fileTypes.impl.FileSystemViewDelegate;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.io.File;
import java.util.*;
/**
* @author yole
*/
public class NativeFileIconUtil {
public static final NativeFileIconUtil INSTANCE = new NativeFileIconUtil();
private final Map<Ext, Icon> myIconCache = new HashMap<Ext, Icon>();
// on Windows .exe and .ico files provide their own icons which can differ for each file, cache them by full file path
private final Set<Ext> myCustomIconExtensions =
SystemInfo.isWindows ? new HashSet<Ext>(Arrays.asList(new Ext("exe"), new Ext("ico"))) : new HashSet<Ext>();
private final Map<String, Icon> myCustomIconCache = new HashMap<String, Icon>();
private static final Ext NO_EXT = new Ext(null);
private static final Ext CLOSED_DIR = new Ext(null);
public Icon getIcon(@NotNull VirtualFile file) {
if (!isNativeFileType(file)) return null;
final Ext ext = getExtension(file);
final String filePath = file.getPath();
Icon icon;
synchronized (myIconCache) {
if (!myCustomIconExtensions.contains(ext)) {
icon = ext != null ? myIconCache.get(ext) : null;
}
else {
icon = filePath != null ? myCustomIconCache.get(filePath) : null;
}
}
if (icon != null) {
return icon;
}
final File f = new File(filePath);
if (!f.exists()) {
return null;
}
try {
icon = getNativeIcon(f);
}
catch (Exception e) { // see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4854174
return null;
}
if (ext != null) {
synchronized (myIconCache) {
if (!myCustomIconExtensions.contains(ext)) {
myIconCache.put(ext, icon);
}
else if (filePath != null) {
myCustomIconCache.put(filePath, icon);
}
}
}
return icon;
/* return IconDeferrer.getInstance().defer(EmptyIcon.ICON_16, file, new Function<VirtualFile, Icon>() {
@Override
public Icon fun(VirtualFile virtualFile) {
final File f = new File(filePath);
if (!f.exists()) {
return null;
}
Icon icon;
try {
icon = getNativeIcon(f);
}
catch (Exception e) { // see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4854174
return null;
}
if (ext != null) {
synchronized (myIconCache) {
if (!myCustomIconExtensions.contains(ext)) {
myIconCache.put(ext, icon);
}
else if (filePath != null) {
myCustomIconCache.put(filePath, icon);
}
}
}
return icon;
}
}); */
}
@Nullable
public static Icon getNativeIcon(@Nullable File file) {
return file == null || file.isDirectory() ? null : FileSystemViewDelegate.getIcon(file);
}
private static Ext getExtension(final VirtualFile file) {
if (file.isDirectory()) {
if (file.getExtension() == null) {
return CLOSED_DIR;
}
else {
return new Ext(file.getExtension());
}
}
return file.getExtension() != null ? new Ext(file.getExtension()) : NO_EXT;
}
public static boolean isNativeFileType(VirtualFile file) {
return isNativeFileType(file.getFileType());
}
public static boolean isNativeFileType(FileType fileType) {
return fileType instanceof INativeFileType && ((INativeFileType)fileType).useNativeIcon() || fileType instanceof UnknownFileType;
}
private static class Ext extends ComparableObject.Impl {
private final Object[] myText;
private Ext(@Nullable String text) {
myText = new Object[]{text};
}
@Override
@NotNull
public Object[] getEqualityObjects() {
return myText;
}
@Override
public String toString() {
return myText[0] != null ? myText[0].toString() : null;
}
}
}