From d6ff7e141f8e60dd2e605c5a0a632967de037a8a Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 16 Sep 2015 15:19:35 +0300 Subject: [PATCH] optimisation: number of repaint events reduced --- .../src/com/intellij/ui/IconDeferrer.java | 6 +++- .../src/com/intellij/ui/DeferredIconImpl.java | 27 ++++++++++++----- .../src/com/intellij/ui/IconDeferrerImpl.java | 7 ++++- .../src/com/intellij/ui/tabs/TabInfo.java | 30 +++++++++++++------ 4 files changed, 51 insertions(+), 19 deletions(-) diff --git a/platform/core-api/src/com/intellij/ui/IconDeferrer.java b/platform/core-api/src/com/intellij/ui/IconDeferrer.java index b5b5c46932a0..9a50b12a3031 100644 --- a/platform/core-api/src/com/intellij/ui/IconDeferrer.java +++ b/platform/core-api/src/com/intellij/ui/IconDeferrer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -20,6 +20,7 @@ package com.intellij.ui; import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.util.Comparing; import com.intellij.util.Function; import org.jetbrains.annotations.NotNull; @@ -32,4 +33,7 @@ public abstract class IconDeferrer { public abstract Icon defer(Icon base, T param, @NotNull Function f); public abstract Icon deferAutoUpdatable(Icon base, T param, @NotNull Function f); + public boolean equalIcons(Icon icon1, Icon icon2) { + return Comparing.equal(icon1, icon2); + } } \ No newline at end of file diff --git a/platform/lang-impl/src/com/intellij/ui/DeferredIconImpl.java b/platform/lang-impl/src/com/intellij/ui/DeferredIconImpl.java index 182954edb85b..f4bc20dbbd1f 100644 --- a/platform/lang-impl/src/com/intellij/ui/DeferredIconImpl.java +++ b/platform/lang-impl/src/com/intellij/ui/DeferredIconImpl.java @@ -24,6 +24,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.util.ProgressIndicatorUtils; import com.intellij.openapi.project.IndexNotReadyException; +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; @@ -48,14 +49,14 @@ public class DeferredIconImpl implements DeferredIcon { @NotNull private volatile Icon myDelegateIcon; private Function myEvaluator; - private volatile boolean myIsScheduled = false; + private volatile boolean myIsScheduled; private T myParam; private static final Icon EMPTY_ICON = JBUI.emptyIcon(16); private final boolean myNeedReadAction; private boolean myDone; private final boolean myAutoUpdatable; - private long myLastCalcTime = 0L; - private long myLastTimeSpent = 0L; + private long myLastCalcTime; + private long myLastTimeSpent; private static final ThreadPoolExecutor ourIconsCalculatingExecutor = ConcurrencyUtil.newSingleThreadExecutor("Icons"); @@ -85,7 +86,7 @@ public class DeferredIconImpl implements DeferredIcon { } @Override - public void paintIcon(final Component c, final Graphics g, final int x, final int y) { + public void paintIcon(@NotNull final Component c, @NotNull final Graphics g, final int x, final int y) { if (!(myDelegateIcon instanceof DeferredIconImpl && ((DeferredIconImpl)myDelegateIcon).myDelegateIcon instanceof DeferredIconImpl)) { myDelegateIcon.paintIcon(c, g, x, y); //SOE protection } @@ -165,7 +166,7 @@ public class DeferredIconImpl implements DeferredIcon { if (actualTarget == null) return; if (shouldRevalidate) { - // revalidate will not work: jtree caches size of nodes + // revalidate will not work: JTree caches size of nodes if (actualTarget instanceof JTree) { final TreeUI ui = ((JTree)actualTarget).getUI(); if (ui instanceof BasicTreeUI) { @@ -283,7 +284,7 @@ public class DeferredIconImpl implements DeferredIcon { } public boolean isDone() { - if (myAutoUpdatable && myDone && myLastCalcTime > 0 && (System.currentTimeMillis() - myLastCalcTime) > Math.max(MIN_AUTO_UPDATE_MILLIS, 10 * myLastTimeSpent)) { + if (myAutoUpdatable && myDone && myLastCalcTime > 0 && System.currentTimeMillis() - myLastCalcTime > Math.max(MIN_AUTO_UPDATE_MILLIS, 10 * myLastTimeSpent)) { myDone = false; myIsScheduled = false; } @@ -294,7 +295,7 @@ public class DeferredIconImpl implements DeferredIcon { private final Alarm myAlarm = new Alarm(); private final Set myQueue = new LinkedHashSet(); - public void pushDirtyComponent(@NotNull Component c, final Rectangle rec) { + private void pushDirtyComponent(@NotNull Component c, final Rectangle rec) { ApplicationManager.getApplication().assertIsDispatchThread(); // assert myQueue accessed from EDT only myAlarm.cancelAllRequests(); myAlarm.addRequest(new Runnable() { @@ -336,7 +337,17 @@ public class DeferredIconImpl implements DeferredIcon { } } - public interface IconListener { + interface IconListener { void evalDone(DeferredIconImpl source, T key, @NotNull Icon result); } + + public static boolean equalIcons(Icon icon1, Icon icon2) { + if (icon1 instanceof DeferredIconImpl) { + icon1 = ((DeferredIconImpl)icon1).myDelegateIcon; + } + if (icon2 instanceof DeferredIconImpl) { + icon2 = ((DeferredIconImpl)icon2).myDelegateIcon; + } + return Comparing.equal(icon1, icon2); + } } diff --git a/platform/lang-impl/src/com/intellij/ui/IconDeferrerImpl.java b/platform/lang-impl/src/com/intellij/ui/IconDeferrerImpl.java index 7f2cf33332eb..01e5341737fd 100644 --- a/platform/lang-impl/src/com/intellij/ui/IconDeferrerImpl.java +++ b/platform/lang-impl/src/com/intellij/ui/IconDeferrerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -125,4 +125,9 @@ public class IconDeferrerImpl extends IconDeferrer { myEvaluationIsInProgress.set(Boolean.FALSE); } } + + @Override + public boolean equalIcons(Icon icon1, Icon icon2) { + return DeferredIconImpl.equalIcons(icon1, icon2); + } } diff --git a/platform/platform-api/src/com/intellij/ui/tabs/TabInfo.java b/platform/platform-api/src/com/intellij/ui/tabs/TabInfo.java index d1dfa976e479..8ac9efbbb2cf 100644 --- a/platform/platform-api/src/com/intellij/ui/tabs/TabInfo.java +++ b/platform/platform-api/src/com/intellij/ui/tabs/TabInfo.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * 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. @@ -18,7 +18,9 @@ package com.intellij.ui.tabs; import com.intellij.icons.AllIcons; import com.intellij.openapi.actionSystem.ActionGroup; import com.intellij.openapi.ui.Queryable; +import com.intellij.openapi.util.Comparing; import com.intellij.reference.SoftReference; +import com.intellij.ui.IconDeferrer; import com.intellij.ui.PlaceProvider; import com.intellij.ui.SimpleColoredText; import com.intellij.ui.SimpleTextAttributes; @@ -103,8 +105,10 @@ public final class TabInfo implements Queryable, PlaceProvider { } public TabInfo setText(String text) { - clearText(false); - append(text, getDefaultAttributes()); + if (!myText.toString().equals(text)) { + clearText(false); + append(text, getDefaultAttributes()); + } return this; } @@ -135,8 +139,10 @@ public final class TabInfo implements Queryable, PlaceProvider { public TabInfo setIcon(Icon icon) { Icon old = myIcon; - myIcon = icon; - myChangeSupport.firePropertyChange(ICON, old, icon); + if (!IconDeferrer.getInstance().equalIcons(old, icon)) { + myIcon = icon; + myChangeSupport.firePropertyChange(ICON, old, icon); + } return this; } @@ -168,6 +174,7 @@ public final class TabInfo implements Queryable, PlaceProvider { return myIcon; } + @Override public String getPlace() { return myPlace; } @@ -339,8 +346,10 @@ public final class TabInfo implements Queryable, PlaceProvider { public TabInfo setTooltipText(final String text) { String old = myTooltipText; - myTooltipText = text; - myChangeSupport.firePropertyChange(TEXT, old, myTooltipText); + if (!Comparing.equal(old, text)) { + myTooltipText = text; + myChangeSupport.firePropertyChange(TEXT, old, myTooltipText); + } return this; } @@ -350,8 +359,10 @@ public final class TabInfo implements Queryable, PlaceProvider { public TabInfo setTabColor(Color color) { Color old = myTabColor; - myTabColor = color; - myChangeSupport.firePropertyChange(TAB_COLOR, old, color); + if (!Comparing.equal(color, old)) { + myTabColor = color; + myChangeSupport.firePropertyChange(TAB_COLOR, old, color); + } return this; } @@ -364,6 +375,7 @@ public final class TabInfo implements Queryable, PlaceProvider { return this; } + @Override public void putInfo(@NotNull Map info) { if (myQueryable != null) { myQueryable.putInfo(info);