loottracker: Optimize panel rebuild
Removing components in swing can be incredibly slow under serveral circumstances. This adds a special removeAll that can take less time in some cases
This commit is contained in:
@@ -54,6 +54,7 @@ import net.runelite.client.ui.components.PluginErrorPanel;
|
|||||||
import net.runelite.client.util.ColorUtil;
|
import net.runelite.client.util.ColorUtil;
|
||||||
import net.runelite.client.util.ImageUtil;
|
import net.runelite.client.util.ImageUtil;
|
||||||
import net.runelite.client.util.QuantityFormatter;
|
import net.runelite.client.util.QuantityFormatter;
|
||||||
|
import net.runelite.client.util.SwingUtil;
|
||||||
import net.runelite.http.api.loottracker.LootTrackerClient;
|
import net.runelite.http.api.loottracker.LootTrackerClient;
|
||||||
|
|
||||||
class LootTrackerPanel extends PluginPanel
|
class LootTrackerPanel extends PluginPanel
|
||||||
@@ -488,7 +489,7 @@ class LootTrackerPanel extends PluginPanel
|
|||||||
*/
|
*/
|
||||||
private void rebuild()
|
private void rebuild()
|
||||||
{
|
{
|
||||||
logsContainer.removeAll();
|
SwingUtil.fastRemoveAll(logsContainer);
|
||||||
boxes.clear();
|
boxes.clear();
|
||||||
|
|
||||||
if (groupLoot)
|
if (groupLoot)
|
||||||
|
|||||||
@@ -612,7 +612,7 @@ public class LootTrackerPlugin extends Plugin
|
|||||||
}
|
}
|
||||||
|
|
||||||
config.setIgnoredItems(Text.toCSV(ignoredItemSet));
|
config.setIgnoredItems(Text.toCSV(ignoredItemSet));
|
||||||
panel.updateIgnoredRecords();
|
// the config changed will update the panel
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isIgnored(String name)
|
boolean isIgnored(String name)
|
||||||
|
|||||||
@@ -26,11 +26,16 @@ package net.runelite.client.util;
|
|||||||
|
|
||||||
import java.awt.AWTException;
|
import java.awt.AWTException;
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.Container;
|
||||||
|
import java.awt.EventQueue;
|
||||||
import java.awt.Font;
|
import java.awt.Font;
|
||||||
import java.awt.Frame;
|
import java.awt.Frame;
|
||||||
import java.awt.Image;
|
import java.awt.Image;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
|
import java.awt.SecondaryLoop;
|
||||||
import java.awt.SystemTray;
|
import java.awt.SystemTray;
|
||||||
|
import java.awt.Toolkit;
|
||||||
import java.awt.TrayIcon;
|
import java.awt.TrayIcon;
|
||||||
import java.awt.event.MouseAdapter;
|
import java.awt.event.MouseAdapter;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
@@ -50,6 +55,7 @@ import javax.swing.JMenuItem;
|
|||||||
import javax.swing.JOptionPane;
|
import javax.swing.JOptionPane;
|
||||||
import javax.swing.JPopupMenu;
|
import javax.swing.JPopupMenu;
|
||||||
import javax.swing.LookAndFeel;
|
import javax.swing.LookAndFeel;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
import javax.swing.ToolTipManager;
|
import javax.swing.ToolTipManager;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.UnsupportedLookAndFeelException;
|
import javax.swing.UnsupportedLookAndFeelException;
|
||||||
@@ -293,4 +299,54 @@ public class SwingUtil
|
|||||||
{
|
{
|
||||||
button.addItemListener(l -> button.setToolTipText(button.isSelected() ? on : off));
|
button.addItemListener(l -> button.setToolTipText(button.isSelected() ? on : off));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes all of a component's children faster than calling removeAll() on it in many cases
|
||||||
|
*/
|
||||||
|
public static void fastRemoveAll(Container c)
|
||||||
|
{
|
||||||
|
// If we are not on the EDT this will deadlock, in addition to being totally unsafe
|
||||||
|
assert SwingUtilities.isEventDispatchThread();
|
||||||
|
|
||||||
|
// when a component is removed it has to be resized for some reason, but only if it's valid
|
||||||
|
// so we make sure to invalidate everything before removing it
|
||||||
|
c.invalidate();
|
||||||
|
for (int i = 0; i < c.getComponentCount(); i++)
|
||||||
|
{
|
||||||
|
Component ic = c.getComponent(i);
|
||||||
|
|
||||||
|
// removeAll and removeNotify are both recursive, so we have to recurse before them
|
||||||
|
if (ic instanceof Container)
|
||||||
|
{
|
||||||
|
fastRemoveAll((Container) ic);
|
||||||
|
}
|
||||||
|
|
||||||
|
// each removeNotify needs to remove anything from the event queue that is for that widget
|
||||||
|
// this however requires taking a lock, and is moderately slow, so we just execute all of
|
||||||
|
// those events with a secondary event loop
|
||||||
|
pumpPendingEvents();
|
||||||
|
|
||||||
|
// call removeNotify early; this is most of the work in removeAll, and generates events that
|
||||||
|
// the next secondaryLoop will pickup
|
||||||
|
ic.removeNotify();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actually remove anything
|
||||||
|
c.removeAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run any events currently in the event queue
|
||||||
|
*/
|
||||||
|
public static void pumpPendingEvents()
|
||||||
|
{
|
||||||
|
EventQueue eq = Toolkit.getDefaultToolkit().getSystemEventQueue();
|
||||||
|
|
||||||
|
if (eq.peekEvent() != null)
|
||||||
|
{
|
||||||
|
SecondaryLoop l = eq.createSecondaryLoop();
|
||||||
|
SwingUtilities.invokeLater(l::exit);
|
||||||
|
l.enter();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user