repaint file tab icon after dumb mode fixed, evaluate icons in app pool instead of dedicated thread

This commit is contained in:
Alexey Kudravtsev
2015-09-23 16:33:26 +03:00
parent 3794adaa71
commit 79964d1579
2 changed files with 268 additions and 15 deletions
@@ -28,12 +28,13 @@ import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.ui.tabs.impl.TabLabel;
import com.intellij.util.Alarm;
import com.intellij.util.ConcurrencyUtil;
import com.intellij.util.Function;
import com.intellij.util.concurrency.BoundedTaskExecutor;
import com.intellij.util.containers.TransferToEDTQueue;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.ide.PooledThreadExecutor;
import javax.swing.*;
import javax.swing.plaf.TreeUI;
@@ -41,7 +42,7 @@ import javax.swing.plaf.basic.BasicTreeUI;
import java.awt.*;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.Executor;
public class DeferredIconImpl<T> implements DeferredIcon {
private static final int MIN_AUTO_UPDATE_MILLIS = 950;
@@ -58,10 +59,13 @@ public class DeferredIconImpl<T> implements DeferredIcon {
private long myLastCalcTime;
private long myLastTimeSpent;
private static final ThreadPoolExecutor ourIconsCalculatingExecutor = ConcurrencyUtil.newSingleThreadExecutor("Icons");
private static final Executor ourIconsCalculatingExecutor = new BoundedTaskExecutor(PooledThreadExecutor.INSTANCE, 1);
private final IconListener<T> myEvalListener;
private static final TransferToEDTQueue<Runnable> ourLaterInvocator = TransferToEDTQueue.createRunnableMerger("Deferred icon later invocator", 200);
private static class Holder {
private static final boolean CHECK_CONSISTENCY = ApplicationManager.getApplication().isUnitTestMode();
}
public DeferredIconImpl(Icon baseIcon, T param, @NotNull Function<T, Icon> evaluator, @NotNull IconListener<T> listener, boolean autoUpdatable) {
this(baseIcon, param, true, evaluator, listener, autoUpdatable);
@@ -99,7 +103,7 @@ public class DeferredIconImpl<T> implements DeferredIcon {
final Component target = getTarget(c);
final Component paintingParent = SwingUtilities.getAncestorOfClass(PaintingParent.class, c);
final Rectangle paintingParentRec = paintingParent == null ? null : ((PaintingParent)paintingParent).getChildRec(c);
ourIconsCalculatingExecutor.submit(new Runnable() {
ourIconsCalculatingExecutor.execute(new Runnable() {
@Override
public void run() {
int oldWidth = myDelegateIcon.getIconWidth();
@@ -113,12 +117,7 @@ public class DeferredIconImpl<T> implements DeferredIcon {
IconDeferrerImpl.evaluateDeferred(new Runnable() {
@Override
public void run() {
try {
evaluated[0] = nonNull(myEvaluator.fun(myParam));
}
catch (IndexNotReadyException e) {
evaluated[0] = EMPTY_ICON;
}
evaluated[0] = evaluate();
}
});
if (myAutoUpdatable) {
@@ -136,7 +135,7 @@ public class DeferredIconImpl<T> implements DeferredIcon {
IconDeferrerImpl.evaluateDeferred(new Runnable() {
@Override
public void run() {
evaluated[0] = nonNull(myEvaluator.fun(myParam));
evaluated[0] = evaluate();
}
});
if (myAutoUpdatable) {
@@ -246,7 +245,9 @@ public class DeferredIconImpl<T> implements DeferredIcon {
result = EMPTY_ICON;
}
checkDoesntReferenceThis(result);
if (Holder.CHECK_CONSISTENCY) {
checkDoesntReferenceThis(result);
}
return result;
}
@@ -341,13 +342,19 @@ public class DeferredIconImpl<T> implements DeferredIcon {
void evalDone(DeferredIconImpl<T> source, T key, @NotNull Icon result);
}
public static boolean equalIcons(Icon icon1, Icon icon2) {
static boolean equalIcons(Icon icon1, Icon icon2) {
if (icon1 instanceof DeferredIconImpl) {
icon1 = ((DeferredIconImpl)icon1).myDelegateIcon;
return ((DeferredIconImpl)icon1).isDeferredAndEqual(icon2);
}
if (icon2 instanceof DeferredIconImpl) {
icon2 = ((DeferredIconImpl)icon2).myDelegateIcon;
return ((DeferredIconImpl)icon2).isDeferredAndEqual(icon1);
}
return Comparing.equal(icon1, icon2);
}
private boolean isDeferredAndEqual(Icon icon) {
return icon instanceof DeferredIconImpl &&
Comparing.equal(myParam, ((DeferredIconImpl)icon).myParam) &&
equalIcons(myDelegateIcon, ((DeferredIconImpl)icon).myDelegateIcon);
}
}
@@ -0,0 +1,246 @@
/*
* Copyright 2000-2015 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.editor.impl;
import com.intellij.openapi.util.Iconable;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.testFramework.PlatformTestCase;
import com.intellij.ui.DeferredIcon;
import com.intellij.util.FileContentUtilCore;
import com.intellij.util.IconUtil;
import com.intellij.util.TimeoutUtil;
import javax.swing.*;
import java.awt.*;
import java.awt.image.ImageObserver;
import java.io.IOException;
import java.text.AttributedCharacterIterator;
public class IconUtilTest extends PlatformTestCase {
public void testIconDeferrerDoesNotDeferIconsAdInfinitum() throws IOException {
VirtualFile file = createTempFile("txt", null, "hkjh", CharsetToolkit.UTF8_CHARSET);
Icon icon = IconUtil.getIcon(file, Iconable.ICON_FLAG_VISIBILITY, getProject());
assertTrue(icon instanceof DeferredIcon);
Graphics g = new Graphics() {
@Override
public Graphics create() {
return this;
}
@Override
public void translate(int x, int y) {
}
@Override
public Color getColor() {
return null;
}
@Override
public void setColor(Color c) {
}
@Override
public void setPaintMode() {
}
@Override
public void setXORMode(Color c1) {
}
@Override
public Font getFont() {
return null;
}
@Override
public void setFont(Font font) {
}
@Override
public FontMetrics getFontMetrics(Font f) {
return null;
}
@Override
public Rectangle getClipBounds() {
return null;
}
@Override
public void clipRect(int x, int y, int width, int height) {
}
@Override
public void setClip(int x, int y, int width, int height) {
}
@Override
public Shape getClip() {
return null;
}
@Override
public void setClip(Shape clip) {
}
@Override
public void copyArea(int x, int y, int width, int height, int dx, int dy) {
}
@Override
public void drawLine(int x1, int y1, int x2, int y2) {
}
@Override
public void fillRect(int x, int y, int width, int height) {
}
@Override
public void clearRect(int x, int y, int width, int height) {
}
@Override
public void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) {
}
@Override
public void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) {
}
@Override
public void drawOval(int x, int y, int width, int height) {
}
@Override
public void fillOval(int x, int y, int width, int height) {
}
@Override
public void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) {
}
@Override
public void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) {
}
@Override
public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints) {
}
@Override
public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints) {
}
@Override
public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints) {
}
@Override
public void drawString(String str, int x, int y) {
}
@Override
public void drawString(AttributedCharacterIterator iterator, int x, int y) {
}
@Override
public boolean drawImage(Image img, int x, int y, ImageObserver observer) {
return false;
}
@Override
public boolean drawImage(Image img, int x, int y, int width, int height, ImageObserver observer) {
return false;
}
@Override
public boolean drawImage(Image img, int x, int y, Color bgcolor, ImageObserver observer) {
return false;
}
@Override
public boolean drawImage(Image img, int x, int y, int width, int height, Color bgcolor, ImageObserver observer) {
return false;
}
@Override
public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver observer) {
return false;
}
@Override
public boolean drawImage(Image img,
int dx1,
int dy1,
int dx2,
int dy2,
int sx1,
int sy1,
int sx2,
int sy2,
Color bgcolor,
ImageObserver observer) {
return false;
}
@Override
public void dispose() {
}
};
icon.paintIcon(new JLabel(), g, 0, 0); // force to eval
TimeoutUtil.sleep(1000); // give chance to evaluate
Icon icon2 = IconUtil.getIcon(file, Iconable.ICON_FLAG_VISIBILITY, getProject());
assertSame(icon, icon2);
FileContentUtilCore.reparseFiles(file);
Icon icon3 = IconUtil.getIcon(file, Iconable.ICON_FLAG_VISIBILITY, getProject());
assertNotSame(icon2, icon3);
}
@Override
protected boolean isRunInWriteAction() {
return false;
}
}