Merge pull request #3957 from takuyakanbr/improve-plugin-list

Improve plugin list/config panel
This commit is contained in:
Tomas Slusny
2018-07-04 01:23:46 +02:00
committed by GitHub
184 changed files with 1013 additions and 872 deletions

View File

@@ -26,11 +26,7 @@ package net.runelite.client.config;
import java.awt.Color;
@ConfigGroup(
keyName = "textrecolor",
name = "Chat Text Recolor",
description = "Configuration for chat text recoloring"
)
@ConfigGroup("textrecolor")
public interface ChatColorConfig extends Config
{
@ConfigItem(

View File

@@ -33,9 +33,11 @@ import java.lang.annotation.Target;
@Target(ElementType.TYPE)
public @interface ConfigGroup
{
String keyName();
String name();
String description();
/**
* The key name of the config group used for storing configuration within the config group.
* This should typically be a lowercased version of your plugin name, with all spaces removed.
* <p>
* For example, the {@code Grand Exchange} plugin uses the key name {@code grandexchange}.
*/
String value();
}

View File

@@ -64,7 +64,7 @@ class ConfigInvocationHandler implements InvocationHandler
if (args == null)
{
// Getting configuration item
String value = manager.getConfiguration(group.keyName(), item.keyName());
String value = manager.getConfiguration(group.value(), item.keyName());
if (value == null)
{
@@ -85,7 +85,7 @@ class ConfigInvocationHandler implements InvocationHandler
}
catch (Exception e)
{
log.warn("Unable to unmarshal {}.{} ", group.keyName(), item.keyName(), e);
log.warn("Unable to unmarshal {}.{} ", group.value(), item.keyName(), e);
if (method.isDefault())
{
return callDefaultMethod(proxy, method, null);
@@ -111,19 +111,19 @@ class ConfigInvocationHandler implements InvocationHandler
if (Objects.equal(newValue, defaultValue))
{
// Just unset if it goes back to the default
manager.unsetConfiguration(group.keyName(), item.keyName());
manager.unsetConfiguration(group.value(), item.keyName());
return null;
}
}
if (newValue == null)
{
manager.unsetConfiguration(group.keyName(), item.keyName());
manager.unsetConfiguration(group.value(), item.keyName());
}
else
{
String newValueStr = ConfigManager.objectToString(newValue);
manager.setConfiguration(group.keyName(), item.keyName(), newValueStr);
manager.setConfiguration(group.value(), item.keyName(), newValueStr);
}
return null;
}

View File

@@ -386,11 +386,11 @@ public class ConfigManager
{
if (override)
{
String current = getConfiguration(group.keyName(), item.keyName());
String current = getConfiguration(group.value(), item.keyName());
// only unset if already set
if (current != null)
{
unsetConfiguration(group.keyName(), item.keyName());
unsetConfiguration(group.value(), item.keyName());
}
}
continue;
@@ -398,7 +398,7 @@ public class ConfigManager
if (!override)
{
String current = getConfiguration(group.keyName(), item.keyName());
String current = getConfiguration(group.value(), item.keyName());
if (current != null)
{
continue; // something else is already set
@@ -416,16 +416,16 @@ public class ConfigManager
continue;
}
String current = getConfiguration(group.keyName(), item.keyName());
String current = getConfiguration(group.value(), item.keyName());
String valueString = objectToString(defaultValue);
if (Objects.equals(current, valueString))
{
continue; // already set to the default value
}
log.debug("Setting default configuration value for {}.{} to {}", group.keyName(), item.keyName(), defaultValue);
log.debug("Setting default configuration value for {}.{} to {}", group.value(), item.keyName(), defaultValue);
setConfiguration(group.keyName(), item.keyName(), valueString);
setConfiguration(group.value(), item.keyName(), valueString);
}
}

View File

@@ -27,11 +27,7 @@ package net.runelite.client.config;
import java.awt.Dimension;
import net.runelite.api.Constants;
@ConfigGroup(
keyName = "runelite",
name = "RuneLite",
description = "Configuration for RuneLite client options"
)
@ConfigGroup("runelite")
public interface RuneLiteConfig extends Config
{
@ConfigItem(

View File

@@ -37,11 +37,21 @@ public @interface PluginDescriptor
{
String name();
/**
* A short, one-line summary of the plugin.
*/
String description() default "";
/**
* A list of plugin keywords, used (together with the name) when searching for plugins.
* Each tag should not contain any spaces, and should be fully lowercase.
*/
String[] tags() default {};
boolean enabledByDefault() default true;
/**
* Whether or not plugin is hidden from configuration panel
* @return
*/
boolean hidden() default false;

View File

@@ -99,7 +99,7 @@ public class PluginManager
private final List<Plugin> plugins = new CopyOnWriteArrayList<>();
private final List<Plugin> activePlugins = new CopyOnWriteArrayList<>();
private final String runeliteGroupName = RuneLiteConfig.class
.getAnnotation(ConfigGroup.class).keyName();
.getAnnotation(ConfigGroup.class).value();
@Subscribe
public void onSessionOpen(SessionOpen event)

View File

@@ -44,6 +44,8 @@ import net.runelite.client.util.RunnableExceptionLogger;
@PluginDescriptor(
name = "Account",
description = "Sync RuneLite config settings with your Google account",
tags = {"external", "google", "integration"},
loadWhenOutdated = true
)
@Slf4j

View File

@@ -29,11 +29,7 @@ import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(
keyName = "agility",
name = "Agility",
description = "Configuration for the Agility plugin"
)
@ConfigGroup("agility")
public interface AgilityConfig extends Config
{
@ConfigItem(

View File

@@ -68,7 +68,9 @@ import net.runelite.client.ui.overlay.OverlayManager;
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
@PluginDescriptor(
name = "Agility"
name = "Agility",
description = "Show helpful information about agility courses and obstacles",
tags = {"grace", "marks", "overlay", "shortcuts", "skilling", "traps"}
)
@Slf4j
public class AgilityPlugin extends Plugin

View File

@@ -28,11 +28,7 @@ import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(
keyName = AnimationSmoothingPlugin.CONFIG_GROUP,
name = "Smooth Animations",
description = "Configuration for the smooth animations plugin"
)
@ConfigGroup(AnimationSmoothingPlugin.CONFIG_GROUP)
public interface AnimationSmoothingConfig extends Config
{

View File

@@ -35,6 +35,8 @@ import javax.inject.Inject;
@PluginDescriptor(
name = "Animation Smoothing",
description = "Show smoother player, NPC, and object animations",
tags = {"npcs", "objects", "players"},
enabledByDefault = false
)
public class AnimationSmoothingPlugin extends Plugin

View File

@@ -28,11 +28,7 @@ import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(
keyName = "antiDrag",
name = "Anti Drag",
description = "Configuration for the anti drag plugin (shift only)"
)
@ConfigGroup("antiDrag")
public interface AntiDragConfig extends Config
{
@ConfigItem(

View File

@@ -36,7 +36,11 @@ import net.runelite.client.input.KeyManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
@PluginDescriptor(name = "Shift Anti Drag")
@PluginDescriptor(
name = "Shift Anti Drag",
description = "Prevent dragging an item for a specified delay",
tags = {"antidrag", "delay", "inventory", "items"}
)
public class AntiDragPlugin extends Plugin implements KeyListener
{
private static final int DEFAULT_DELAY = 5;

View File

@@ -28,11 +28,7 @@ import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(
keyName = "attackIndicator",
name = "Attack Styles",
description = "Configuration for the attack styles plugin"
)
@ConfigGroup("attackIndicator")
public interface AttackStylesConfig extends Config
{
@ConfigItem(

View File

@@ -56,7 +56,9 @@ import static net.runelite.client.plugins.attackstyles.AttackStyle.OTHER;
import net.runelite.client.ui.overlay.OverlayManager;
@PluginDescriptor(
name = "Attack Styles"
name = "Attack Styles",
description = "Show your current attack style as an overlay",
tags = {"combat", "defence", "magic", "overlay", "ranged", "strength"}
)
@Slf4j
public class AttackStylesPlugin extends Plugin

View File

@@ -48,7 +48,9 @@ import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
@PluginDescriptor(
name = "Bank Tags"
name = "Bank Tags",
description = "Enable tagging of bank items and searching of bank tags",
tags = {"searching", "tagging"}
)
@Slf4j
public class BankTagsPlugin extends Plugin

View File

@@ -29,10 +29,7 @@ import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(
keyName = "bankvalue",
name = "Bank Value",
description = "Shows the value of your bank and/or current tab")
@ConfigGroup("bankvalue")
public interface BankValueConfig extends Config
{
@ConfigItem(

View File

@@ -36,7 +36,11 @@ import net.runelite.client.config.ConfigManager;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
@PluginDescriptor(name = "Bank Value")
@PluginDescriptor(
name = "Bank Value",
description = "Show the value of your bank and/or current tab",
tags = {"grand", "exchange", "high", "alchemy", "prices"}
)
public class BankValuePlugin extends Plugin
{
@Inject

View File

@@ -28,11 +28,7 @@ import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(
keyName = "barbarianAssault",
name = "Barbarian Assault",
description = "Configuration for the barbarian assault plugin"
)
@ConfigGroup("barbarianAssault")
public interface BarbarianAssaultConfig extends Config
{
@ConfigItem(

View File

@@ -48,7 +48,9 @@ import net.runelite.client.ui.FontManager;
import net.runelite.client.ui.overlay.OverlayManager;
@PluginDescriptor(
name = "Barbarian Assault"
name = "Barbarian Assault",
description = "Show a timer to the next call change",
tags = {"minigame", "overlay"}
)
public class BarbarianAssaultPlugin extends Plugin
{

View File

@@ -29,11 +29,7 @@ import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(
keyName = "barrows",
name = "Barrows Brothers",
description = "Configuration for the Barrows plugin"
)
@ConfigGroup("barrows")
public interface BarrowsConfig extends Config
{
@ConfigItem(

View File

@@ -66,7 +66,9 @@ import net.runelite.client.util.StackFormatter;
import net.runelite.http.api.item.ItemPrice;
@PluginDescriptor(
name = "Barrows Brothers"
name = "Barrows Brothers",
description = "Show helpful information for the Barrows minigame",
tags = {"combat", "minigame", "minimap"}
)
@Slf4j
public class BarrowsPlugin extends Plugin

View File

@@ -28,11 +28,7 @@ import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(
keyName = "blastfurnace",
name = "Blast Furnace",
description = "Configuration for the Blast furnace plugin"
)
@ConfigGroup("blastfurnace")
public interface BlastFurnaceConfig extends Config
{
@ConfigItem(

View File

@@ -42,7 +42,9 @@ import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager;
@PluginDescriptor(
name = "Blast Furnace"
name = "Blast Furnace",
description = "Show helpful information for the Blast Furnace minigame",
tags = {"minigame", "overlay", "skilling", "smithing"}
)
public class BlastFurnacePlugin extends Plugin
{

View File

@@ -44,7 +44,11 @@ import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager;
@PluginDescriptor(name = "Blast Mine")
@PluginDescriptor(
name = "Blast Mine",
description = "Show helpful information for the Blast Mine minigame",
tags = {"explode", "explosive", "mining", "minigame", "skilling"}
)
public class BlastMinePlugin extends Plugin
{
@Getter

View File

@@ -30,11 +30,7 @@ import net.runelite.client.config.ConfigItem;
import java.awt.Color;
@ConfigGroup(
keyName = "blastmine",
name = "Blast Mine",
description = "Configuration for the Blast Mine plugin"
)
@ConfigGroup("blastmine")
public interface BlastMinePluginConfig extends Config
{
@ConfigItem(

View File

@@ -28,11 +28,7 @@ import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(
keyName = "boosts",
name = "Boosts Information",
description = "Configuration for the Boosts plugin"
)
@ConfigGroup("boosts")
public interface BoostsConfig extends Config
{
@ConfigItem(

View File

@@ -49,7 +49,9 @@ import net.runelite.client.ui.overlay.OverlayManager;
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
@PluginDescriptor(
name = "Boosts Information"
name = "Boosts Information",
description = "Show combat and/or skill boost information",
tags = {"combat", "notifications", "skilling", "overlay"}
)
@Slf4j
public class BoostsPlugin extends Plugin

View File

@@ -36,7 +36,9 @@ import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
@PluginDescriptor(
name = "Boss Timers"
name = "Boss Timers",
description = "Show boss spawn timer overlays",
tags = {"combat", "pve", "overlay", "spawn"}
)
@Slf4j
public class BossTimersPlugin extends Plugin

View File

@@ -29,11 +29,7 @@ import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(
keyName = "cannon",
name = "Cannon",
description = "Configuration for the Cannon plugin"
)
@ConfigGroup("cannon")
public interface CannonConfig extends Config
{
@ConfigItem(

View File

@@ -61,7 +61,9 @@ import net.runelite.client.ui.overlay.OverlayManager;
import net.runelite.client.ui.overlay.infobox.InfoBoxManager;
@PluginDescriptor(
name = "Cannon"
name = "Cannon",
description = "Show information about cannon placement and/or amount of cannonballs",
tags = {"combat", "notifications", "ranged", "overlay"}
)
public class CannonPlugin extends Plugin
{

View File

@@ -42,7 +42,11 @@ import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager;
@PluginDescriptor(name = "Cerberus")
@PluginDescriptor(
name = "Cerberus",
description = "Show what to pray against the summoned souls",
tags = {"bosses", "combat", "ghosts", "prayer", "pve", "overlay", "souls"}
)
@Singleton
public class CerberusPlugin extends Plugin
{

View File

@@ -28,11 +28,7 @@ import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(
keyName = "chatcommands",
name = "Chat Commands",
description = "Configuration for chat commands"
)
@ConfigGroup("chatcommands")
public interface ChatCommandsConfig extends Config
{
@ConfigItem(

View File

@@ -63,7 +63,9 @@ import net.runelite.http.api.item.ItemPrice;
import net.runelite.http.api.item.SearchResult;
@PluginDescriptor(
name = "Chat Commands"
name = "Chat Commands",
description = "Enable chat commands",
tags = {"grand", "exchange", "level", "prices"}
)
@Slf4j
public class ChatCommandsPlugin extends Plugin

View File

@@ -38,7 +38,10 @@ import net.runelite.client.chat.QueuedMessage;
import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
@PluginDescriptor(name = "Chat History")
@PluginDescriptor(
name = "Chat History",
description = "Retain your chat history when logging in/out or world hopping"
)
public class ChatHistoryPlugin extends Plugin
{
private static final String WELCOME_MESSAGE = "Welcome to RuneScape.";

View File

@@ -29,11 +29,7 @@ import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(
keyName = "chatnotification",
name = "Chat Notifications",
description = "Highlights and notifies you of chat messages"
)
@ConfigGroup("chatnotification")
public interface ChatNotificationsConfig extends Config
{
@ConfigItem(

View File

@@ -50,6 +50,8 @@ import net.runelite.client.util.Text;
@PluginDescriptor(
name = "Chat Notifications",
description = "Highlight and notify you of chat messages",
tags = {"duel", "messages", "notifications", "trade", "username"},
enabledByDefault = false
)
public class ChatNotificationsPlugin extends Plugin

View File

@@ -41,7 +41,9 @@ import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.task.Schedule;
@PluginDescriptor(
name = "Clan Chat"
name = "Clan Chat",
description = "Add rank icons to users talking in clan chat",
tags = {"icons", "rank"}
)
@Slf4j
public class ClanChatPlugin extends Plugin

View File

@@ -28,11 +28,7 @@ import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(
name = "Clue Scroll",
keyName = "cluescroll",
description = "Configuration for the clue scroll plugin"
)
@ConfigGroup("cluescroll")
public interface ClueScrollConfig extends Config
{
@ConfigItem(

View File

@@ -87,7 +87,9 @@ import net.runelite.client.util.QueryRunner;
import net.runelite.client.util.Text;
@PluginDescriptor(
name = "Clue Scroll"
name = "Clue Scroll",
description = "Show answers to clue scroll riddles, anagrams, ciphers, and cryptic clues",
tags = {"arrow", "hints", "world", "map"}
)
@Slf4j
public class ClueScrollPlugin extends Plugin

View File

@@ -38,7 +38,8 @@ import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
@PluginDescriptor(
name = "Combat Level"
name = "Combat Level",
description = "Show a more accurate combat level in Combat Options panel"
)
public class CombatLevelPlugin extends Plugin
{

View File

@@ -24,12 +24,12 @@
*/
package net.runelite.client.plugins.config;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.ItemEvent;
@@ -39,10 +39,12 @@ import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Map;
import java.util.TreeMap;
import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
import java.util.stream.Collectors;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
@@ -59,6 +61,7 @@ import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JTextArea;
import javax.swing.ScrollPaneConstants;
import javax.swing.SpinnerModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingConstants;
@@ -70,6 +73,7 @@ import lombok.extern.slf4j.Slf4j;
import net.runelite.client.config.ChatColorConfig;
import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigDescriptor;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
import net.runelite.client.config.ConfigItemDescriptor;
import net.runelite.client.config.ConfigManager;
@@ -83,6 +87,7 @@ import net.runelite.client.ui.ColorScheme;
import net.runelite.client.ui.DynamicGridLayout;
import net.runelite.client.ui.PluginPanel;
import net.runelite.client.ui.components.ComboBoxListRenderer;
import net.runelite.client.ui.components.IconButton;
import net.runelite.client.ui.components.IconTextField;
import net.runelite.client.util.SwingUtil;
@@ -90,24 +95,42 @@ import net.runelite.client.util.SwingUtil;
public class ConfigPanel extends PluginPanel
{
private static final int SPINNER_FIELD_WIDTH = 6;
private static final ImageIcon CONFIG_ICON;
private static final ImageIcon CONFIG_ICON_HOVER;
private static final ImageIcon ON_SWITCHER;
private static final ImageIcon OFF_SWITCHER;
private static final int SCROLLBAR_WIDTH = 17;
private static final int OFFSET = 6;
private static final ImageIcon BACK_ICON;
private static final ImageIcon BACK_ICON_HOVER;
private static final ImageIcon SEARCH;
private static final String RUNELITE_GROUP_NAME = RuneLiteConfig.class.getAnnotation(ConfigGroup.class).value();
private static final String PINNED_PLUGINS_CONFIG_KEY = "pinnedPlugins";
private static final String RUNELITE_PLUGIN = "RuneLite";
private static final String CHAT_COLOR_PLUGIN = "Chat Color";
private static final Splitter COMMA_SPLITTER = Splitter.on(',');
private final PluginManager pluginManager;
private final ConfigManager configManager;
private final ScheduledExecutorService executorService;
private final RuneLiteConfig runeLiteConfig;
private final ChatColorConfig chatColorConfig;
private final IconTextField searchBar = new IconTextField();
private final List<PluginListItem> pluginList = new ArrayList<>();
private final JPanel topPanel;
private final JPanel mainPanel;
private final JScrollPane scrollPane;
private boolean showingPluginList = true;
private int scrollBarPosition = 0;
static
{
try
{
synchronized (ImageIO.class)
{
BufferedImage configIcon = ImageIO.read(ConfigPanel.class.getResourceAsStream("config_edit_icon.png"));
CONFIG_ICON = new ImageIcon(configIcon);
CONFIG_ICON_HOVER = new ImageIcon(SwingUtil.grayscaleOffset(configIcon, -100));
ON_SWITCHER = new ImageIcon(ImageIO.read(ConfigPanel.class.getResourceAsStream("switchers/on.png")));
OFF_SWITCHER = new ImageIcon(ImageIO.read(ConfigPanel.class.getResourceAsStream("switchers/off.png")));
BufferedImage backIcon = ImageIO.read(ConfigPanel.class.getResourceAsStream("config_back_icon.png"));
BACK_ICON = new ImageIcon(backIcon);
BACK_ICON_HOVER = new ImageIcon(SwingUtil.grayscaleOffset(backIcon, -100));
SEARCH = new ImageIcon(ImageIO.read(IconTextField.class.getResourceAsStream("search.png")));
}
}
@@ -117,19 +140,10 @@ public class ConfigPanel extends PluginPanel
}
}
private final PluginManager pluginManager;
private final ConfigManager configManager;
private final ScheduledExecutorService executorService;
private final RuneLiteConfig runeLiteConfig;
private final ChatColorConfig chatColorConfig;
private final IconTextField searchBar = new IconTextField();
private Map<String, JPanel> children = new TreeMap<>();
private int scrollBarPosition = 0;
public ConfigPanel(PluginManager pluginManager, ConfigManager configManager, ScheduledExecutorService executorService,
ConfigPanel(PluginManager pluginManager, ConfigManager configManager, ScheduledExecutorService executorService,
RuneLiteConfig runeLiteConfig, ChatColorConfig chatColorConfig)
{
super();
super(false);
this.pluginManager = pluginManager;
this.configManager = configManager;
this.executorService = executorService;
@@ -137,7 +151,7 @@ public class ConfigPanel extends PluginPanel
this.chatColorConfig = chatColorConfig;
searchBar.setIcon(SEARCH);
searchBar.setPreferredSize(new Dimension(100, 30));
searchBar.setPreferredSize(new Dimension(PluginPanel.PANEL_WIDTH - 20, 30));
searchBar.setBackground(ColorScheme.DARKER_GRAY_COLOR);
searchBar.setHoverBackgroundColor(ColorScheme.DARK_GRAY_HOVER_COLOR);
searchBar.getDocument().addDocumentListener(new DocumentListener()
@@ -161,292 +175,159 @@ public class ConfigPanel extends PluginPanel
}
});
setBorder(new EmptyBorder(10, 10, 10, 10));
setLayout(new DynamicGridLayout(0, 1, 0, 5));
setLayout(new BorderLayout());
setBackground(ColorScheme.DARK_GRAY_COLOR);
rebuildPluginList();
openConfigList();
topPanel = new JPanel();
topPanel.setBorder(new EmptyBorder(10, 10, 10, 10));
topPanel.setLayout(new BorderLayout(0, OFFSET));
add(topPanel, BorderLayout.NORTH);
mainPanel = new FixedWidthPanel();
mainPanel.setBorder(new EmptyBorder(8, 10, 10, 10));
mainPanel.setLayout(new DynamicGridLayout(0, 1, 0, 5));
mainPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
JPanel northPanel = new FixedWidthPanel();
northPanel.setLayout(new BorderLayout());
northPanel.add(mainPanel, BorderLayout.NORTH);
scrollPane = new JScrollPane(northPanel);
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
add(scrollPane, BorderLayout.CENTER);
initializePluginList();
refreshPluginList();
}
final void rebuildPluginList()
private void initializePluginList()
{
scrollBarPosition = getScrollPane().getVerticalScrollBar().getValue();
Map<String, JPanel> newChildren = new TreeMap<>();
final List<String> pinnedPlugins = getPinnedPluginNames();
// populate pluginList with all non-hidden plugins
pluginManager.getPlugins().stream()
.filter(plugin -> !plugin.getClass().getAnnotation(PluginDescriptor.class).hidden())
.sorted(Comparator.comparing(left -> left.getClass().getAnnotation(PluginDescriptor.class).name()))
.forEach(plugin ->
{
final Config pluginConfigProxy = pluginManager.getPluginConfigProxy(plugin);
final String pluginName = plugin.getClass().getAnnotation(PluginDescriptor.class).name();
final PluginDescriptor descriptor = plugin.getClass().getAnnotation(PluginDescriptor.class);
final Config config = pluginManager.getPluginConfigProxy(plugin);
final ConfigDescriptor configDescriptor = config == null ? null : configManager.getConfigDescriptor(config);
final JPanel groupPanel = buildGroupPanel();
JLabel name = new JLabel(pluginName);
name.setForeground(Color.WHITE);
groupPanel.add(name, BorderLayout.CENTER);
final JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(1, 2));
groupPanel.add(buttonPanel, BorderLayout.LINE_END);
final JLabel editConfigButton = buildConfigButton(pluginConfigProxy);
buttonPanel.add(editConfigButton);
final JLabel toggleButton = buildToggleButton(plugin);
toggleButton.setHorizontalAlignment(SwingConstants.RIGHT);
buttonPanel.add(toggleButton);
newChildren.put(pluginName, groupPanel);
final PluginListItem listItem = new PluginListItem(this, plugin, descriptor, config, configDescriptor);
listItem.setPinned(pinnedPlugins.contains(listItem.getName()));
pluginList.add(listItem);
});
addCoreConfig(newChildren, "RuneLite", runeLiteConfig);
addCoreConfig(newChildren, "Chat Color", chatColorConfig);
// add special entries for core client configurations
final PluginListItem runeLite = new PluginListItem(this, runeLiteConfig,
configManager.getConfigDescriptor(runeLiteConfig),
RUNELITE_PLUGIN, "RuneLite client settings", "client");
runeLite.setPinned(pinnedPlugins.contains(RUNELITE_PLUGIN));
pluginList.add(runeLite);
children = newChildren;
openConfigList();
final PluginListItem chatColor = new PluginListItem(this, chatColorConfig,
configManager.getConfigDescriptor(chatColorConfig),
CHAT_COLOR_PLUGIN, "Recolor chat text", "colour", "messages");
chatColor.setPinned(pinnedPlugins.contains(CHAT_COLOR_PLUGIN));
pluginList.add(chatColor);
pluginList.sort(Comparator.comparing(PluginListItem::getName));
}
private void addCoreConfig(Map<String, JPanel> newChildren, String configName, Config config)
void refreshPluginList()
{
final JPanel groupPanel = buildGroupPanel();
JLabel name = new JLabel(configName);
name.setForeground(Color.WHITE);
groupPanel.add(name, BorderLayout.CENTER);
final JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(1, 2));
groupPanel.add(buttonPanel, BorderLayout.LINE_END);
final JLabel editConfigButton = buildConfigButton(config);
buttonPanel.add(editConfigButton);
final JLabel toggleButton = buildToggleButton(null);
toggleButton.setVisible(false);
buttonPanel.add(toggleButton);
newChildren.put(configName, groupPanel);
}
private JPanel buildGroupPanel()
{
// Create base panel for the config button and enabled/disabled button
final JPanel groupPanel = new JPanel();
groupPanel.setLayout(new BorderLayout(3, 0));
groupPanel.setPreferredSize(new Dimension(PluginPanel.PANEL_WIDTH, 20));
return groupPanel;
}
private JLabel buildConfigButton(Config config)
{
// Create edit config button and disable it by default
final JLabel editConfigButton = new JLabel(CONFIG_ICON);
editConfigButton.setPreferredSize(new Dimension(25, 0));
editConfigButton.setVisible(false);
// If we have configuration proxy enable the button and add edit config listener
if (config != null)
// update enabled / disabled status of all items
pluginList.forEach(listItem ->
{
final ConfigDescriptor configDescriptor = configManager.getConfigDescriptor(config);
final boolean configEmpty = configDescriptor.getItems().stream().allMatch(item -> item.getItem().hidden());
if (!configEmpty)
final Plugin plugin = listItem.getPlugin();
if (plugin != null)
{
editConfigButton.addMouseListener(new MouseAdapter()
{
@Override
public void mousePressed(MouseEvent mouseEvent)
{
editConfigButton.setIcon(CONFIG_ICON);
openGroupConfigPanel(config, configDescriptor, configManager);
}
@Override
public void mouseEntered(MouseEvent e)
{
editConfigButton.setIcon(CONFIG_ICON_HOVER);
}
@Override
public void mouseExited(MouseEvent e)
{
editConfigButton.setIcon(CONFIG_ICON);
}
});
editConfigButton.setVisible(true);
editConfigButton.setToolTipText("Edit plugin configuration");
}
}
return editConfigButton;
}
private JLabel buildToggleButton(Plugin plugin)
{
// Create enabling/disabling button
final JLabel toggleButton = new JLabel(ON_SWITCHER);
toggleButton.setPreferredSize(new Dimension(25, 0));
if (plugin == null)
{
toggleButton.setEnabled(false);
return toggleButton;
}
highlightButton(toggleButton, pluginManager.isPluginEnabled(plugin));
toggleButton.addMouseListener(new MouseAdapter()
{
@Override
public void mousePressed(MouseEvent mouseEvent)
{
executorService.submit(() ->
{
final boolean enabled = pluginManager.isPluginEnabled(plugin);
pluginManager.setPluginEnabled(plugin, !enabled);
try
{
if (enabled)
{
pluginManager.stopPlugin(plugin);
}
else
{
pluginManager.startPlugin(plugin);
}
}
catch (PluginInstantiationException ex)
{
log.warn("Error during starting/stopping plugin {}", plugin.getClass().getSimpleName(), ex);
}
highlightButton(toggleButton, !enabled);
});
listItem.setPluginEnabled(pluginManager.isPluginEnabled(plugin));
}
});
return toggleButton;
if (showingPluginList)
{
openConfigList();
}
}
private void highlightButton(JLabel button, boolean enabled)
void openConfigList()
{
button.setIcon(enabled ? ON_SWITCHER : OFF_SWITCHER);
button.setToolTipText(enabled ? "Disable plugin" : "Enable plugin");
if (showingPluginList)
{
scrollBarPosition = scrollPane.getVerticalScrollBar().getValue();
}
showingPluginList = true;
topPanel.removeAll();
mainPanel.removeAll();
JLabel title = new JLabel("Configuration", SwingConstants.LEFT);
title.setForeground(Color.WHITE);
topPanel.add(title, BorderLayout.NORTH);
topPanel.add(searchBar, BorderLayout.CENTER);
onSearchBarChanged();
searchBar.requestFocusInWindow();
validate();
scrollPane.getVerticalScrollBar().setValue(scrollBarPosition);
}
private void onSearchBarChanged()
{
final String text = searchBar.getText();
children.values().forEach(this::remove);
pluginList.forEach(mainPanel::remove);
if (text.isEmpty())
{
children.values().forEach(this::add);
revalidate();
return;
}
showMatchingPlugins(true, text);
showMatchingPlugins(false, text);
FuzzySearch.findAndProcess(text, children.keySet(), (k) -> add(children.get(k)));
revalidate();
}
@Override
public void onActivate()
private void showMatchingPlugins(boolean pinned, String text)
{
super.onActivate();
if (searchBar.getParent() != null)
if (text.isEmpty())
{
searchBar.requestFocusInWindow();
pluginList.stream().filter(item -> pinned == item.isPinned()).forEach(mainPanel::add);
return;
}
}
private void openConfigList()
{
removeAll();
JLabel title = new JLabel("Configuration", SwingConstants.LEFT);
title.setForeground(Color.WHITE);
add(title);
add(searchBar);
onSearchBarChanged();
searchBar.requestFocusInWindow();
JScrollPane scrollbar = getScrollPane();
scrollbar.validate();
scrollbar.getVerticalScrollBar().setValue(scrollBarPosition);
}
private void changeConfiguration(Config config, JComponent component, ConfigDescriptor cd, ConfigItemDescriptor cid)
{
ConfigItem configItem = cid.getItem();
if (!Strings.isNullOrEmpty(configItem.warning()))
final String[] searchTerms = text.toLowerCase().split(" ");
pluginList.forEach(listItem ->
{
final int result = JOptionPane.showOptionDialog(component, configItem.warning(),
"Are you sure?", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE,
null, new String[]{"Yes", "No"}, "No");
if (result != JOptionPane.YES_OPTION)
if (pinned == listItem.isPinned() && listItem.matchesSearchTerms(searchTerms))
{
openGroupConfigPanel(config, cd, configManager);
return;
mainPanel.add(listItem);
}
}
if (component instanceof JCheckBox)
{
JCheckBox checkbox = (JCheckBox) component;
configManager.setConfiguration(cd.getGroup().keyName(), cid.getItem().keyName(), "" + checkbox.isSelected());
}
if (component instanceof JSpinner)
{
JSpinner spinner = (JSpinner) component;
configManager.setConfiguration(cd.getGroup().keyName(), cid.getItem().keyName(), "" + spinner.getValue());
}
if (component instanceof JTextArea)
{
JTextArea textField = (JTextArea) component;
configManager.setConfiguration(cd.getGroup().keyName(), cid.getItem().keyName(), textField.getText());
}
if (component instanceof JColorChooser)
{
JColorChooser jColorChooser = (JColorChooser) component;
configManager.setConfiguration(cd.getGroup().keyName(), cid.getItem().keyName(), String.valueOf(jColorChooser.getColor().getRGB()));
}
if (component instanceof JComboBox)
{
JComboBox jComboBox = (JComboBox) component;
configManager.setConfiguration(cd.getGroup().keyName(), cid.getItem().keyName(), ((Enum) jComboBox.getSelectedItem()).name());
}
if (component instanceof HotkeyButton)
{
HotkeyButton hotkeyButton = (HotkeyButton) component;
configManager.setConfiguration(cd.getGroup().keyName(), cid.getItem().keyName(), hotkeyButton.getValue());
}
});
}
private void openGroupConfigPanel(Config config, ConfigDescriptor cd, ConfigManager configManager)
void openGroupConfigPanel(PluginListItem listItem, Config config, ConfigDescriptor cd)
{
scrollBarPosition = getScrollPane().getVerticalScrollBar().getValue();
removeAll();
String name = cd.getGroup().name() + " Configuration";
JLabel title = new JLabel(name, SwingConstants.CENTER);
showingPluginList = false;
scrollBarPosition = scrollPane.getVerticalScrollBar().getValue();
topPanel.removeAll();
mainPanel.removeAll();
final IconButton topPanelBackButton = new IconButton(BACK_ICON, BACK_ICON_HOVER);
topPanelBackButton.setPreferredSize(new Dimension(22, 0));
topPanelBackButton.setBorder(new EmptyBorder(0, 0, 0, 5));
topPanelBackButton.addActionListener(e -> openConfigList());
topPanelBackButton.setToolTipText("Back");
topPanel.add(topPanelBackButton, BorderLayout.WEST);
topPanel.add(listItem.createToggleButton(), BorderLayout.EAST);
String name = listItem.getName();
JLabel title = new JLabel(name);
title.setForeground(Color.WHITE);
title.setToolTipText(cd.getGroup().description());
add(title);
title.setToolTipText("<html>" + name + ":<br>" + listItem.getDescription() + "</html>");
topPanel.add(title);
for (ConfigItemDescriptor cid : cd.getItems())
{
@@ -457,6 +338,7 @@ public class ConfigPanel extends PluginPanel
JPanel item = new JPanel();
item.setLayout(new BorderLayout());
item.setMinimumSize(new Dimension(PANEL_WIDTH, 0));
name = cid.getItem().name();
JLabel configEntryName = new JLabel(name);
configEntryName.setForeground(Color.WHITE);
@@ -467,22 +349,22 @@ public class ConfigPanel extends PluginPanel
{
JCheckBox checkbox = new JCheckBox();
checkbox.setBackground(ColorScheme.LIGHT_GRAY_COLOR);
checkbox.setSelected(Boolean.parseBoolean(configManager.getConfiguration(cd.getGroup().keyName(), cid.getItem().keyName())));
checkbox.addActionListener(ae -> changeConfiguration(config, checkbox, cd, cid));
checkbox.setSelected(Boolean.parseBoolean(configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName())));
checkbox.addActionListener(ae -> changeConfiguration(listItem, config, checkbox, cd, cid));
item.add(checkbox, BorderLayout.EAST);
}
if (cid.getType() == int.class)
{
int value = Integer.parseInt(configManager.getConfiguration(cd.getGroup().keyName(), cid.getItem().keyName()));
int value = Integer.parseInt(configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName()));
SpinnerModel model = new SpinnerNumberModel(value, 0, Integer.MAX_VALUE, 1);
JSpinner spinner = new JSpinner(model);
Component editor = spinner.getEditor();
JFormattedTextField spinnerTextField = ((JSpinner.DefaultEditor) editor).getTextField();
spinnerTextField.setColumns(SPINNER_FIELD_WIDTH);
spinner.addChangeListener(ce -> changeConfiguration(config, spinner, cd, cid));
spinner.addChangeListener(ce -> changeConfiguration(listItem, config, spinner, cd, cid));
item.add(spinner, BorderLayout.EAST);
}
@@ -493,14 +375,14 @@ public class ConfigPanel extends PluginPanel
textField.setLineWrap(true);
textField.setWrapStyleWord(true);
textField.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
textField.setText(configManager.getConfiguration(cd.getGroup().keyName(), cid.getItem().keyName()));
textField.setText(configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName()));
textField.addFocusListener(new FocusAdapter()
{
@Override
public void focusLost(FocusEvent e)
{
changeConfiguration(config, textField, cd, cid);
changeConfiguration(listItem, config, textField, cd, cid);
}
});
@@ -509,7 +391,7 @@ public class ConfigPanel extends PluginPanel
if (cid.getType() == Color.class)
{
String existing = configManager.getConfiguration(cd.getGroup().keyName(), cid.getItem().keyName());
String existing = configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName());
Color existingColor;
JButton colorPicker;
@@ -544,7 +426,7 @@ public class ConfigPanel extends PluginPanel
@Override
public void windowClosing(WindowEvent e)
{
changeConfiguration(config, jColorChooser, cd, cid);
changeConfiguration(listItem, config, jColorChooser, cd, cid);
}
});
parent.add(jColorChooser);
@@ -560,7 +442,7 @@ public class ConfigPanel extends PluginPanel
JPanel dimensionPanel = new JPanel();
dimensionPanel.setLayout(new BorderLayout());
String str = configManager.getConfiguration(cd.getGroup().keyName(), cid.getItem().keyName());
String str = configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName());
String[] splitStr = str.split("x");
int width = Integer.parseInt(splitStr[0]);
int height = Integer.parseInt(splitStr[1]);
@@ -578,7 +460,7 @@ public class ConfigPanel extends PluginPanel
heightSpinnerTextField.setColumns(4);
ChangeListener listener = e ->
configManager.setConfiguration(cd.getGroup().keyName(), cid.getItem().keyName(), widthSpinner.getValue() + "x" + heightSpinner.getValue());
configManager.setConfiguration(cd.getGroup().value(), cid.getItem().keyName(), widthSpinner.getValue() + "x" + heightSpinner.getValue());
widthSpinner.addChangeListener(listener);
heightSpinner.addChangeListener(listener);
@@ -601,7 +483,7 @@ public class ConfigPanel extends PluginPanel
box.setPrototypeDisplayValue("XXXXXXXX"); //sorry but this is the way to keep the size of the combobox in check.
try
{
Enum selectedItem = Enum.valueOf(type, configManager.getConfiguration(cd.getGroup().keyName(), cid.getItem().keyName()));
Enum selectedItem = Enum.valueOf(type, configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName()));
box.setSelectedItem(selectedItem);
box.setToolTipText(selectedItem.toString());
}
@@ -613,7 +495,7 @@ public class ConfigPanel extends PluginPanel
{
if (e.getStateChange() == ItemEvent.SELECTED)
{
changeConfiguration(config, box, cd, cid);
changeConfiguration(listItem, config, box, cd, cid);
box.setToolTipText(box.getSelectedItem().toString());
}
});
@@ -622,7 +504,7 @@ public class ConfigPanel extends PluginPanel
if (cid.getType() == Keybind.class)
{
Keybind startingValue = configManager.getConfiguration(cd.getGroup().keyName(), cid.getItem().keyName(), Keybind.class);
Keybind startingValue = configManager.getConfiguration(cd.getGroup().value(), cid.getItem().keyName(), Keybind.class);
HotkeyButton button = new HotkeyButton(startingValue);
@@ -631,14 +513,14 @@ public class ConfigPanel extends PluginPanel
@Override
public void focusLost(FocusEvent e)
{
changeConfiguration(config, button, cd, cid);
changeConfiguration(listItem, config, button, cd, cid);
}
});
item.add(button, BorderLayout.EAST);
}
add(item);
mainPanel.add(item);
}
JButton resetButton = new JButton("Reset");
@@ -647,15 +529,151 @@ public class ConfigPanel extends PluginPanel
configManager.setDefaultConfiguration(config, true);
// Reload configuration panel
openGroupConfigPanel(config, cd, configManager);
openGroupConfigPanel(listItem, config, cd);
});
add(resetButton);
mainPanel.add(resetButton);
JButton backButton = new JButton("Back");
backButton.addActionListener(e -> openConfigList());
add(backButton);
mainPanel.add(backButton);
revalidate();
getScrollPane().getVerticalScrollBar().setValue(0);
scrollPane.getVerticalScrollBar().setValue(0);
}
private void changeConfiguration(PluginListItem listItem, Config config, JComponent component, ConfigDescriptor cd, ConfigItemDescriptor cid)
{
final ConfigItem configItem = cid.getItem();
if (!Strings.isNullOrEmpty(configItem.warning()))
{
final int result = JOptionPane.showOptionDialog(component, configItem.warning(),
"Are you sure?", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE,
null, new String[]{"Yes", "No"}, "No");
if (result != JOptionPane.YES_OPTION)
{
openGroupConfigPanel(listItem, config, cd);
return;
}
}
if (component instanceof JCheckBox)
{
JCheckBox checkbox = (JCheckBox) component;
configManager.setConfiguration(cd.getGroup().value(), cid.getItem().keyName(), "" + checkbox.isSelected());
}
else if (component instanceof JSpinner)
{
JSpinner spinner = (JSpinner) component;
configManager.setConfiguration(cd.getGroup().value(), cid.getItem().keyName(), "" + spinner.getValue());
}
else if (component instanceof JTextArea)
{
JTextArea textField = (JTextArea) component;
configManager.setConfiguration(cd.getGroup().value(), cid.getItem().keyName(), textField.getText());
}
else if (component instanceof JColorChooser)
{
JColorChooser jColorChooser = (JColorChooser) component;
configManager.setConfiguration(cd.getGroup().value(), cid.getItem().keyName(), String.valueOf(jColorChooser.getColor().getRGB()));
}
else if (component instanceof JComboBox)
{
JComboBox jComboBox = (JComboBox) component;
configManager.setConfiguration(cd.getGroup().value(), cid.getItem().keyName(), ((Enum) jComboBox.getSelectedItem()).name());
}
else if (component instanceof HotkeyButton)
{
HotkeyButton hotkeyButton = (HotkeyButton) component;
configManager.setConfiguration(cd.getGroup().value(), cid.getItem().keyName(), hotkeyButton.getValue());
}
}
void startPlugin(Plugin plugin, PluginListItem listItem)
{
executorService.submit(() ->
{
pluginManager.setPluginEnabled(plugin, true);
try
{
pluginManager.startPlugin(plugin);
}
catch (PluginInstantiationException ex)
{
log.warn("Error when starting plugin {}", plugin.getClass().getSimpleName(), ex);
}
listItem.setPluginEnabled(true);
});
}
void stopPlugin(Plugin plugin, PluginListItem listItem)
{
executorService.submit(() ->
{
pluginManager.setPluginEnabled(plugin, false);
try
{
pluginManager.stopPlugin(plugin);
}
catch (PluginInstantiationException ex)
{
log.warn("Error when stopping plugin {}", plugin.getClass().getSimpleName(), ex);
}
listItem.setPluginEnabled(false);
});
}
private List<String> getPinnedPluginNames()
{
final String config = configManager.getConfiguration(RUNELITE_GROUP_NAME, PINNED_PLUGINS_CONFIG_KEY);
if (config == null)
{
return Collections.emptyList();
}
return COMMA_SPLITTER.splitToList(config);
}
void savePinnedPlugins()
{
final String value = pluginList.stream()
.filter(PluginListItem::isPinned)
.map(PluginListItem::getName)
.collect(Collectors.joining(","));
configManager.setConfiguration(RUNELITE_GROUP_NAME, PINNED_PLUGINS_CONFIG_KEY, value);
}
@Override
public void onActivate()
{
super.onActivate();
if (searchBar.getParent() != null)
{
searchBar.requestFocusInWindow();
}
}
@Override
public Dimension getPreferredSize()
{
return new Dimension(PANEL_WIDTH + SCROLLBAR_WIDTH, super.getPreferredSize().height);
}
private class FixedWidthPanel extends JPanel
{
@Override
public Dimension getPreferredSize()
{
return new Dimension(PANEL_WIDTH, super.getPreferredSize().height);
}
}
}

View File

@@ -98,6 +98,6 @@ public class ConfigPlugin extends Plugin
@Subscribe
public void onPluginChanged(PluginChanged event)
{
SwingUtilities.invokeLater(configPanel::rebuildPluginList);
SwingUtilities.invokeLater(configPanel::refreshPluginList);
}
}

View File

@@ -1,131 +0,0 @@
/*
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
* 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.config;
import java.util.Collection;
import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import lombok.Value;
import org.apache.commons.text.similarity.JaroWinklerDistance;
public class FuzzySearch
{
private static final JaroWinklerDistance FUZZY_SCORE = new JaroWinklerDistance();
private static final double STRING_OCCURRENCE_MULTIPLIER = 3d;
/**
* Try to find a match and call callback on each match, sorted by score and filtered by average
*
* @param query query to search for
* @param entries entries to search in
* @param callback callback to call
*/
public static void findAndProcess(final String query, final Collection<String> entries, final Consumer<String> callback)
{
// Calculate score for each entry matching query
final Set<FuzzyMatch> matches = entries.stream()
.map(entry -> new FuzzyMatch(
FUZZY_SCORE.apply(query, entry)
+ calculateStringOccurrenceBonus(entry, query)
* STRING_OCCURRENCE_MULTIPLIER,
entry))
.collect(Collectors.toSet());
// Calculate average score of the matches to filter out the less relevant ones
final double average = matches.stream().mapToDouble(m -> m.score).average().orElse(0);
final double max = matches.stream().mapToDouble(m -> m.score).max().orElse(0);
final double limit = Math.min(average * 1.7, max);
matches.stream()
.filter(m -> m.score >= limit)
.sorted((left, right) -> Double.compare(right.score, left.score))
.map(m -> m.value)
.forEach(callback);
}
/**
* Calculates string occurrence bonus of query in the entry string
* @param entry entry string
* @param query query string
* @return string occurrence bonus
*/
private static double calculateStringOccurrenceBonus(final String entry, final String query)
{
// Exit early, no occurrence bonus for too long query
if (query.length() > entry.length())
{
return 0;
}
// Create relaxed variants of the input (e.g lower cased ones)
final String relaxedEntry = entry.toLowerCase();
final String relaxedQuery = query.toLowerCase();
// Create base bonus
final double base = 1d / 6d;
if (entry.equals(query))
{
return base * 6d;
}
if (entry.equals(relaxedQuery) || relaxedQuery.equals(entry))
{
return base * 5d;
}
if (relaxedEntry.equals(relaxedQuery))
{
return base * 4d;
}
if (entry.contains(query))
{
return base * 3d;
}
if (entry.contains(relaxedQuery) || relaxedEntry.contains(query))
{
return base * 2d;
}
if (relaxedEntry.contains(relaxedQuery))
{
return base;
}
return 0;
}
@Value
private static class FuzzyMatch
{
/**
* Score of the match
*/
double score;
/**
* Match value
*/
String value;
}
}

View File

@@ -0,0 +1,259 @@
/*
* Copyright (c) 2018, Daniel Teo <https://github.com/takuyakanbr>
* 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.config;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.annotation.Nullable;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
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.PluginPanel;
import net.runelite.client.ui.components.IconButton;
import net.runelite.client.util.SwingUtil;
import org.apache.commons.text.similarity.JaroWinklerDistance;
class PluginListItem extends JPanel
{
private static final JaroWinklerDistance DISTANCE = new JaroWinklerDistance();
private static final ImageIcon CONFIG_ICON;
private static final ImageIcon CONFIG_ICON_HOVER;
private static final ImageIcon ON_SWITCHER;
private static final ImageIcon OFF_SWITCHER;
private static final ImageIcon ON_STAR;
private static final ImageIcon OFF_STAR;
private final ConfigPanel configPanel;
@Getter
@Nullable
private final Plugin plugin;
@Getter
private final String name;
@Getter
private final String description;
private final List<String> keywords = new ArrayList<>();
private final IconButton pinButton = new IconButton(OFF_STAR);
private final IconButton configButton = new IconButton(CONFIG_ICON, CONFIG_ICON_HOVER);
private final IconButton toggleButton = new IconButton(OFF_SWITCHER);
private boolean isPluginEnabled = false;
@Getter
private boolean isPinned = false;
static
{
try
{
BufferedImage configIcon;
synchronized (ImageIO.class)
{
configIcon = ImageIO.read(ConfigPanel.class.getResourceAsStream("config_edit_icon.png"));
CONFIG_ICON = new ImageIcon(configIcon);
ON_SWITCHER = new ImageIcon(ImageIO.read(ConfigPanel.class.getResourceAsStream("switchers/on.png")));
OFF_SWITCHER = new ImageIcon(ImageIO.read(ConfigPanel.class.getResourceAsStream("switchers/off.png")));
ON_STAR = new ImageIcon(ImageIO.read(ConfigPanel.class.getResourceAsStream("stars/on.png")));
OFF_STAR = new ImageIcon(ImageIO.read(ConfigPanel.class.getResourceAsStream("stars/off.png")));
}
CONFIG_ICON_HOVER = new ImageIcon(SwingUtil.grayscaleOffset(configIcon, -100));
}
catch (IOException e)
{
throw new RuntimeException(e);
}
}
/**
* Creates a new {@code PluginListItem} for a plugin.
* <p>
* Note that {@code config} and {@code configDescriptor} can be {@code null}
* if there is no configuration associated with the plugin.
*/
PluginListItem(ConfigPanel configPanel, Plugin plugin, PluginDescriptor descriptor,
@Nullable Config config, @Nullable ConfigDescriptor configDescriptor)
{
this(configPanel, plugin, config, configDescriptor,
descriptor.name(), descriptor.description(), descriptor.tags());
}
/**
* Creates a new {@code PluginListItem} for a core configuration.
*/
PluginListItem(ConfigPanel configPanel, Config config, ConfigDescriptor configDescriptor,
String name, String description, String... tags)
{
this(configPanel, null, config, configDescriptor, name, description, tags);
}
private PluginListItem(ConfigPanel configPanel, @Nullable Plugin plugin, @Nullable Config config,
@Nullable ConfigDescriptor configDescriptor, String name, String description, String... tags)
{
this.configPanel = configPanel;
this.plugin = plugin;
this.name = name;
this.description = description;
Collections.addAll(keywords, name.toLowerCase().split(" "));
Collections.addAll(keywords, tags);
setLayout(new BorderLayout(3, 0));
setPreferredSize(new Dimension(PluginPanel.PANEL_WIDTH, 20));
JLabel nameLabel = new JLabel(name);
nameLabel.setForeground(Color.WHITE);
if (!description.isEmpty())
{
nameLabel.setToolTipText("<html>" + name + ":<br>" + description + "</html>");
}
add(nameLabel, BorderLayout.CENTER);
pinButton.setPreferredSize(new Dimension(21, 0));
add(pinButton, BorderLayout.LINE_START);
pinButton.addActionListener(e ->
{
setPinned(!isPinned);
configPanel.savePinnedPlugins();
configPanel.openConfigList();
});
final JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(1, 2));
add(buttonPanel, BorderLayout.LINE_END);
configButton.setPreferredSize(new Dimension(25, 0));
configButton.setVisible(false);
buttonPanel.add(configButton);
// add a listener to configButton only if there are config items to show
if (config != null && !configDescriptor.getItems().stream().allMatch(item -> item.getItem().hidden()))
{
configButton.addActionListener(e ->
{
configButton.setIcon(CONFIG_ICON);
configPanel.openGroupConfigPanel(PluginListItem.this, config, configDescriptor);
});
configButton.setVisible(true);
configButton.setToolTipText("Edit plugin configuration");
}
toggleButton.setPreferredSize(new Dimension(25, 0));
attachToggleButtonListener(toggleButton);
buttonPanel.add(toggleButton);
}
private void attachToggleButtonListener(IconButton button)
{
// no need for a listener if there is no plugin to enable / disable
if (plugin == null)
{
button.setVisible(false);
return;
}
button.addActionListener(e ->
{
if (isPluginEnabled)
{
configPanel.stopPlugin(plugin, PluginListItem.this);
}
else
{
configPanel.startPlugin(plugin, PluginListItem.this);
}
setPluginEnabled(!isPluginEnabled);
updateToggleButton(button);
});
}
IconButton createToggleButton()
{
IconButton button = new IconButton(OFF_SWITCHER);
button.setPreferredSize(new Dimension(25, 0));
updateToggleButton(button);
attachToggleButtonListener(button);
return button;
}
void setPluginEnabled(boolean enabled)
{
isPluginEnabled = enabled;
updateToggleButton(toggleButton);
}
void setPinned(boolean pinned)
{
isPinned = pinned;
pinButton.setIcon(pinned ? ON_STAR : OFF_STAR);
pinButton.setToolTipText(pinned ? "Unpin plugin" : "Pin plugin");
}
private void updateToggleButton(IconButton button)
{
button.setIcon(isPluginEnabled ? ON_SWITCHER : OFF_SWITCHER);
button.setToolTipText(isPluginEnabled ? "Disable plugin" : "Enable plugin");
}
/**
* Checks if all the search terms in the given list matches at least one keyword.
* @return true if all search terms matches at least one keyword, or false if otherwise.
*/
boolean matchesSearchTerms(String[] searchTerms)
{
for (String term : searchTerms)
{
if (keywords.stream().noneMatch((t) -> t.contains(term) ||
DISTANCE.apply(t, term) > 0.9))
{
return false;
}
}
return true;
}
}

View File

@@ -51,7 +51,9 @@ import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager;
@PluginDescriptor(
name = "Corporeal Beast"
name = "Corporeal Beast",
description = "Show damage statistics and highlight dark energy cores",
tags = {"bosses", "combat", "pve", "overlay"}
)
public class CorpPlugin extends Plugin
{

View File

@@ -44,6 +44,8 @@ import okhttp3.Response;
@PluginDescriptor(
name = "Crystal Math Labs",
description = "Automatically updates your stats on Crystal Math Labs when you log out",
tags = {"cml", "external", "integration"},
enabledByDefault = false
)
@Slf4j

View File

@@ -28,11 +28,7 @@ import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(
keyName = "dailytaskindicators",
name = "Daily Task Indicators",
description = "Configuration for Daily Task Indicators plugin"
)
@ConfigGroup("dailytaskindicators")
public interface DailyTasksConfig extends Config
{
@ConfigItem(

View File

@@ -46,6 +46,7 @@ import net.runelite.client.plugins.PluginDescriptor;
@PluginDescriptor(
name = "Daily Task Indicator",
description = "Show chat notifications for daily tasks upon login",
enabledByDefault = false
)
@Slf4j

View File

@@ -29,11 +29,7 @@ import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(
keyName = "deathIndicator",
name = "Death Indicator",
description = "Configuration for the death indicator plugin"
)
@ConfigGroup("deathIndicator")
public interface DeathIndicatorConfig extends Config
{
@ConfigItem(

View File

@@ -53,7 +53,9 @@ import net.runelite.client.ui.overlay.infobox.Timer;
import net.runelite.client.ui.overlay.worldmap.WorldMapPointManager;
@PluginDescriptor(
name = "Death Indicator"
name = "Death Indicator",
description = "Show where you last died, and on what world",
tags = {"arrow", "hints", "world", "map", "overlay"}
)
@Slf4j
public class DeathIndicatorPlugin extends Plugin

View File

@@ -28,11 +28,7 @@ import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(
keyName = "defaultworld",
name = "Default World",
description = "Sets the default world and remembers it"
)
@ConfigGroup("defaultworld")
public interface DefaultWorldConfig extends Config
{
@ConfigItem(

View File

@@ -42,7 +42,10 @@ import net.runelite.http.api.worlds.World;
import net.runelite.http.api.worlds.WorldClient;
import net.runelite.http.api.worlds.WorldResult;
@PluginDescriptor(name = "Default World")
@PluginDescriptor(
name = "Default World",
description = "Enable a default world to be selected when launching the client"
)
@Slf4j
public class DefaultWorldPlugin extends Plugin
{

View File

@@ -61,7 +61,9 @@ import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager;
@PluginDescriptor(
name = "Demonic Gorillas"
name = "Demonic Gorillas",
description = "Count demonic gorilla attacks and display their next possible attack styles",
tags = {"combat", "overlay"}
)
@Slf4j
public class DemonicGorillaPlugin extends Plugin

View File

@@ -27,11 +27,7 @@ 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"
)
@ConfigGroup("devtools")
public interface DevToolsConfig
{
@ConfigItem(

View File

@@ -55,6 +55,7 @@ import org.slf4j.LoggerFactory;
@PluginDescriptor(
name = "Developer Tools",
tags = {"panel"},
developerPlugin = true
)
@Slf4j

View File

@@ -28,11 +28,7 @@ import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(
keyName = "discord",
name = "Discord",
description = "Configuration for Discord plugin"
)
@ConfigGroup("discord")
public interface DiscordConfig extends Config
{
@ConfigItem(

View File

@@ -48,7 +48,9 @@ import net.runelite.client.ui.TitleToolbar;
import net.runelite.client.util.LinkBrowser;
@PluginDescriptor(
name = "Discord"
name = "Discord",
description = "Show your status and activity in the Discord user panel",
tags = {"action", "activity", "external", "integration", "status"}
)
public class DiscordPlugin extends Plugin
{

View File

@@ -29,11 +29,7 @@ import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(
keyName = "entityhider",
name = "Entity Hider",
description = "Hides various entities such as players and NPCs"
)
@ConfigGroup("entityhider")
public interface EntityHiderConfig extends Config
{
@ConfigItem(

View File

@@ -36,6 +36,8 @@ import net.runelite.client.plugins.PluginDescriptor;
@PluginDescriptor(
name = "Entity Hider",
description = "Hide players, NPCs, and/or projectiles",
tags = {"npcs", "players", "projectiles"},
enabledByDefault = false
)
public class EntityHiderPlugin extends Plugin

View File

@@ -61,7 +61,9 @@ import net.runelite.http.api.item.ItemPrice;
* @author Adam
*/
@PluginDescriptor(
name = "Examine"
name = "Examine",
description = "Send examine information to the API",
tags = {"npcs", "items", "inventory", "objects"}
)
@Slf4j
public class ExaminePlugin extends Plugin

View File

@@ -29,11 +29,7 @@ import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(
keyName = "xpdrop",
name = "XP Drop",
description = "Configuration for XP drop customization"
)
@ConfigGroup("xpdrop")
public interface XpDropConfig extends Config
{
@ConfigItem(

View File

@@ -41,7 +41,9 @@ import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
@PluginDescriptor(
name = "XP Drop"
name = "XP Drop",
description = "Enable customization of the way XP drops are displayed",
tags = {"experience", "levels"}
)
public class XpDropPlugin extends Plugin
{

View File

@@ -39,7 +39,9 @@ import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
@PluginDescriptor(
name = "Fairy Ring Helper"
name = "Fairy Ring Helper",
description = "Show the location of the fairy ring teleport",
tags = {"teleportation"}
)
public class FairyRingPlugin extends Plugin
{

View File

@@ -28,11 +28,7 @@ import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(
keyName = "farmingTracker",
name = "Farming Tracker",
description = "Configuration for the farming tracker"
)
@ConfigGroup("farmingTracker")
public interface FarmingTrackerConfig extends Config
{
String KEY_NAME = "farmingTracker";

View File

@@ -48,7 +48,9 @@ import net.runelite.client.ui.NavigationButton;
import net.runelite.client.ui.PluginToolbar;
@PluginDescriptor(
name = "Farming Tracker"
name = "Farming Tracker",
description = "Show when your farming plots would be fully grown",
tags = {"skilling", "panel", "timers"}
)
@Slf4j
public class FarmingTrackerPlugin extends Plugin

View File

@@ -4,11 +4,7 @@ import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(
keyName = "feed",
name = "News Feed",
description = "Displays client and game-related news"
)
@ConfigGroup("feed")
public interface FeedConfig extends Config
{
@ConfigItem(

View File

@@ -48,6 +48,8 @@ import net.runelite.http.api.feed.FeedResult;
@PluginDescriptor(
name = "News Feed",
description = "Show the latest RuneLite blog posts, OSRS news, and JMod Twitter posts",
tags = {"external", "integration", "panel", "twitter"},
loadWhenOutdated = true
)
@Slf4j

View File

@@ -39,7 +39,9 @@ import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager;
@PluginDescriptor(
name = "Fight Cave"
name = "Fight Cave",
description = "Show what to pray against Jad",
tags = {"bosses", "combat", "minigame", "overlay", "prayer", "pve"}
)
public class FightCavePlugin extends Plugin
{

View File

@@ -28,11 +28,7 @@ import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(
keyName = "fishing",
name = "Fishing",
description = "Configuration for the fishing plugin"
)
@ConfigGroup("fishing")
public interface FishingConfig extends Config
{
@ConfigItem(

View File

@@ -53,7 +53,9 @@ import net.runelite.client.ui.overlay.OverlayManager;
import net.runelite.client.util.QueryRunner;
@PluginDescriptor(
name = "Fishing"
name = "Fishing",
description = "Show fishing stats and mark fishing spots",
tags = {"overlay", "skilling"}
)
@PluginDependency(XpTrackerPlugin.class)
@Singleton

View File

@@ -28,11 +28,7 @@ import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(
keyName = FpsPlugin.CONFIG_GROUP_KEY,
name = "FPS Control",
description = "Lets you control what your game frame rate is, often helps keep CPU down too"
)
@ConfigGroup(FpsPlugin.CONFIG_GROUP_KEY)
public interface FpsConfig extends Config
{
@ConfigItem(

View File

@@ -47,6 +47,8 @@ import net.runelite.client.ui.overlay.OverlayManager;
*/
@PluginDescriptor(
name = "FPS Control",
description = "Show current FPS and/or set an FPS limit",
tags = {"frames", "framerate", "limit", "overlay"},
enabledByDefault = false
)
public class FpsPlugin extends Plugin

View File

@@ -52,7 +52,10 @@ import net.runelite.client.ui.overlay.OverlayManager;
import net.runelite.client.util.Text;
@Slf4j
@PluginDescriptor(name = "Friend Notes")
@PluginDescriptor(
name = "Friend Notes",
description = "Store notes about your friends"
)
public class FriendNotesPlugin extends Plugin
{
private static final String CONFIG_GROUP = "friendNotes";

View File

@@ -28,11 +28,7 @@ import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(
keyName = "grandexchange",
name = "Grand Exchange",
description = "Configuration for the Grand Exchange"
)
@ConfigGroup("grandexchange")
public interface GrandExchangeConfig extends Config
{
@ConfigItem(

View File

@@ -71,7 +71,9 @@ import net.runelite.http.api.osbuddy.GrandExchangeClient;
import net.runelite.http.api.osbuddy.GrandExchangeResult;
@PluginDescriptor(
name = "Grand Exchange"
name = "Grand Exchange",
description = "Provide additional and/or easier access to Grand Exchange information",
tags = {"external", "integration", "notifications", "panel", "prices", "trade"}
)
@Slf4j
public class GrandExchangePlugin extends Plugin

View File

@@ -33,11 +33,7 @@ import net.runelite.client.plugins.grounditems.config.ItemHighlightMode;
import net.runelite.client.plugins.grounditems.config.MenuHighlightMode;
import net.runelite.client.plugins.grounditems.config.PriceDisplayMode;
@ConfigGroup(
keyName = "grounditems",
name = "Ground Items",
description = "Configuration for the ground items plugin"
)
@ConfigGroup("grounditems")
public interface GroundItemsConfig extends Config
{
@ConfigItem(

View File

@@ -85,7 +85,9 @@ import net.runelite.client.ui.overlay.OverlayManager;
import net.runelite.http.api.item.ItemPrice;
@PluginDescriptor(
name = "Ground Items"
name = "Ground Items",
description = "Highlight ground items and/or show price information",
tags = {"grand", "exchange", "high", "alchemy", "prices", "highlight", "overlay"}
)
@Slf4j
public class GroundItemsPlugin extends Plugin

View File

@@ -32,11 +32,7 @@ import net.runelite.client.config.ConfigItem;
import java.awt.Color;
@ConfigGroup(
keyName = "groundMarker",
name = "Ground Marker",
description = "Mark ground tiles"
)
@ConfigGroup("groundMarker")
public interface GroundMarkerConfig extends Config
{
@ConfigItem(

View File

@@ -60,7 +60,9 @@ import net.runelite.client.ui.overlay.OverlayManager;
@Slf4j
@PluginDescriptor(
name = "Ground Markers"
name = "Ground Markers",
description = "Enable marking of tiles using the Shift key",
tags = {"overlay", "tiles"}
)
public class GroundMarkerPlugin extends Plugin
{

View File

@@ -29,11 +29,7 @@ import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(
keyName = "herbiboar",
name = "Herbiboar",
description = "Configuration for the herbiboar plugin"
)
@ConfigGroup("herbiboar")
public interface HerbiboarConfig extends Config
{
@ConfigItem(

View File

@@ -61,7 +61,9 @@ import net.runelite.client.ui.overlay.OverlayManager;
@Slf4j
@PluginDescriptor(
name = "Herbiboar"
name = "Herbiboar",
description = "Highlight starting rocks, trails, and the objects to search at the end of each trail",
tags = {"herblore", "hunter", "skilling", "overlay"}
)
public class HerbiboarPlugin extends Plugin
{

View File

@@ -28,11 +28,7 @@ import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(
keyName = "hiscore",
name = "HiScore",
description = "Configuration for the hiscore plugin"
)
@ConfigGroup("hiscore")
public interface HiscoreConfig extends Config
{
@ConfigItem(

View File

@@ -53,6 +53,8 @@ import org.apache.commons.lang3.ArrayUtils;
@PluginDescriptor(
name = "HiScore",
description = "Enable the HiScore panel and an optional Lookup option on players",
tags = {"panel", "players"},
loadWhenOutdated = true
)
public class HiscorePlugin extends Plugin

View File

@@ -29,11 +29,7 @@ import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(
keyName = "hunterplugin",
name = "Hunter",
description = "Configuration for the hunter plugin"
)
@ConfigGroup("hunterplugin")
public interface HunterConfig extends Config
{
@ConfigItem(

View File

@@ -52,7 +52,9 @@ import net.runelite.client.ui.overlay.OverlayManager;
@Slf4j
@PluginDescriptor(
name = "Hunter"
name = "Hunter",
description = "Show the state of your traps",
tags = {"overlay", "skilling", "timers"}
)
public class HunterPlugin extends Plugin
{

View File

@@ -28,11 +28,7 @@ import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(
keyName = "idlenotifier",
name = "Idle Notifier",
description = "Configuration for the idle notifier plugin"
)
@ConfigGroup("idlenotifier")
public interface IdleNotifierConfig extends Config
{
@ConfigItem(

View File

@@ -46,7 +46,9 @@ import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor;
@PluginDescriptor(
name = "Idle Notifier"
name = "Idle Notifier",
description = "Send a notification when going idle, or when HP/Prayer reaches a threshold",
tags = {"health", "hitpoints", "notifications", "prayer"}
)
public class IdleNotifierPlugin extends Plugin
{

View File

@@ -33,11 +33,7 @@ import net.runelite.client.config.ConfigItem;
*
* @author robin
*/
@ConfigGroup(
keyName = "implings",
name = "Implings",
description = "Configuration for the implings plugin"
)
@ConfigGroup("implings")
public interface ImplingsConfig extends Config
{
@ConfigItem(

View File

@@ -46,7 +46,9 @@ import net.runelite.client.ui.overlay.OverlayManager;
* @author robin
*/
@PluginDescriptor(
name = "Implings"
name = "Implings",
description = "Highlight nearby implings on the minimap and on-screen",
tags = {"hunter", "minimap", "overlay"}
)
public class ImplingsPlugin extends Plugin
{

View File

@@ -34,6 +34,7 @@ import net.runelite.client.ui.PluginToolbar;
@PluginDescriptor(
name = "Info Panel",
description = "Enable the Info panel",
loadWhenOutdated = true
)
public class InfoPlugin extends Plugin

View File

@@ -40,7 +40,8 @@ import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager;
@PluginDescriptor(
name = "Instance Map"
name = "Instance Map",
description = "Add an instanced map, accessible by right-clicking the map button"
)
public class InstanceMapPlugin extends Plugin
{

View File

@@ -30,11 +30,7 @@ import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(
keyName = "interfaceStyles",
name = "Interface Styles",
description = "Configuration for the Interface Styles plugin"
)
@ConfigGroup("interfaceStyles")
public interface InterfaceStylesConfig extends Config
{
@ConfigItem(

View File

@@ -53,6 +53,8 @@ import net.runelite.client.plugins.PluginDescriptor;
@Slf4j
@PluginDescriptor(
name = "Interface Styles",
description = "Change the interface style to the 2005/2010 interface",
tags = {"2005", "2010"},
enabledByDefault = false
)
public class InterfaceStylesPlugin extends Plugin

View File

@@ -29,11 +29,7 @@ import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(
keyName = "inventorytags",
name = "Inventory Tags",
description = "Configuration for the Inventory Item Tagging plugin"
)
@ConfigGroup("inventorytags")
public interface InventoryTagsConfig extends Config
{
String GROUP = "inventorytags";

View File

@@ -52,6 +52,8 @@ import org.apache.commons.lang3.ArrayUtils;
@PluginDescriptor(
name = "Inventory Tags",
description = "Add the ability to tag items in your inventory",
tags = {"highlight", "items", "overlay", "tagging"},
enabledByDefault = false
)
public class InventoryTagsPlugin extends Plugin

View File

@@ -31,6 +31,8 @@ import net.runelite.client.ui.overlay.OverlayManager;
@PluginDescriptor(
name = "Inventory Viewer",
description = "Add an overlay showing the contents of your inventory",
tags = {"alternate", "items", "overlay", "second"},
enabledByDefault = false
)
public class InventoryViewerPlugin extends Plugin

View File

@@ -29,11 +29,7 @@ import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem;
@ConfigGroup(
keyName = "itemCharge",
name = "Item Charges",
description = "Configuration for the Item Charges plugin"
)
@ConfigGroup("itemCharge")
public interface ItemChargeConfig extends Config
{
@ConfigItem(

View File

@@ -40,7 +40,9 @@ import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.overlay.OverlayManager;
@PluginDescriptor(
name = "Item Charges"
name = "Item Charges",
description = "Show number of item charges remaining",
tags = {"inventory", "notifications", "overlay"}
)
public class ItemChargePlugin extends Plugin
{

Some files were not shown because too many files have changed in this diff Show More