/*
* Copyright 2013-2016 consulo.io
*
* 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 consulo.fileTypes.impl;
import com.intellij.icons.AllIcons;
import com.intellij.ide.presentation.VirtualFilePresentation;
import com.intellij.openapi.fileTypes.impl.NativeFileIconUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Iconable;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.VFileProperty;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.WritingAccessProvider;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiManager;
import com.intellij.ui.IconDeferrer;
import com.intellij.util.AnyIconKey;
import com.intellij.util.BitUtil;
import com.intellij.util.NullableFunction;
import consulo.annotations.RequiredReadAction;
import consulo.ide.IconDescriptor;
import consulo.ide.IconDescriptorUpdaters;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
/**
* @author VISTALL
* @since 20-Nov-16.
*/
public class VfsIconUtil {
private static NullableFunction<AnyIconKey<VirtualFile>, Icon> ourVirtualFileIconFunc = new NullableFunction<AnyIconKey<VirtualFile>, Icon>() {
@Override
@RequiredReadAction
public Icon fun(final AnyIconKey<VirtualFile> key) {
final VirtualFile file = key.getObject();
final int flags = key.getFlags();
Project project = key.getProject();
if (!file.isValid() || project != null && (project.isDisposed() || !wasEverInitialized(project))) return null;
boolean processedDescriptors = false;
final Icon nativeIcon = NativeFileIconUtil.INSTANCE.getIcon(file);
IconDescriptor iconDescriptor = new IconDescriptor(nativeIcon == null ? VirtualFilePresentation.getIcon(file) : nativeIcon);
if (project != null) {
PsiManager manager = PsiManager.getInstance(project);
final PsiElement element = file.isDirectory() ? manager.findDirectory(file) : manager.findFile(file);
if (element != null) {
IconDescriptorUpdaters.processExistingDescriptor(iconDescriptor, element, flags);
processedDescriptors = true;
}
}
// if descriptors not processed - we need add layer icon obviously
if (!processedDescriptors && file.is(VFileProperty.SYMLINK)) {
iconDescriptor.addLayerIcon(AllIcons.Nodes.Symlink);
}
if (BitUtil.isSet(flags, Iconable.ICON_FLAG_READ_STATUS)) {
final boolean isLocked = !file.isWritable() || !WritingAccessProvider.isPotentiallyWritable(file, project);
if (isLocked) {
iconDescriptor.addLayerIcon(AllIcons.Nodes.Locked);
}
}
Icon icon = iconDescriptor.toIcon();
Iconable.LastComputedIcon.put(file, icon, flags);
return icon;
}
};
private static final Key<Boolean> PROJECT_WAS_EVER_INITIALIZED = Key.create("iconDeferrer:projectWasEverInitialized");
private static boolean wasEverInitialized(@NotNull Project project) {
Boolean was = project.getUserData(PROJECT_WAS_EVER_INITIALIZED);
if (was == null) {
if (project.isInitialized()) {
was = Boolean.valueOf(true);
project.putUserData(PROJECT_WAS_EVER_INITIALIZED, was);
}
else {
was = Boolean.valueOf(false);
}
}
return was.booleanValue();
}
@Nullable
public static Icon getIcon(@NotNull final VirtualFile file, @Iconable.IconFlags final int flags, @Nullable final Project project) {
Icon icon = Iconable.LastComputedIcon.get(file, flags);
if (icon == null) {
icon = VirtualFilePresentation.getIcon(file);
}
return IconDeferrer.getInstance().defer(icon, new AnyIconKey<>(file, project, flags), ourVirtualFileIconFunc);
}
}