Merge pull request #10565 from Trevor159/script-events
Add script fired events and add script inspector devtool
This commit is contained in:
@@ -29,6 +29,16 @@ package net.runelite.api;
|
||||
*/
|
||||
public class Opcodes
|
||||
{
|
||||
/**
|
||||
* opcode used to return from scripts.
|
||||
*/
|
||||
public static final int RETURN = 21;
|
||||
|
||||
/**
|
||||
* opcode used to invoke scripts.
|
||||
*/
|
||||
public static final int INVOKE = 40;
|
||||
|
||||
/**
|
||||
* RuneLite execution opcode used to inject scripts.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Trevor <https://github.com/Trevor159>
|
||||
* 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.api.events;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
/**
|
||||
* An event that is fired after the designated script is ran
|
||||
*/
|
||||
@Value
|
||||
public class ScriptPostFired
|
||||
{
|
||||
/**
|
||||
* The script id of the invoked script
|
||||
*/
|
||||
private final int scriptId;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Trevor <https://github.com/Trevor159>
|
||||
* 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.api.events;
|
||||
|
||||
import lombok.Data;
|
||||
import net.runelite.api.ScriptEvent;
|
||||
|
||||
/**
|
||||
* An event that is fired before the designated script is ran
|
||||
*/
|
||||
@Data
|
||||
public class ScriptPreFired
|
||||
{
|
||||
/**
|
||||
* The script id of the invoked script
|
||||
*/
|
||||
private final int scriptId;
|
||||
|
||||
/**
|
||||
* The input of the script invoke, this will be null unless it is the root script
|
||||
*/
|
||||
private ScriptEvent scriptEvent;
|
||||
}
|
||||
@@ -43,15 +43,23 @@ class DevToolsPanel extends PluginPanel
|
||||
|
||||
private final WidgetInspector widgetInspector;
|
||||
private final VarInspector varInspector;
|
||||
private final ScriptInspector scriptInspector;
|
||||
|
||||
@Inject
|
||||
private DevToolsPanel(Client client, DevToolsPlugin plugin, WidgetInspector widgetInspector, VarInspector varInspector, Notifier notifier)
|
||||
private DevToolsPanel(
|
||||
Client client,
|
||||
DevToolsPlugin plugin,
|
||||
WidgetInspector widgetInspector,
|
||||
VarInspector varInspector,
|
||||
ScriptInspector scriptInspector,
|
||||
Notifier notifier)
|
||||
{
|
||||
super();
|
||||
this.client = client;
|
||||
this.plugin = plugin;
|
||||
this.widgetInspector = widgetInspector;
|
||||
this.varInspector = varInspector;
|
||||
this.scriptInspector = scriptInspector;
|
||||
this.notifier = notifier;
|
||||
|
||||
setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||
@@ -133,6 +141,19 @@ class DevToolsPanel extends PluginPanel
|
||||
});
|
||||
container.add(notificationBtn);
|
||||
|
||||
container.add(plugin.getScriptInspector());
|
||||
plugin.getScriptInspector().addActionListener((ev) ->
|
||||
{
|
||||
if (plugin.getScriptInspector().isActive())
|
||||
{
|
||||
scriptInspector.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
scriptInspector.open();
|
||||
}
|
||||
});
|
||||
|
||||
return container;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,6 +129,7 @@ public class DevToolsPlugin extends Plugin
|
||||
private DevToolsButton widgetInspector;
|
||||
private DevToolsButton varInspector;
|
||||
private DevToolsButton soundEffects;
|
||||
private DevToolsButton scriptInspector;
|
||||
private NavigationButton navButton;
|
||||
|
||||
@Provides
|
||||
@@ -170,6 +171,7 @@ public class DevToolsPlugin extends Plugin
|
||||
widgetInspector = new DevToolsButton("Widget Inspector");
|
||||
varInspector = new DevToolsButton("Var Inspector");
|
||||
soundEffects = new DevToolsButton("Sound Effects");
|
||||
scriptInspector = new DevToolsButton("Script Inspector");
|
||||
|
||||
overlayManager.add(overlay);
|
||||
overlayManager.add(locationOverlay);
|
||||
|
||||
@@ -0,0 +1,494 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Trevor <https://github.com/Trevor159>
|
||||
* 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.plugins.devtools;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Component;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.FlowLayout;
|
||||
import java.awt.event.AdjustmentEvent;
|
||||
import java.awt.event.AdjustmentListener;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import javax.inject.Inject;
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFormattedTextField;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollBar;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSpinner;
|
||||
import javax.swing.JTree;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.border.CompoundBorder;
|
||||
import javax.swing.tree.DefaultMutableTreeNode;
|
||||
import javax.swing.tree.DefaultTreeModel;
|
||||
import javax.swing.tree.TreePath;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.runelite.api.Client;
|
||||
import net.runelite.api.events.ScriptPostFired;
|
||||
import net.runelite.api.events.ScriptPreFired;
|
||||
import net.runelite.api.widgets.Widget;
|
||||
import net.runelite.api.widgets.WidgetInfo;
|
||||
import static net.runelite.api.widgets.WidgetInfo.TO_CHILD;
|
||||
import static net.runelite.api.widgets.WidgetInfo.TO_GROUP;
|
||||
import net.runelite.client.config.ConfigManager;
|
||||
import net.runelite.client.eventbus.EventBus;
|
||||
import net.runelite.client.eventbus.Subscribe;
|
||||
import net.runelite.client.ui.ClientUI;
|
||||
import net.runelite.client.ui.ColorScheme;
|
||||
import net.runelite.client.ui.DynamicGridLayout;
|
||||
import net.runelite.client.ui.FontManager;
|
||||
import net.runelite.client.util.Text;
|
||||
|
||||
@Slf4j
|
||||
public class ScriptInspector extends JFrame
|
||||
{
|
||||
// These scripts are the only ones that fire every client tick regardless of location.
|
||||
private final static String DEFAULT_BLACKLIST = "3174,1004";
|
||||
private final static int MAX_LOG_ENTRIES = 10000;
|
||||
|
||||
private final Client client;
|
||||
private final EventBus eventBus;
|
||||
private final ConfigManager configManager;
|
||||
|
||||
private final JPanel tracker = new JPanel();
|
||||
private ScriptTreeNode currentNode;
|
||||
private int lastTick;
|
||||
private Set<Integer> blacklist;
|
||||
private Set<Integer> highlights;
|
||||
private JList jList;
|
||||
private DefaultListModel listModel;
|
||||
private ListState state = ListState.BLACKLIST;
|
||||
|
||||
private enum ListState
|
||||
{
|
||||
BLACKLIST,
|
||||
HIGHLIGHT
|
||||
}
|
||||
|
||||
@Data
|
||||
private class ScriptTreeNode extends DefaultMutableTreeNode
|
||||
{
|
||||
private final int scriptId;
|
||||
private Widget source;
|
||||
private int duplicateNumber = 1;
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
String output = Integer.toString(scriptId);
|
||||
|
||||
if (duplicateNumber != 1)
|
||||
{
|
||||
output += " (" + duplicateNumber + ")";
|
||||
}
|
||||
|
||||
if (source != null)
|
||||
{
|
||||
int id = source.getId();
|
||||
output += " - " + TO_GROUP(id) + "." + TO_CHILD(id);
|
||||
|
||||
if (source.getIndex() != -1)
|
||||
{
|
||||
output += "[" + source.getIndex() + "]";
|
||||
}
|
||||
|
||||
WidgetInfo info = WidgetInspector.getWidgetInfo(id);
|
||||
if (info != null)
|
||||
{
|
||||
output += " " + info.name();
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
@Inject
|
||||
ScriptInspector(Client client, EventBus eventBus, DevToolsPlugin plugin, ConfigManager configManager)
|
||||
{
|
||||
this.eventBus = eventBus;
|
||||
this.client = client;
|
||||
this.configManager = configManager;
|
||||
|
||||
setTitle("RuneLite Script Inspector");
|
||||
setIconImage(ClientUI.ICON);
|
||||
|
||||
setLayout(new BorderLayout());
|
||||
|
||||
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
|
||||
addWindowListener(new WindowAdapter()
|
||||
{
|
||||
@Override
|
||||
public void windowClosing(WindowEvent e)
|
||||
{
|
||||
close();
|
||||
plugin.getScriptInspector().setActive(false);
|
||||
}
|
||||
});
|
||||
|
||||
tracker.setLayout(new DynamicGridLayout(0, 1, 0, 3));
|
||||
|
||||
final JPanel leftSide = new JPanel();
|
||||
leftSide.setLayout(new BorderLayout());
|
||||
|
||||
final JPanel trackerWrapper = new JPanel();
|
||||
trackerWrapper.setLayout(new BorderLayout());
|
||||
trackerWrapper.add(tracker, BorderLayout.NORTH);
|
||||
|
||||
final JScrollPane trackerScroller = new JScrollPane(trackerWrapper);
|
||||
trackerScroller.setPreferredSize(new Dimension(400, 400));
|
||||
|
||||
final JScrollBar vertical = trackerScroller.getVerticalScrollBar();
|
||||
vertical.addAdjustmentListener(new AdjustmentListener()
|
||||
{
|
||||
int lastMaximum = actualMax();
|
||||
|
||||
private int actualMax()
|
||||
{
|
||||
return vertical.getMaximum() - vertical.getModel().getExtent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void adjustmentValueChanged(AdjustmentEvent e)
|
||||
{
|
||||
if (vertical.getValue() >= lastMaximum)
|
||||
{
|
||||
vertical.setValue(actualMax());
|
||||
}
|
||||
lastMaximum = actualMax();
|
||||
}
|
||||
});
|
||||
|
||||
leftSide.add(trackerScroller, BorderLayout.CENTER);
|
||||
|
||||
final JPanel bottomLeftRow = new JPanel();
|
||||
final JButton clearBtn = new JButton("Clear");
|
||||
clearBtn.addActionListener(e ->
|
||||
{
|
||||
tracker.removeAll();
|
||||
tracker.revalidate();
|
||||
});
|
||||
|
||||
bottomLeftRow.add(clearBtn);
|
||||
leftSide.add(bottomLeftRow, BorderLayout.SOUTH);
|
||||
add(leftSide, BorderLayout.CENTER);
|
||||
|
||||
String blacklistConfig = configManager.getConfiguration("devtools", "blacklist");
|
||||
|
||||
if (blacklistConfig == null)
|
||||
{
|
||||
blacklistConfig = DEFAULT_BLACKLIST;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
blacklist = new HashSet<>(Lists.transform(Text.fromCSV(blacklistConfig), Integer::parseInt));
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
blacklist = new HashSet<>(Lists.transform(Text.fromCSV(DEFAULT_BLACKLIST), Integer::parseInt));
|
||||
}
|
||||
|
||||
String highlightsConfig = configManager.getConfiguration("devtools", "highlights");
|
||||
|
||||
if (highlightsConfig == null)
|
||||
{
|
||||
highlightsConfig = "";
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
highlights = new HashSet<>(Lists.transform(Text.fromCSV(highlightsConfig), Integer::parseInt));
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
blacklist = new HashSet<>();
|
||||
}
|
||||
|
||||
final JPanel rightSide = new JPanel();
|
||||
rightSide.setLayout(new BorderLayout());
|
||||
|
||||
listModel = new DefaultListModel();
|
||||
changeState(ListState.BLACKLIST);
|
||||
jList = new JList(listModel);
|
||||
jList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
JScrollPane listScrollPane = new JScrollPane(jList);
|
||||
|
||||
final JButton blacklistButton = new JButton("Blacklist");
|
||||
blacklistButton.addActionListener(e -> changeState(ListState.BLACKLIST));
|
||||
|
||||
final JButton highlightsButton = new JButton("Highlights");
|
||||
highlightsButton.addActionListener(e -> changeState(ListState.HIGHLIGHT));
|
||||
|
||||
final JPanel topLeftRow = new JPanel();
|
||||
topLeftRow.setLayout(new FlowLayout());
|
||||
topLeftRow.add(blacklistButton);
|
||||
topLeftRow.add(highlightsButton);
|
||||
|
||||
rightSide.add(topLeftRow, BorderLayout.NORTH);
|
||||
rightSide.add(listScrollPane, BorderLayout.CENTER);
|
||||
|
||||
final JSpinner jSpinner = new JSpinner();
|
||||
Component mySpinnerEditor = jSpinner.getEditor();
|
||||
JFormattedTextField textField = ((JSpinner.DefaultEditor) mySpinnerEditor).getTextField();
|
||||
textField.setColumns(5);
|
||||
|
||||
final JButton addButton = new JButton("Add");
|
||||
addButton.addActionListener(e -> addToSet(jSpinner));
|
||||
|
||||
final JButton removeButton = new JButton("Remove");
|
||||
removeButton.addActionListener(e -> removeSelectedFromSet());
|
||||
|
||||
final JPanel bottomButtonRow = new JPanel();
|
||||
bottomButtonRow.setLayout(new FlowLayout());
|
||||
bottomButtonRow.add(addButton);
|
||||
bottomButtonRow.add(jSpinner);
|
||||
bottomButtonRow.add(removeButton);
|
||||
|
||||
rightSide.add(bottomButtonRow, BorderLayout.SOUTH);
|
||||
|
||||
add(rightSide, BorderLayout.EAST);
|
||||
|
||||
pack();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onScriptPreFired(ScriptPreFired event)
|
||||
{
|
||||
ScriptTreeNode newNode = new ScriptTreeNode(event.getScriptId());
|
||||
if (event.getScriptEvent() != null)
|
||||
{
|
||||
newNode.setSource(event.getScriptEvent().getSource());
|
||||
}
|
||||
|
||||
if (currentNode == null)
|
||||
{
|
||||
currentNode = newNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
int count = 0;
|
||||
Enumeration children = currentNode.children();
|
||||
if (children != null)
|
||||
{
|
||||
while (children.hasMoreElements())
|
||||
{
|
||||
ScriptTreeNode child = (ScriptTreeNode) children.nextElement();
|
||||
|
||||
if (child.getScriptId() == event.getScriptId())
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
newNode.setDuplicateNumber(count + 1);
|
||||
}
|
||||
|
||||
currentNode.add(newNode);
|
||||
currentNode = newNode;
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void onScriptPostFired(ScriptPostFired event)
|
||||
{
|
||||
if (currentNode == null || currentNode.getScriptId() != event.getScriptId())
|
||||
{
|
||||
log.warn("a script was post-fired that was never pre-fired. Script id: " + event.getScriptId());
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentNode.getParent() != null)
|
||||
{
|
||||
currentNode = (ScriptTreeNode) currentNode.getParent();
|
||||
}
|
||||
else
|
||||
{
|
||||
addScriptLog(currentNode);
|
||||
currentNode = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void open()
|
||||
{
|
||||
eventBus.register(this);
|
||||
setVisible(true);
|
||||
toFront();
|
||||
repaint();
|
||||
}
|
||||
|
||||
public void close()
|
||||
{
|
||||
configManager.setConfiguration("devtools", "highlights",
|
||||
Text.toCSV(Lists.transform(new ArrayList<>(highlights), String::valueOf)));
|
||||
configManager.setConfiguration("devtools", "blacklist",
|
||||
Text.toCSV(Lists.transform(new ArrayList<>(blacklist), String::valueOf)));
|
||||
currentNode = null;
|
||||
eventBus.unregister(this);
|
||||
setVisible(false);
|
||||
}
|
||||
|
||||
private void addScriptLog(ScriptTreeNode treeNode)
|
||||
{
|
||||
if (blacklist.contains(treeNode.getScriptId()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int tick = client.getTickCount();
|
||||
SwingUtilities.invokeLater(() ->
|
||||
{
|
||||
if (tick != lastTick)
|
||||
{
|
||||
lastTick = tick;
|
||||
JLabel header = new JLabel("Tick " + tick);
|
||||
header.setFont(FontManager.getRunescapeSmallFont());
|
||||
header.setBorder(new CompoundBorder(
|
||||
BorderFactory.createMatteBorder(0, 0, 1, 0, ColorScheme.LIGHT_GRAY_COLOR),
|
||||
BorderFactory.createEmptyBorder(3, 6, 0, 0)
|
||||
));
|
||||
tracker.add(header);
|
||||
}
|
||||
DefaultTreeModel treeModel = new DefaultTreeModel(treeNode);
|
||||
JTree tree = new JTree(treeModel);
|
||||
tree.setRootVisible(true);
|
||||
tree.setShowsRootHandles(true);
|
||||
tree.collapsePath(new TreePath(treeNode));
|
||||
|
||||
ScriptTreeNode highlightNode = findHighlightPathNode(treeNode);
|
||||
|
||||
if (highlightNode != null)
|
||||
{
|
||||
tree.setExpandsSelectedPaths(true);
|
||||
tree.setSelectionPath(new TreePath(treeModel.getPathToRoot(highlightNode)));
|
||||
}
|
||||
|
||||
tracker.add(tree);
|
||||
|
||||
// Cull very old stuff
|
||||
for (; tracker.getComponentCount() > MAX_LOG_ENTRIES; )
|
||||
{
|
||||
tracker.remove(0);
|
||||
}
|
||||
|
||||
tracker.revalidate();
|
||||
});
|
||||
}
|
||||
|
||||
private void changeState(ListState state)
|
||||
{
|
||||
this.state = state;
|
||||
refreshList();
|
||||
}
|
||||
|
||||
private void addToSet(JSpinner spinner)
|
||||
{
|
||||
int script = (Integer) spinner.getValue();
|
||||
Set<Integer> set = getSet();
|
||||
set.add(script);
|
||||
refreshList();
|
||||
spinner.setValue(0);
|
||||
}
|
||||
|
||||
private void removeSelectedFromSet()
|
||||
{
|
||||
int index = jList.getSelectedIndex();
|
||||
|
||||
if (index == -1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int script = (Integer) listModel.get(index);
|
||||
getSet().remove(script);
|
||||
refreshList();
|
||||
}
|
||||
|
||||
private void refreshList()
|
||||
{
|
||||
listModel.clear();
|
||||
Set<Integer> set = getSet();
|
||||
|
||||
for (Integer i : set)
|
||||
{
|
||||
listModel.addElement(i);
|
||||
}
|
||||
}
|
||||
|
||||
private Set<Integer> getSet()
|
||||
{
|
||||
Set<Integer> set;
|
||||
|
||||
if (state == ListState.BLACKLIST)
|
||||
{
|
||||
set = blacklist;
|
||||
}
|
||||
else
|
||||
{
|
||||
set = highlights;
|
||||
}
|
||||
|
||||
return set;
|
||||
}
|
||||
|
||||
private ScriptTreeNode findHighlightPathNode(ScriptTreeNode node)
|
||||
{
|
||||
if (highlights.contains(node.getScriptId()))
|
||||
{
|
||||
return node;
|
||||
}
|
||||
|
||||
Enumeration children = node.children();
|
||||
if (children != null)
|
||||
{
|
||||
while (children.hasMoreElements())
|
||||
{
|
||||
ScriptTreeNode child = (ScriptTreeNode) children.nextElement();
|
||||
|
||||
ScriptTreeNode find = findHighlightPathNode(child);
|
||||
|
||||
if (find != null)
|
||||
{
|
||||
return find;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user