diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java b/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java index cfd5fca7c6..ebaa54e7cb 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/config/ConfigPanel.java @@ -311,6 +311,7 @@ public class ConfigPanel extends PluginPanel JLabel title = new JLabel(name); title.setForeground(Color.WHITE); title.setToolTipText("" + name + ":
" + listItem.getDescription() + ""); + PluginListItem.addLabelPopupMenu(title, PluginListItem.wikiLinkMenuItem(listItem.getName())); topPanel.add(title); for (ConfigItemDescriptor cid : cd.getItems()) @@ -704,4 +705,4 @@ public class ConfigPanel extends PluginPanel } } -} \ No newline at end of file +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginListItem.java b/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginListItem.java index 64b97a6ab8..092b4c9c92 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginListItem.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/config/PluginListItem.java @@ -26,30 +26,43 @@ package net.runelite.client.plugins.config; import java.awt.BorderLayout; import java.awt.Color; +import java.awt.Component; import java.awt.Dimension; import java.awt.GridLayout; +import java.awt.MouseInfo; +import java.awt.Point; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.List; import javax.annotation.Nullable; import javax.swing.ImageIcon; import javax.swing.JLabel; +import javax.swing.JMenuItem; import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.SwingUtilities; +import javax.swing.border.EmptyBorder; import lombok.AccessLevel; import lombok.Getter; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigDescriptor; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; +import net.runelite.client.ui.ColorScheme; import net.runelite.client.ui.PluginPanel; import net.runelite.client.ui.components.IconButton; import net.runelite.client.util.ImageUtil; +import net.runelite.client.util.LinkBrowser; import org.apache.commons.text.similarity.JaroWinklerDistance; class PluginListItem extends JPanel { private static final JaroWinklerDistance DISTANCE = new JaroWinklerDistance(); + private static final String RUNELITE_WIKI_FORMAT = "https://github.com/runelite/runelite/wiki/%s"; private static final ImageIcon CONFIG_ICON; private static final ImageIcon CONFIG_ICON_HOVER; @@ -149,6 +162,8 @@ class PluginListItem extends JPanel Collections.addAll(keywords, description.toLowerCase().split(" ")); Collections.addAll(keywords, tags); + final List popupMenuItems = new ArrayList<>(); + setLayout(new BorderLayout(3, 0)); setPreferredSize(new Dimension(PluginPanel.PANEL_WIDTH, 20)); @@ -160,7 +175,6 @@ class PluginListItem extends JPanel nameLabel.setToolTipText("" + name + ":
" + description + ""); } - add(nameLabel, BorderLayout.CENTER); pinButton.setPreferredSize(new Dimension(21, 0)); add(pinButton, BorderLayout.LINE_START); @@ -186,13 +200,21 @@ class PluginListItem extends JPanel configButton.addActionListener(e -> { configButton.setIcon(CONFIG_ICON); - configPanel.openGroupConfigPanel(PluginListItem.this, config, configDescriptor); + openGroupConfigPanel(); }); configButton.setVisible(true); configButton.setToolTipText("Edit plugin configuration"); + + final JMenuItem configMenuItem = new JMenuItem("Configure"); + configMenuItem.addActionListener(e -> openGroupConfigPanel()); + popupMenuItems.add(configMenuItem); } + popupMenuItems.add(wikiLinkMenuItem(name)); + addLabelPopupMenu(nameLabel, popupMenuItems); + add(nameLabel, BorderLayout.CENTER); + toggleButton.setPreferredSize(new Dimension(25, 0)); attachToggleButtonListener(toggleButton); buttonPanel.add(toggleButton); @@ -267,4 +289,81 @@ class PluginListItem extends JPanel } return true; } + + private void openGroupConfigPanel() + { + configPanel.openGroupConfigPanel(PluginListItem.this, config, configDescriptor); + } + + /** + * Adds a mouseover effect to change the text of the passed label to {@link ColorScheme#BRAND_ORANGE} color, and + * adds the passed menu item to a popup menu shown when the label is clicked. + * + * @param label The label to attach the mouseover and click effects to + * @param menuItem The menu item to be shown when the label is clicked + */ + static void addLabelPopupMenu(final JLabel label, final JMenuItem menuItem) + { + addLabelPopupMenu(label, Collections.singletonList(menuItem)); + } + + /** + * Adds a mouseover effect to change the text of the passed label to {@link ColorScheme#BRAND_ORANGE} color, and + * adds the passed menu items to a popup menu shown when the label is clicked. + * + * @param label The label to attach the mouseover and click effects to + * @param menuItems The menu items to be shown when the label is clicked + */ + static void addLabelPopupMenu(final JLabel label, final Collection menuItems) + { + final JPopupMenu menu = new JPopupMenu(); + menu.setBorder(new EmptyBorder(5, 5, 5, 5)); + + for (final JMenuItem menuItem : menuItems) + { + menu.add(menuItem); + } + + label.addMouseListener(new MouseAdapter() + { + private Color lastForeground; + + @Override + public void mouseClicked(MouseEvent mouseEvent) + { + Component source = (Component) mouseEvent.getSource(); + Point location = MouseInfo.getPointerInfo().getLocation(); + SwingUtilities.convertPointFromScreen(location, source); + menu.show(source, location.x, location.y); + } + + @Override + public void mouseEntered(MouseEvent mouseEvent) + { + lastForeground = label.getForeground(); + label.setForeground(ColorScheme.BRAND_ORANGE); + } + + @Override + public void mouseExited(MouseEvent mouseEvent) + { + label.setForeground(lastForeground); + } + }); + } + + /** + * Creates a menu item for linking to a wiki page which, when clicked, opens a link to the plugin's wiki page for + * the passed plugin name. + * + * @param pluginName The name of the plugin which should be linked to + * @return A {@link JMenuItem} which opens the plugin's wiki page URL in the browser when clicked + */ + static JMenuItem wikiLinkMenuItem(final String pluginName) + { + final JMenuItem menuItem = new JMenuItem("Wiki"); + final String sanitizedName = pluginName.replace(' ', '-'); + menuItem.addActionListener(e -> LinkBrowser.browse(String.format(RUNELITE_WIKI_FORMAT, sanitizedName))); + return menuItem; + } }