diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/Widget.java b/runelite-api/src/main/java/net/runelite/api/widgets/Widget.java index 416a3d8d66..3e6c44caa0 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/Widget.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/Widget.java @@ -78,8 +78,19 @@ public interface Widget void setSpriteId(int spriteId); + /** + * @return True if this widget or any of it's parents are hidden + */ boolean isHidden(); + /** + * @return True if this widget, regardless of it's parent's state + */ + boolean isSelfHidden(); + + /** + * Sets if this element is hidden as returned by isSelfHidden() + */ void setHidden(boolean hidden); Point getCanvasLocation(); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsConfig.java new file mode 100644 index 0000000000..e65d86586e --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsConfig.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018 Abex + * 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 net.runelite.client.config.ConfigGroup; +import net.runelite.client.config.ConfigItem; + +@ConfigGroup( + keyName = "devtools", + name = "Dev Tools", + description = "Configuration for developer tools" +) +public interface DevToolsConfig +{ + @ConfigItem( + keyName = "inspectorAlwaysOnTop", + name = "", + description = "", + hidden = true + ) + default boolean inspectorAlwaysOnTop() + { + return false; + } + + @ConfigItem( + keyName = "inspectorAlwaysOnTop", + name = "", + description = "" + ) + void inspectorAlwaysOnTop(boolean value); +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsPanel.java index f98739b42d..a1596b1837 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsPanel.java @@ -25,88 +25,46 @@ */ package net.runelite.client.plugins.devtools; - -import static net.runelite.api.widgets.WidgetInfo.TO_CHILD; -import static net.runelite.api.widgets.WidgetInfo.TO_GROUP; -import java.awt.BorderLayout; import java.awt.Color; import java.awt.GridLayout; import java.io.IOException; -import java.util.Collection; -import java.util.concurrent.ExecutionException; import javax.imageio.ImageIO; import javax.inject.Inject; import javax.swing.ImageIcon; import javax.swing.JButton; -import javax.swing.JLabel; import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTree; -import javax.swing.SwingWorker; -import javax.swing.border.EmptyBorder; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.DefaultTreeModel; import lombok.extern.slf4j.Slf4j; import net.runelite.api.Client; -import net.runelite.api.widgets.Widget; -import net.runelite.api.widgets.WidgetItem; import net.runelite.client.ui.PluginPanel; @Slf4j public class DevToolsPanel extends PluginPanel { - private JButton renderPlayersBtn = new JButton(); - private JButton renderNpcsBtn = new JButton(); - private JButton renderGroundItemsBtn = new JButton(); - private JButton renderGroundObjectsBtn = new JButton(); - private JButton renderGameObjectsBtn = new JButton(); - private JButton renderWallsBtn = new JButton(); - private JButton renderDecorBtn = new JButton(); - private JButton renderInventoryBtn = new JButton(); - private JButton renderProjectilesBtn = new JButton(); - private JPanel boundsDebugPanel = new JPanel(); - private JButton renderLocationBtn = new JButton(); - - private JLabel textLbl = new JLabel(); - private JLabel textColorLbl = new JLabel(); - private JLabel nameLbl = new JLabel(); - private JLabel modelLbl = new JLabel(); - private JLabel textureLbl = new JLabel(); - private JLabel typeLbl = new JLabel(); - private JLabel contentTypeLbl = new JLabel(); - private JButton editWidgetBtn = new JButton(); - - private JPanel borderedWrap = null; - private JPanel widgetTreeContainer = null; - private WidgetEditPanel editWidgetPanel = null; - private boolean editActive = false; - private final Client client; private final DevToolsPlugin plugin; private final SettingsTracker settingsTracker; + private WidgetInspector widgetInspector; + @Inject - public DevToolsPanel(Client client, DevToolsPlugin plugin) + public DevToolsPanel(Client client, DevToolsPlugin plugin, WidgetInspector widgetInspector) { super(); this.client = client; this.plugin = plugin; + this.widgetInspector = widgetInspector; settingsTracker = new SettingsTracker(client); - borderedWrap = new JPanel(); - borderedWrap.setLayout(new BorderLayout(0, 3)); - borderedWrap.add(createOptionsPanel(), BorderLayout.NORTH); - borderedWrap.add(createWidgetTreePanel(), BorderLayout.CENTER); - add(borderedWrap); + add(createOptionsPanel()); } private JPanel createOptionsPanel() { - JPanel container = new JPanel(); - container.setLayout(new GridLayout(7, 2, 3, 3)); + final JPanel container = new JPanel(); + container.setLayout(new GridLayout(0, 2, 3, 3)); - renderPlayersBtn = new JButton("Players"); + final JButton renderPlayersBtn = new JButton("Players"); renderPlayersBtn.addActionListener(e -> { highlightButton(renderPlayersBtn); @@ -114,7 +72,7 @@ public class DevToolsPanel extends PluginPanel }); container.add(renderPlayersBtn); - renderNpcsBtn = new JButton("NPCs"); + final JButton renderNpcsBtn = new JButton("NPCs"); renderNpcsBtn.addActionListener(e -> { highlightButton(renderNpcsBtn); @@ -122,7 +80,7 @@ public class DevToolsPanel extends PluginPanel }); container.add(renderNpcsBtn); - renderGroundItemsBtn = new JButton("Ground Items"); + final JButton renderGroundItemsBtn = new JButton("Ground Items"); renderGroundItemsBtn.addActionListener(e -> { highlightButton(renderGroundItemsBtn); @@ -130,7 +88,7 @@ public class DevToolsPanel extends PluginPanel }); container.add(renderGroundItemsBtn); - renderGroundObjectsBtn = new JButton("Ground Objects"); + final JButton renderGroundObjectsBtn = new JButton("Ground Objects"); renderGroundObjectsBtn.addActionListener(e -> { highlightButton(renderGroundObjectsBtn); @@ -138,7 +96,7 @@ public class DevToolsPanel extends PluginPanel }); container.add(renderGroundObjectsBtn); - renderGameObjectsBtn = new JButton("Game Objects"); + final JButton renderGameObjectsBtn = new JButton("Game Objects"); renderGameObjectsBtn.addActionListener(e -> { highlightButton(renderGameObjectsBtn); @@ -146,7 +104,7 @@ public class DevToolsPanel extends PluginPanel }); container.add(renderGameObjectsBtn); - renderWallsBtn = new JButton("Walls"); + final JButton renderWallsBtn = new JButton("Walls"); renderWallsBtn.addActionListener(e -> { highlightButton(renderWallsBtn); @@ -154,7 +112,7 @@ public class DevToolsPanel extends PluginPanel }); container.add(renderWallsBtn); - renderDecorBtn = new JButton("Decorations"); + final JButton renderDecorBtn = new JButton("Decorations"); renderDecorBtn.addActionListener(e -> { highlightButton(renderDecorBtn); @@ -162,7 +120,7 @@ public class DevToolsPanel extends PluginPanel }); container.add(renderDecorBtn); - renderInventoryBtn = new JButton("Inventory"); + final JButton renderInventoryBtn = new JButton("Inventory"); renderInventoryBtn.addActionListener(e -> { highlightButton(renderInventoryBtn); @@ -170,7 +128,7 @@ public class DevToolsPanel extends PluginPanel }); container.add(renderInventoryBtn); - renderProjectilesBtn = new JButton("Projectiles"); + final JButton renderProjectilesBtn = new JButton("Projectiles"); renderProjectilesBtn.addActionListener(e -> { highlightButton(renderProjectilesBtn); @@ -178,18 +136,18 @@ public class DevToolsPanel extends PluginPanel }); container.add(renderProjectilesBtn); - boundsDebugPanel = createBoundsDebugMultiButton(); + final JPanel boundsDebugPanel = createBoundsDebugMultiButton(); container.add(boundsDebugPanel); - JButton settingsSnapshotBtn = new JButton("Get Settings"); + final JButton settingsSnapshotBtn = new JButton("Get Settings"); settingsSnapshotBtn.addActionListener(settingsTracker::snapshot); container.add(settingsSnapshotBtn); - JButton settingsClearBtn = new JButton("Clear Settings"); + final JButton settingsClearBtn = new JButton("Clear Settings"); settingsClearBtn.addActionListener(settingsTracker::clear); container.add(settingsClearBtn); - renderLocationBtn = new JButton("Location"); + final JButton renderLocationBtn = new JButton("Location"); renderLocationBtn.addActionListener(e -> { highlightButton(renderLocationBtn); @@ -197,6 +155,15 @@ public class DevToolsPanel extends PluginPanel }); container.add(renderLocationBtn); + final JButton widgetInspectorBtn = new JButton("Inspector"); + widgetInspectorBtn.addActionListener(e -> + { + widgetInspector.setVisible(true); + widgetInspector.toFront(); + widgetInspector.repaint(); + }); + container.add(widgetInspectorBtn); + return container; } @@ -267,150 +234,6 @@ public class DevToolsPanel extends PluginPanel return buttonPanel; } - private void editWidget(Widget w) - { - if (editWidgetPanel == null) - { - editWidgetPanel = new WidgetEditPanel(this, w); - } - else - { - editWidgetPanel.setWidget(w); - } - - widgetTreeContainer.setVisible(false); - this.borderedWrap.remove(widgetTreeContainer); - this.borderedWrap.add(editWidgetPanel, BorderLayout.CENTER); - editWidgetPanel.validate(); - editWidgetPanel.setVisible(true); - editWidgetPanel.repaint(); - editActive = true; - } - - public void cancelEdit() - { - if (!editActive) - return; - - editWidgetPanel.setVisible(false); - this.borderedWrap.remove(editWidgetPanel); - this.borderedWrap.add(widgetTreeContainer, BorderLayout.CENTER); - widgetTreeContainer.revalidate(); - widgetTreeContainer.setVisible(true); - widgetTreeContainer.repaint(); - } - - private JPanel createWidgetTreePanel() - { - widgetTreeContainer = new JPanel(); - widgetTreeContainer.setLayout(new BorderLayout(0, 3)); - - JTree tree = new JTree(new DefaultMutableTreeNode()); - tree.setRootVisible(false); - tree.setShowsRootHandles(true); - tree.getSelectionModel().addTreeSelectionListener(e -> - { - Object selected = tree.getLastSelectedPathComponent(); - if (selected instanceof WidgetTreeNode) - { - WidgetTreeNode node = (WidgetTreeNode) selected; - Widget widget = node.getWidget(); - plugin.currentWidget = widget; - plugin.itemIndex = widget.getItemId(); - setWidgetInfo(widget); - log.debug("Set widget to {} and item index to {}", widget, widget.getItemId()); - } - else if (selected instanceof WidgetItemNode) - { - WidgetItemNode node = (WidgetItemNode) selected; - plugin.itemIndex = node.getWidgetItem().getIndex(); - log.debug("Set item index to {}", plugin.itemIndex); - } - }); - - JScrollPane scrollPane = new JScrollPane(tree); - widgetTreeContainer.add(scrollPane, BorderLayout.CENTER); - - JButton refreshWidgetsBtn = new JButton("Refresh Widgets"); - refreshWidgetsBtn.addActionListener(e -> - { - new SwingWorker() - { - @Override - protected DefaultMutableTreeNode doInBackground() throws Exception - { - return refreshWidgets(); - } - - @Override - protected void done() - { - try - { - tree.setModel(new DefaultTreeModel(get())); - } - catch (InterruptedException | ExecutionException ex) - { - throw new RuntimeException(ex); - } - } - }.execute(); - }); - - JPanel btnContainer = new JPanel(); - btnContainer.setLayout(new BorderLayout()); - btnContainer.add(refreshWidgetsBtn); - widgetTreeContainer.add(btnContainer, BorderLayout.NORTH); - - JPanel infoContainer = new JPanel(); - infoContainer.setLayout(new GridLayout(0, 1)); - - textLbl = new JLabel("Text: "); - textColorLbl = new JLabel("Text Color: "); - nameLbl = new JLabel("Name: "); - modelLbl = new JLabel("Model ID: "); - textureLbl = new JLabel("Texture ID: "); - typeLbl = new JLabel("Type: "); - contentTypeLbl = new JLabel("Content Type: "); - editWidgetBtn = new JButton("Edit"); - editWidgetBtn.addActionListener(e -> - { - editWidget(plugin.currentWidget); - }); - - infoContainer.add(textLbl); - infoContainer.add(textColorLbl); - infoContainer.add(nameLbl); - infoContainer.add(modelLbl); - infoContainer.add(textureLbl); - infoContainer.add(typeLbl); - infoContainer.add(contentTypeLbl); - infoContainer.add(editWidgetBtn); - - JScrollPane infoScrollPane = new JScrollPane(infoContainer); - infoScrollPane.setBorder(new EmptyBorder(6, 6, 6, 6)); - widgetTreeContainer.add(infoScrollPane, BorderLayout.SOUTH); - - return widgetTreeContainer; - } - - private void setWidgetInfo(Widget widget) - { - if (widget == null) - { - return; - } - - textLbl.setText("Text: " + widget.getText().trim()); - textColorLbl.setText("Text Color: " + widget.getTextColor()); - nameLbl.setText("Name: " + widget.getName().trim()); - modelLbl.setText("Model ID: " + widget.getModelId()); - textureLbl.setText("Sprite ID: " + widget.getSpriteId()); - typeLbl.setText("Type: " + widget.getType() - + " Parent " + (widget.getParentId() == -1 ? -1 : TO_GROUP(widget.getParentId()) + "." + TO_CHILD(widget.getParentId()))); - contentTypeLbl.setText("Content Type: " + widget.getContentType() + " Hidden " + widget.isHidden()); - } - private void highlightButton(JButton button) { if (button.getBackground().equals(Color.GREEN)) @@ -422,90 +245,4 @@ public class DevToolsPanel extends PluginPanel button.setBackground(Color.GREEN); } } - - private DefaultMutableTreeNode refreshWidgets() - { - Widget[] rootWidgets = client.getWidgetRoots(); - DefaultMutableTreeNode root = new DefaultMutableTreeNode(); - - plugin.currentWidget = null; - plugin.itemIndex = -1; - - for (Widget widget : rootWidgets) - { - DefaultMutableTreeNode childNode = addWidget("R", widget); - if (childNode != null) - { - root.add(childNode); - } - } - - return root; - } - - private DefaultMutableTreeNode addWidget(String type, Widget widget) - { - if (widget == null || widget.isHidden()) - { - return null; - } - - DefaultMutableTreeNode node = new WidgetTreeNode(type, widget); - - Widget[] childComponents = widget.getDynamicChildren(); - if (childComponents != null) - { - for (Widget component : childComponents) - { - DefaultMutableTreeNode childNode = addWidget("D", component); - if (childNode != null) - { - node.add(childNode); - } - } - } - - childComponents = widget.getStaticChildren(); - if (childComponents != null) - { - for (Widget component : childComponents) - { - DefaultMutableTreeNode childNode = addWidget("S", component); - if (childNode != null) - { - node.add(childNode); - } - } - } - - childComponents = widget.getNestedChildren(); - if (childComponents != null) - { - for (Widget component : childComponents) - { - DefaultMutableTreeNode childNode = addWidget("N", component); - if (childNode != null) - { - node.add(childNode); - } - } - } - - Collection items = widget.getWidgetItems(); - if (items != null) - { - for (WidgetItem item : items) - { - if (item == null) - { - continue; - } - - node.add(new WidgetItemNode(item)); - } - } - - return node; - } - } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsPlugin.java index 752ae9de83..f46f2bb90b 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/DevToolsPlugin.java @@ -24,6 +24,7 @@ */ package net.runelite.client.plugins.devtools; +import com.google.inject.Provides; import java.awt.Font; import java.awt.image.BufferedImage; import java.util.Arrays; @@ -31,6 +32,7 @@ import java.util.Collection; import javax.imageio.ImageIO; import javax.inject.Inject; import net.runelite.api.widgets.Widget; +import net.runelite.client.config.ConfigManager; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; import net.runelite.client.ui.ClientUI; @@ -70,6 +72,12 @@ public class DevToolsPlugin extends Plugin private Font font; private NavigationButton navButton; + @Provides + DevToolsConfig provideConfig(ConfigManager configManager) + { + return configManager.getConfig(DevToolsConfig.class); + } + @Override protected void startUp() throws Exception { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/NumberField.java b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/NumberField.java deleted file mode 100644 index f9bb2a2fd2..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/NumberField.java +++ /dev/null @@ -1,66 +0,0 @@ -/* -* Copyright (c) 2018, Dreyri -* 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 lombok.extern.slf4j.Slf4j; -import javax.swing.JTextField; - -@Slf4j -public class NumberField extends JTextField -{ - private int number; - - public NumberField() - { - super(); - } - - public NumberField(int number) - { - super(String.valueOf(number)); - - this.number = number; - } - - public NumberField(String text) - { - super(text); - } - - public int getNumber() - { - try - { - this.number = Integer.valueOf(super.getText()); - } - catch (NumberFormatException e) - { - log.warn("Not a number!", e); - super.setText(String.valueOf(this.number)); - } - - return this.number; - } -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/WidgetEditPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/WidgetEditPanel.java deleted file mode 100644 index a2ad226792..0000000000 --- a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/WidgetEditPanel.java +++ /dev/null @@ -1,290 +0,0 @@ -/* - * Copyright (c) 2018, Dreyri - * 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 java.awt.Color; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JTextField; -import lombok.extern.slf4j.Slf4j; -import net.runelite.api.widgets.Widget; - -@Slf4j -public class WidgetEditPanel extends JPanel -{ - private Widget widget; - - private JLabel nameLbl = new JLabel(); - private JLabel textLbl = new JLabel(); - private JLabel typeLbl = new JLabel(); - private JLabel contentTypeLbl = new JLabel(); - private JLabel textColorLbl = new JLabel(); - private JLabel hiddenLbl = new JLabel(); - private JLabel spriteLbl = new JLabel(); - private JLabel relativeXLbl = new JLabel(); - private JLabel relativeYLbl = new JLabel(); - private JLabel widthLbl = new JLabel(); - private JLabel heightLbl = new JLabel(); - - private JTextField nameTF = new JTextField(); - private JTextField textTF = new JTextField(); - private NumberField typeTF = new NumberField(); - private NumberField contentTypeTF = new NumberField(); - private NumberField textColorTF = new NumberField(); - private JCheckBox hiddenCB = new JCheckBox(); - private NumberField spriteTF = new NumberField(); - private NumberField relativeXTF = new NumberField(); - private NumberField relativeYTF = new NumberField(); - private NumberField widthTF = new NumberField(); - private NumberField heightTF = new NumberField(); - - private JButton cancelBtn = new JButton(); - private JButton applyBtn = new JButton(); - - private final DevToolsPanel owner; - - public WidgetEditPanel(DevToolsPanel panel, Widget w) - { - this.owner = panel; - this.widget = w; - - init(); - } - - private void init() - { - createInputElements(); - - this.setLayout(new GridBagLayout()); - - errorCheck(); - createInterfaceElements(); - setupInterface(); - } - - private void errorCheck() - { - if (widget == null) - { - JLabel errorLabel = new JLabel("Widget could not be loaded!"); - errorLabel.setForeground(Color.RED); - this.add(errorLabel); - } - } - - public void setWidget(Widget w) - { - this.removeAll(); - this.widget = w; - init(); - - } - - private void createInputElements() - { - if (widget == null) - return; - - nameTF = new JTextField(widget.getName()); - textTF = new JTextField(widget.getText()); - typeTF = new NumberField(widget.getType()); - contentTypeTF = new NumberField(widget.getContentType()); - textColorTF = new NumberField(widget.getTextColor()); - hiddenCB = new JCheckBox(); - spriteTF = new NumberField(widget.getSpriteId()); - relativeXTF = new NumberField(widget.getRelativeX()); - relativeYTF = new NumberField(widget.getRelativeY()); - widthTF = new NumberField(widget.getWidth()); - heightTF = new NumberField(widget.getHeight()); - - hiddenCB.setSelected(widget.isHidden()); - } - - private void createInterfaceElements() - { - nameLbl = new JLabel("Name"); - textLbl = new JLabel("Text"); - typeLbl = new JLabel("Type"); - contentTypeLbl = new JLabel("Content type"); - textColorLbl = new JLabel(String.valueOf("Text color")); - hiddenLbl = new JLabel("Hidden"); - spriteLbl = new JLabel("Sprite"); - relativeXLbl = new JLabel("Relative X"); - relativeYLbl = new JLabel("Relative Y"); - widthLbl = new JLabel("Width"); - heightLbl = new JLabel("Height"); - - cancelBtn = new JButton("Cancel"); - applyBtn = new JButton("Apply"); - - this.cancelBtn.addActionListener(e -> - { - owner.cancelEdit(); - }); - - this.applyBtn.addActionListener(e -> - { - applyChanges(); - }); - } - - /** - * only change when actual change happened to prevent sending too many change events - */ - private void applyChanges() - { - boolean hidden = hiddenCB.isSelected(); - String name = nameTF.getText(); - String text = textTF.getText(); - int type = typeTF.getNumber(); - int contentType = contentTypeTF.getNumber(); - int textColor = textColorTF.getNumber(); - int sprite = spriteTF.getNumber(); - int relativeX = relativeXTF.getNumber(); - int relativeY = relativeYTF.getNumber(); - int width = widthTF.getNumber(); - int height = heightTF.getNumber(); - - if (hidden != widget.isHidden()) - widget.setHidden(hidden); - - if (!name.equals(widget.getName())) - widget.setName(name); - - if (!text.equals(widget.getText())) - widget.setText(text); - - if (type != widget.getType()) - widget.setType(type); - - if (contentType != widget.getContentType()) - widget.setContentType(contentType); - - if (textColor != widget.getTextColor()) - widget.setTextColor(textColor); - - if (sprite != widget.getSpriteId()) - widget.setSpriteId(sprite); - - if (relativeX != widget.getRelativeX()) - widget.setRelativeX(relativeX); - - if (relativeY != widget.getRelativeY()) - widget.setRelativeY(relativeY); - - if (width != widget.getWidth()) - widget.setWidth(width); - - if (height != widget.getHeight()) - widget.setHeight(height); - } - - private void setupInterface() - { - GridBagConstraints constraints = new GridBagConstraints(); - - constraints.fill = GridBagConstraints.HORIZONTAL; - constraints.weightx = 0.5; - - constraints.gridwidth = 1; - constraints.gridx = 0; - constraints.gridy = 2; - this.add(nameLbl, constraints); - - constraints.gridx = 1; - this.add(nameTF, constraints); - - constraints.gridx = 0; - constraints.gridy = 3; - this.add(textLbl, constraints); - constraints.gridx = 1; - this.add(textTF, constraints); - - constraints.gridx = 0; - constraints.gridy = 4; - this.add(typeLbl, constraints); - constraints.gridx = 1; - this.add(typeTF, constraints); - - constraints.gridx = 0; - constraints.gridy = 5; - this.add(contentTypeLbl, constraints); - constraints.gridx = 1; - this.add(contentTypeTF, constraints); - - constraints.gridx = 0; - constraints.gridy = 6; - this.add(textColorLbl, constraints); - constraints.gridx = 1; - this.add(textColorTF, constraints); - - constraints.gridx = 0; - constraints.gridy = 7; - this.add(hiddenLbl, constraints); - constraints.gridx = 1; - this.add(hiddenCB, constraints); - - constraints.gridx = 0; - constraints.gridy = 8; - this.add(spriteLbl, constraints); - constraints.gridx = 1; - this.add(spriteTF, constraints); - - constraints.gridx = 0; - constraints.gridy = 9; - this.add(relativeXLbl, constraints); - constraints.gridx = 1; - this.add(relativeXTF, constraints); - - constraints.gridx = 0; - constraints.gridy = 10; - this.add(relativeYLbl, constraints); - constraints.gridx = 1; - this.add(relativeYTF, constraints); - - constraints.gridx = 0; - constraints.gridy = 11; - this.add(widthLbl, constraints); - constraints.gridx = 1; - this.add(widthTF, constraints); - - constraints.gridx = 0; - constraints.gridy = 12; - this.add(heightLbl, constraints); - constraints.gridx = 1; - this.add(heightTF, constraints); - - constraints.gridx = 0; - constraints.gridy = 13; - this.add(cancelBtn, constraints); - - constraints.gridx = 1; - this.add(applyBtn, constraints); - } -} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/WidgetField.java b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/WidgetField.java new file mode 100644 index 0000000000..a4b21cb94d --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/WidgetField.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2018 Abex + * 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 java.util.function.BiConsumer; +import java.util.function.Function; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.widgets.Widget; +import org.slf4j.helpers.MessageFormatter; + +@Slf4j +public class WidgetField +{ + @Getter + private final String name; + + private final Function getter; + + private final BiConsumer setter; + + private final Class type; + + WidgetField(String name, Function getter) + { + this(name, getter, null, null); + } + + WidgetField(String name, Function getter, BiConsumer setter, Class type) + { + this.name = name; + this.getter = getter; + this.setter = setter; + this.type = type; + } + + Object getValue(Widget widget) + { + Object value = getter.apply(widget); + // These types are handled by the JTable automatically + if (value instanceof Boolean || value instanceof Number || value instanceof String) + { + return value; + } + return MessageFormatter.format("{}", value).getMessage(); + } + + void setValue(Widget widget, Object inValue) + { + Object value = null; + if ("null".equals(inValue)) + { + value = null; + } + if (type.isAssignableFrom(inValue.getClass())) + { + value = inValue; + } + else if (type == Boolean.class) + { + value = Boolean.valueOf((String) inValue); + } + else if (type == Integer.class) + { + value = Integer.valueOf((String) inValue); + } + else + { + log.warn("Type {} is not supported for editing", type); + } + setter.accept(widget, (T) value); + } + + boolean isSettable() + { + return setter != null; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/WidgetInfoTableModel.java b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/WidgetInfoTableModel.java new file mode 100644 index 0000000000..0c26c71dcf --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/WidgetInfoTableModel.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2018 Abex + * 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 java.util.ArrayList; +import java.util.List; +import javax.swing.table.AbstractTableModel; +import net.runelite.api.widgets.Widget; + +public class WidgetInfoTableModel extends AbstractTableModel +{ + private static final int COL_FIELD = 0; + private static final int COL_VALUE = 1; + + private static final List fields = populateWidgetFields(); + + private Widget widget = null; + + public void setWidget(Widget w) + { + this.widget = w; + fireTableStructureChanged(); + } + + @Override + public String getColumnName(int col) + { + switch (col) + { + case COL_FIELD: + return "Field"; + case COL_VALUE: + return "Value"; + default: + return null; + } + } + + @Override + public int getColumnCount() + { + return 2; + } + + @Override + public int getRowCount() + { + if (widget == null) + { + return 0; + } + return fields.size(); + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) + { + WidgetField field = fields.get(rowIndex); + switch (columnIndex) + { + case COL_FIELD: + return field.getName(); + case COL_VALUE: + return field.getValue(widget); + default: + return null; + } + } + + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) + { + if (columnIndex == COL_VALUE) + { + WidgetField field = fields.get(rowIndex); + return field.isSettable(); + } + return false; + } + + @Override + public void setValueAt(Object value, int rowIndex, int columnIndex) + { + WidgetField field = fields.get(rowIndex); + field.setValue(widget, value); + } + + private static List populateWidgetFields() + { + List out = new ArrayList<>(); + + out.add(new WidgetField<>("Id", Widget::getId)); + out.add(new WidgetField<>("Type", Widget::getType, Widget::setType, Integer.class)); + out.add(new WidgetField<>("ContentType", Widget::getContentType, Widget::setContentType, Integer.class)); + out.add(new WidgetField<>("ParentId", Widget::getParentId)); + out.add(new WidgetField<>("SelfHidden", Widget::isSelfHidden, Widget::setHidden, Boolean.class)); + out.add(new WidgetField<>("Hidden", Widget::isHidden)); + out.add(new WidgetField<>("Text", Widget::getText, Widget::setText, String.class)); + out.add(new WidgetField<>("TextColor", + w -> Integer.toString(w.getTextColor(), 16), + (w, str) -> w.setTextColor(Integer.parseInt(str, 16)), + String.class + )); + out.add(new WidgetField<>("Name", w -> w.getName().trim(), Widget::setName, String.class)); + out.add(new WidgetField<>("ItemId", Widget::getItemId)); + out.add(new WidgetField<>("ItemQuantity", Widget::getItemQuantity)); + out.add(new WidgetField<>("ModelId", Widget::getModelId)); + out.add(new WidgetField<>("SpriteId", Widget::getSpriteId, Widget::setSpriteId, Integer.class)); + out.add(new WidgetField<>("Width", Widget::getWidth, Widget::setWidth, Integer.class)); + out.add(new WidgetField<>("Height", Widget::getHeight, Widget::setHeight, Integer.class)); + out.add(new WidgetField<>("RelativeX", Widget::getRelativeX, Widget::setRelativeX, Integer.class)); + out.add(new WidgetField<>("RelativeY", Widget::getRelativeY, Widget::setRelativeY, Integer.class)); + out.add(new WidgetField<>("CanvasLocation", Widget::getCanvasLocation)); + out.add(new WidgetField<>("Bounds", Widget::getBounds)); + out.add(new WidgetField<>("ScrollX", Widget::getScrollX)); + out.add(new WidgetField<>("ScrollY", Widget::getScrollY)); + out.add(new WidgetField<>("OriginalX", Widget::getOriginalX)); + out.add(new WidgetField<>("OriginalY", Widget::getOriginalY)); + out.add(new WidgetField<>("PaddingX", Widget::getPaddingX)); + out.add(new WidgetField<>("PaddingY", Widget::getPaddingY)); + + return out; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/WidgetInspector.java b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/WidgetInspector.java new file mode 100644 index 0000000000..0a40bdf473 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/WidgetInspector.java @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2018 Abex + * Copyright (c) 2017, Kronos + * Copyright (c) 2017, 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.plugins.devtools; + +import com.google.common.eventbus.EventBus; +import com.google.common.eventbus.Subscribe; +import com.google.inject.Inject; +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.util.Collection; +import java.util.concurrent.ExecutionException; +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; +import javax.swing.JTable; +import javax.swing.JTree; +import javax.swing.SwingWorker; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeModel; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import net.runelite.api.events.ConfigChanged; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetItem; +import net.runelite.client.ui.ClientUI; + +@Slf4j +class WidgetInspector extends JFrame +{ + private final Client client; + private final DevToolsPlugin plugin; + private final DevToolsConfig config; + + private final JTree widgetTree; + private final WidgetInfoTableModel infoTableModel; + private final JCheckBox alwaysOnTop; + + @Inject + WidgetInspector(DevToolsPlugin plugin, Client client, WidgetInfoTableModel infoTableModel, DevToolsConfig config, EventBus eventBus) + { + this.plugin = plugin; + this.client = client; + this.infoTableModel = infoTableModel; + this.config = config; + + eventBus.register(this); + + setTitle("RuneLite Widget Inspector"); + setIconImage(ClientUI.ICON); + + // Reset highlight on close + addWindowListener(new WindowAdapter() + { + @Override + public void windowClosing(WindowEvent e) + { + plugin.currentWidget = null; + plugin.itemIndex = -1; + } + }); + + setLayout(new BorderLayout()); + + widgetTree = new JTree(new DefaultMutableTreeNode()); + widgetTree.setRootVisible(false); + widgetTree.setShowsRootHandles(true); + widgetTree.getSelectionModel().addTreeSelectionListener(e -> + { + Object selected = widgetTree.getLastSelectedPathComponent(); + if (selected instanceof WidgetTreeNode) + { + WidgetTreeNode node = (WidgetTreeNode) selected; + Widget widget = node.getWidget(); + plugin.currentWidget = widget; + plugin.itemIndex = widget.getItemId(); + refreshInfo(); + log.debug("Set widget to {} and item index to {}", widget, widget.getItemId()); + } + else if (selected instanceof WidgetItemNode) + { + WidgetItemNode node = (WidgetItemNode) selected; + plugin.itemIndex = node.getWidgetItem().getIndex(); + log.debug("Set item index to {}", plugin.itemIndex); + } + }); + + final JScrollPane treeScrollPane = new JScrollPane(widgetTree); + treeScrollPane.setPreferredSize(new Dimension(200, 400)); + + + final JTable widgetInfo = new JTable(infoTableModel); + + final JScrollPane infoScrollPane = new JScrollPane(widgetInfo); + infoScrollPane.setPreferredSize(new Dimension(400, 400)); + + + final JPanel bottomPanel = new JPanel(); + add(bottomPanel, BorderLayout.SOUTH); + + final JButton refreshWidgetsBtn = new JButton("Refresh"); + refreshWidgetsBtn.addActionListener(e -> refreshWidgets()); + bottomPanel.add(refreshWidgetsBtn); + + alwaysOnTop = new JCheckBox("Always on top"); + alwaysOnTop.addItemListener(ev -> config.inspectorAlwaysOnTop(alwaysOnTop.isSelected())); + onConfigChanged(null); + bottomPanel.add(alwaysOnTop); + + + final JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, treeScrollPane, infoScrollPane); + add(split, BorderLayout.CENTER); + + pack(); + } + + @Subscribe + private void onConfigChanged(ConfigChanged ev) + { + boolean onTop = config.inspectorAlwaysOnTop(); + setAlwaysOnTop(onTop); + alwaysOnTop.setSelected(onTop); + } + + private void refreshWidgets() + { + new SwingWorker() + { + @Override + protected DefaultMutableTreeNode doInBackground() throws Exception + { + Widget[] rootWidgets = client.getWidgetRoots(); + DefaultMutableTreeNode root = new DefaultMutableTreeNode(); + + plugin.currentWidget = null; + plugin.itemIndex = -1; + + for (Widget widget : rootWidgets) + { + DefaultMutableTreeNode childNode = addWidget("R", widget); + if (childNode != null) + { + root.add(childNode); + } + } + + return root; + } + + @Override + protected void done() + { + try + { + plugin.currentWidget = null; + plugin.itemIndex = -1; + refreshInfo(); + widgetTree.setModel(new DefaultTreeModel(get())); + } + catch (InterruptedException | ExecutionException ex) + { + throw new RuntimeException(ex); + } + } + }.execute(); + } + + private DefaultMutableTreeNode addWidget(String type, Widget widget) + { + if (widget == null || widget.isHidden()) + { + return null; + } + + DefaultMutableTreeNode node = new WidgetTreeNode(type, widget); + + Widget[] childComponents = widget.getDynamicChildren(); + if (childComponents != null) + { + for (Widget component : childComponents) + { + DefaultMutableTreeNode childNode = addWidget("D", component); + if (childNode != null) + { + node.add(childNode); + } + } + } + + childComponents = widget.getStaticChildren(); + if (childComponents != null) + { + for (Widget component : childComponents) + { + DefaultMutableTreeNode childNode = addWidget("S", component); + if (childNode != null) + { + node.add(childNode); + } + } + } + + childComponents = widget.getNestedChildren(); + if (childComponents != null) + { + for (Widget component : childComponents) + { + DefaultMutableTreeNode childNode = addWidget("N", component); + if (childNode != null) + { + node.add(childNode); + } + } + } + + Collection items = widget.getWidgetItems(); + if (items != null) + { + for (WidgetItem item : items) + { + if (item == null) + { + continue; + } + + node.add(new WidgetItemNode(item)); + } + } + + return node; + } + + private void refreshInfo() + { + infoTableModel.setWidget(plugin.currentWidget); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java b/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java index 2b9f4a4681..64b1ded59a 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java @@ -75,7 +75,7 @@ import org.pushingpixels.substance.internal.utils.SubstanceTitlePaneUtilities; public class ClientUI extends JFrame { private static final int PANEL_EXPANDED_WIDTH = PluginPanel.PANEL_WIDTH + PluginPanel.SCROLLBAR_WIDTH; - private static final BufferedImage ICON; + public static final BufferedImage ICON; @Getter private TrayIcon trayIcon; diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSWidgetMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSWidgetMixin.java index 07954d9f16..16e9ab0d1a 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSWidgetMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSWidgetMixin.java @@ -143,7 +143,7 @@ public abstract class RSWidgetMixin implements RSWidget return true; } - return isRSHidden(); + return isSelfHidden(); } @Inject diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSWidget.java b/runescape-api/src/main/java/net/runelite/rs/api/RSWidget.java index cbf14f0aa9..370931a397 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSWidget.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSWidget.java @@ -118,7 +118,8 @@ public interface RSWidget extends Widget void setHeight(int height); @Import("isHidden") - boolean isRSHidden(); + @Override + boolean isSelfHidden(); @Import("isHidden") void setHidden(boolean hidden);