Deferred class icons for project view

This commit is contained in:
Maxim Shafirov
2009-10-09 17:47:52 +04:00
parent e459a2cb52
commit 7bd1718cf5
4 changed files with 86 additions and 12 deletions
@@ -27,6 +27,7 @@ public class ElementPresentationUtil {
public static final Icon JUNIT_TEST_MARK = IconLoader.getIcon("/nodes/junitTestMark.png");
private static final Icon RUNNABLE_MARK = IconLoader.getIcon("/nodes/runnableMark.png");
private ElementPresentationUtil() {
}
@@ -83,6 +84,18 @@ public class ElementPresentationUtil {
&& CompilerConfiguration.getInstance(project).isExcludedFromCompilation(vFile);
}
public static int getBasicClassKind(PsiClass aClass) {
if (!aClass.isValid()) return CLASS_KIND_CLASS;
if (aClass.isAnnotationType()) return CLASS_KIND_ANNOTATION;
if (aClass.isEnum()) return CLASS_KIND_ENUM;
if (aClass.isInterface()) return CLASS_KIND_INTERFACE;
if (aClass instanceof JspClass) return CLASS_KIND_JSP;
if (aClass instanceof PsiAnonymousClass) return CLASS_KIND_ANONYMOUS;
return CLASS_KIND_CLASS;
}
public static int getClassKind(final PsiClass aClass) {
if (!aClass.isValid()) {
aClass.putUserData(CLASS_KIND_KEY, null);
@@ -162,8 +175,7 @@ public class ElementPresentationUtil {
BASE_ICON.put(CLASS_KIND_RUNNABLE, Icons.CLASS_ICON);
}
public static Icon getClassBaseIcon(final PsiClass aClass) {
final int classKind = getClassKind(aClass);
public static Icon getClassIconOfKind(PsiClass aClass, int classKind) {
final boolean isAbstract = aClass.hasModifierProperty(PsiModifier.ABSTRACT);
return BASE_ICON.get(classKind | (isAbstract ? FLAGS_ABSTRACT : 0));
}
@@ -24,7 +24,9 @@ import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.PackageScope;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.util.*;
import com.intellij.ui.IconDeferrer;
import com.intellij.ui.RowIcon;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.ReflectionCache;
import com.intellij.util.SmartList;
@@ -267,11 +269,52 @@ public class PsiClassImplUtil {
return (Map<String, List<Pair<T, PsiSubstitutor>>>)value.getValue().get(memberClazz);
}
private static class ClassIconRequest {
public PsiClass psiClass;
public int flags;
private ClassIconRequest(PsiClass psiClass, int flags) {
this.psiClass = psiClass;
this.flags = flags;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ClassIconRequest)) return false;
ClassIconRequest that = (ClassIconRequest)o;
if (flags != that.flags) return false;
if (psiClass != null ? !psiClass.equals(that.psiClass) : that.psiClass != null) return false;
return true;
}
@Override
public int hashCode() {
int result = psiClass != null ? psiClass.hashCode() : 0;
result = 31 * result + flags;
return result;
}
}
private static final Function<ClassIconRequest, Icon> FULL_ICON_EVALUATOR = new Function<ClassIconRequest, Icon>() {
public Icon fun(ClassIconRequest r) {
final boolean isLocked = (r.flags & Iconable.ICON_FLAG_READ_STATUS) != 0 && !r.psiClass.isWritable();
Icon symbolIcon = ElementPresentationUtil.getClassIconOfKind(r.psiClass, ElementPresentationUtil.getClassKind(r.psiClass));
RowIcon baseIcon = ElementBase.createLayeredIcon(symbolIcon, ElementPresentationUtil.getFlags(r.psiClass, isLocked));
return ElementPresentationUtil.addVisibilityIcon(r.psiClass, r.flags, baseIcon);
}
};
public static Icon getClassIcon(final int flags, final PsiClass aClass) {
final boolean isLocked = (flags & Iconable.ICON_FLAG_READ_STATUS) != 0 && !aClass.isWritable();
Icon symbolIcon = ElementPresentationUtil.getClassBaseIcon(aClass);
RowIcon baseIcon = ElementBase.createLayeredIcon(symbolIcon, ElementPresentationUtil.getFlags(aClass, isLocked));
return ElementPresentationUtil.addVisibilityIcon(aClass, flags, baseIcon);
Icon symbolIcon = ElementPresentationUtil.getClassIconOfKind(aClass, ElementPresentationUtil.getBasicClassKind(aClass));
RowIcon baseIcon = ElementBase.createLayeredIcon(symbolIcon, 0);
return IconDeferrer.getInstance().defer(ElementPresentationUtil.addVisibilityIcon(aClass, flags, baseIcon),
new ClassIconRequest(aClass, flags),
FULL_ICON_EVALUATOR);
}
public static SearchScope getClassUseScope(final PsiClass aClass) {
@@ -123,11 +123,7 @@ public abstract class AbstractPsiBasedNode<Value> extends ProjectViewNode<Value>
catch (IndexNotReadyException ignored) {
}
data.setPresentableText(myName);
try {
data.setTooltip(calcTooltip());
}
catch (IndexNotReadyException ignored) {
}
try {
if (isDeprecated()) {
data.setAttributesKey(CodeInsightColors.DEPRECATED_ATTRIBUTES);
@@ -7,6 +7,7 @@ import com.intellij.concurrency.Job;
import com.intellij.concurrency.JobScheduler;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.IndexNotReadyException;
import com.intellij.util.Alarm;
import com.intellij.util.Function;
import com.intellij.util.ui.EmptyIcon;
@@ -15,8 +16,11 @@ import javax.swing.plaf.TreeUI;
import javax.swing.plaf.basic.BasicTreeUI;
import java.awt.*;
import java.lang.ref.WeakReference;
import java.util.LinkedHashSet;
import java.util.Set;
public class DeferredIconImpl<T> implements DeferredIcon {
private static final RepaintScheduler ourRepaintScheduler = new RepaintScheduler();
private volatile Icon myDelegateIcon;
private final Function<T, Icon> myEvaluator;
private volatile boolean myIsScheduled = false;
@@ -96,7 +100,7 @@ public class DeferredIconImpl<T> implements DeferredIcon {
c.repaint(x, y, getIconWidth(), getIconHeight());
}
else {
target.repaint();
ourRepaintScheduler.pushDirtyComponent(target);
}
}
});
@@ -171,4 +175,23 @@ public class DeferredIconImpl<T> implements DeferredIcon {
lastTarget.repaint();
}
}
private static class RepaintScheduler {
private final Alarm myAlarm = new Alarm();
private final Set<Component> myQueue = new LinkedHashSet<Component>();
public void pushDirtyComponent(Component c) {
myAlarm.cancelAllRequests();
myAlarm.addRequest(new Runnable() {
public void run() {
for (Component component : myQueue) {
component.repaint();
}
myQueue.clear();
}
}, 50);
myQueue.add(c);
}
}
}