diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBox.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBox.java index 777bb9d634..fab945c11b 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBox.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBox.java @@ -26,7 +26,6 @@ package net.runelite.client.ui.overlay.infobox; import java.awt.Color; import java.awt.image.BufferedImage; -import javax.annotation.Nonnull; import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; @@ -34,7 +33,6 @@ import net.runelite.client.plugins.Plugin; public abstract class InfoBox { - @Nonnull @Getter(AccessLevel.PACKAGE) private final Plugin plugin; @@ -54,7 +52,7 @@ public abstract class InfoBox @Setter private String tooltip; - public InfoBox(BufferedImage image, @Nonnull Plugin plugin) + public InfoBox(BufferedImage image, Plugin plugin) { this.plugin = plugin; setImage(image); diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxManager.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxManager.java index 764a141952..540eae42c6 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxManager.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxManager.java @@ -27,7 +27,9 @@ package net.runelite.client.ui.overlay.infobox; import com.google.common.collect.ComparisonChain; import java.awt.Graphics; import java.awt.image.BufferedImage; +import java.util.ArrayList; import java.util.Collections; +import java.util.Iterator; import java.util.List; import java.util.Objects; import java.util.concurrent.CopyOnWriteArrayList; @@ -44,7 +46,7 @@ import net.runelite.client.util.AsyncBufferedImage; @Slf4j public class InfoBoxManager { - private final List infoBoxes = new CopyOnWriteArrayList<>(); + private final List infoBoxes = new ArrayList<>(); private final RuneLiteConfig runeLiteConfig; @Inject @@ -69,19 +71,8 @@ public class InfoBoxManager log.debug("Adding InfoBox {}", infoBox); updateInfoBoxImage(infoBox); - - synchronized (this) - { - int idx = Collections.binarySearch(infoBoxes, infoBox, (b1, b2) -> ComparisonChain - .start() - .compare(b1.getPriority(), b2.getPriority()) - .compare(b1.getPlugin().getName(), b2.getPlugin().getName()) - .result()); - if (idx < 0) - { - infoBoxes.add(-idx - 1, infoBox); - } - } + infoBoxes.add(infoBox); + refreshInfoBoxes(); BufferedImage image = infoBox.getImage(); @@ -92,19 +83,21 @@ public class InfoBoxManager } } - public synchronized void removeInfoBox(InfoBox infoBox) + public void removeInfoBox(InfoBox infoBox) { if (infoBoxes.remove(infoBox)) { log.debug("Removed InfoBox {}", infoBox); + refreshInfoBoxes(); } } - public synchronized void removeIf(Predicate filter) + public void removeIf(Predicate filter) { if (infoBoxes.removeIf(filter)) { log.debug("Removed InfoBoxes for filter {}", filter); + refreshInfoBoxes(); } } @@ -113,9 +106,25 @@ public class InfoBoxManager return Collections.unmodifiableList(infoBoxes); } - public synchronized void cull() + public void cull() { - infoBoxes.removeIf(InfoBox::cull); + boolean culled = false; + for (Iterator it = infoBoxes.iterator(); it.hasNext();) + { + InfoBox box = it.next(); + + if (box.cull()) + { + log.debug("Culling InfoBox {}", box); + it.remove(); + culled = true; + } + } + + if (culled) + { + refreshInfoBoxes(); + } } public void updateInfoBoxImage(final InfoBox infoBox) @@ -154,4 +163,13 @@ public class InfoBoxManager infoBox.setScaledImage(resultImage); } + + private void refreshInfoBoxes() + { + infoBoxes.sort((b1, b2) -> ComparisonChain + .start() + .compare(b1.getPriority(), b2.getPriority()) + .compare(b1.getPlugin().getName(), b2.getPlugin().getName()) + .result()); + } } diff --git a/runelite-client/src/test/java/net/runelite/client/ui/overlay/infobox/InfoBoxManagerTest.java b/runelite-client/src/test/java/net/runelite/client/ui/overlay/infobox/InfoBoxManagerTest.java index a69283f0bc..e69de29bb2 100644 --- a/runelite-client/src/test/java/net/runelite/client/ui/overlay/infobox/InfoBoxManagerTest.java +++ b/runelite-client/src/test/java/net/runelite/client/ui/overlay/infobox/InfoBoxManagerTest.java @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2020, Adam - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package net.runelite.client.ui.overlay.infobox; - -import com.google.inject.Guice; -import com.google.inject.testing.fieldbinder.Bind; -import com.google.inject.testing.fieldbinder.BoundFieldModule; -import java.awt.Color; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; -import javax.inject.Inject; -import net.runelite.client.config.OpenOSRSConfig; -import net.runelite.client.config.RuneLiteConfig; -import net.runelite.client.plugins.Plugin; -import static org.junit.Assert.assertEquals; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import static org.mockito.Mockito.mock; -import org.mockito.junit.MockitoJUnitRunner; - -@RunWith(MockitoJUnitRunner.class) -public class InfoBoxManagerTest -{ - @Inject - private InfoBoxManager infoBoxManager; - - @Mock - @Bind - private RuneLiteConfig runeLiteConfig; - - @Mock - @Bind - private OpenOSRSConfig openOSRSConfig; - - @Before - public void before() - { - Guice.createInjector(BoundFieldModule.of(this)).injectMembers(this); - } - - private static class TestInfobox extends InfoBox - { - public TestInfobox(InfoBoxPriority infoBoxPriority) - { - super(null, mock(Plugin.class)); - setPriority(infoBoxPriority); - } - - @Override - public String getText() - { - return null; - } - - @Override - public Color getTextColor() - { - return null; - } - } - - @Test - public void testSorting() - { - infoBoxManager.addInfoBox(new TestInfobox(InfoBoxPriority.LOW)); - infoBoxManager.addInfoBox(new TestInfobox(InfoBoxPriority.HIGH)); - infoBoxManager.addInfoBox(new TestInfobox(InfoBoxPriority.MED)); - - List order = infoBoxManager.getInfoBoxes().stream().map(InfoBox::getPriority).collect(Collectors.toList()); - assertEquals(Arrays.asList(InfoBoxPriority.HIGH, InfoBoxPriority.MED, InfoBoxPriority.LOW), order); - } -} \ No newline at end of file