IDEA-52627 - Icons for native files in project view flicker 94.508
authorKirill Kalishev <kirill.kalishev@jetbrains.com>
Sun, 7 Mar 2010 10:25:23 +0000 (13:25 +0300)
committerKirill Kalishev <kirill.kalishev@jetbrains.com>
Sun, 7 Mar 2010 10:25:23 +0000 (13:25 +0300)
platform/lang-impl/src/com/intellij/openapi/fileTypes/impl/NativeFileIconProvider.java
platform/platform-api/src/com/intellij/util/IconUtil.java

index 4212135e063f7255dd774a5a00480675228c7406..a55591b588d5cda33cb425aca978395f7385e377 100644 (file)
@@ -24,6 +24,7 @@ import com.intellij.openapi.util.SystemInfo;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.ui.DeferredIconImpl;
 import com.intellij.util.Function;
+import com.intellij.util.ui.update.ComparableObject;
 import org.jetbrains.annotations.Nullable;
 
 import javax.swing.*;
@@ -35,17 +36,19 @@ import java.util.*;
  */
 public class NativeFileIconProvider implements FileIconProvider {
   private JFileChooser myFileChooser = new JFileChooser();
-  private final Map<String, Icon> myIconCache = new HashMap<String, Icon>();
+  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<String> myCustomIconExtensions =
-    SystemInfo.isWindows ? new HashSet<String>(Arrays.asList("exe", "ico")) : new HashSet<String>();
+  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);
+
   public Icon getIcon(VirtualFile file, int flags, @Nullable Project project) {
     if (!(file.getFileType() instanceof NativeFileType) && !(file.getFileType() instanceof UnknownFileType)) {
       return null;
     }
-    final String ext = file.getExtension();
+    final Ext ext = file.getExtension() != null ? new Ext(file.getExtension()) : NO_EXT;
     final String filePath = file.getPath();
 
     Icon icon;
@@ -87,4 +90,22 @@ public class NativeFileIconProvider implements FileIconProvider {
       }
     });
   }
+
+  private static class Ext extends ComparableObject.Impl {
+
+    private final Object[] myText;
+
+    private Ext(@Nullable String text) {
+      myText = new Object[] {text};
+    }
+
+    public Object[] getEqualityObjects() {
+      return myText;
+    }
+
+    @Override
+    public String toString() {
+      return myText[0] != null ? myText[0].toString() : null;
+    }
+  }
 }
index ae0e5233ba62366897bfb8bc673f1b36ae2fc0ab..cbd8efe22e2b23712c48c37eb7db49a10ee1f99e 100644 (file)
@@ -23,6 +23,7 @@ import com.intellij.openapi.project.DumbService;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.util.IconLoader;
 import com.intellij.openapi.util.Iconable;
+import com.intellij.openapi.util.Key;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.ui.IconDeferrer;
 import com.intellij.ui.RowIcon;
@@ -35,6 +36,8 @@ import javax.swing.*;
 
 public class IconUtil {
 
+  public static final Key<Icon> LAST_FILE_ICON = Key.create("lastVFileIcon");
+
   private IconUtil() {
   }
 
@@ -85,7 +88,9 @@ public class IconUtil {
   }
 
   public static Icon getIcon(final VirtualFile file, final int flags, final Project project) {
-    return IconDeferrer.getInstance().defer(file.getIcon(), new FileIconKey(file, project, flags), new Function<FileIconKey, Icon>() {
+    Icon lastIcon = file.getUserData(LAST_FILE_ICON);
+
+    return IconDeferrer.getInstance().defer(lastIcon != null ? lastIcon : file.getIcon(), new FileIconKey(file, project, flags), new Function<FileIconKey, Icon>() {
       public Icon fun(final FileIconKey key) {
         VirtualFile file = key.getFile();
         int flags = key.getFlags();
@@ -106,9 +111,11 @@ public class IconUtil {
         }
 
         if ((flags & Iconable.ICON_FLAG_READ_STATUS) != 0 && !file.isWritable()) {
-          return new LayeredIcon(icon, Icons.LOCKED_ICON);
+          icon = new LayeredIcon(icon, Icons.LOCKED_ICON);
         }
         
+        file.putUserData(LAST_FILE_ICON, icon);
+
         return icon;
       }
     });