diff --git a/runelite-client/src/main/java/net/runelite/client/config/ConfigItem.java b/runelite-client/src/main/java/net/runelite/client/config/ConfigItem.java index 182a03f4ae..2314285675 100644 --- a/runelite-client/src/main/java/net/runelite/client/config/ConfigItem.java +++ b/runelite-client/src/main/java/net/runelite/client/config/ConfigItem.java @@ -56,4 +56,12 @@ public @interface ConfigItem Class clazz() default void.class; String method() default ""; + + /** + * Use this to indicate the enum class that is going to be used in the multiple select config. + * This implementation made debugging problems with multiple selects a lot easier + * + * @return The Enum that will be used for the multiple select + */ + Class enumClass() default Enum.class; } diff --git a/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java b/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java index 8890bdc49b..b737f7a367 100644 --- a/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java +++ b/runelite-client/src/main/java/net/runelite/client/config/ConfigManager.java @@ -59,6 +59,7 @@ import java.util.Base64; import java.util.Collection; import java.util.Collections; import java.util.Date; +import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -95,6 +96,7 @@ import net.runelite.client.eventbus.Subscribe; import net.runelite.client.events.ClientShutdown; import net.runelite.client.events.ConfigChanged; import net.runelite.client.events.RuneScapeProfileChanged; +import net.runelite.client.plugins.OPRSExternalPluginManager; import net.runelite.client.util.ColorUtil; import net.runelite.http.api.config.ConfigClient; import net.runelite.http.api.config.ConfigEntry; @@ -841,6 +843,41 @@ public class ConfigManager { return Base64.getUrlDecoder().decode(str); } + if (type == EnumSet.class) + { + try + { + String substring = str.substring(str.indexOf("{") + 1, str.length() - 1); + String[] splitStr = substring.split(", "); + Class enumClass = null; + if (!str.contains("{")) + { + return null; + } + + enumClass = findEnumClass(str, OPRSExternalPluginManager.pluginClassLoaders); + + EnumSet enumSet = EnumSet.noneOf(enumClass); + for (String s : splitStr) + { + try + { + enumSet.add(Enum.valueOf(enumClass, s.replace("[", "").replace("]", ""))); + } + catch (IllegalArgumentException ignore) + { + return EnumSet.noneOf(enumClass); + } + } + return enumSet; + } + catch (Exception e) + { + e.printStackTrace(); + return null; + } + } + return str; } @@ -892,6 +929,16 @@ public class ConfigManager { return Base64.getUrlEncoder().encodeToString((byte[]) object); } + if (object instanceof EnumSet) + { + if (((EnumSet) object).size() == 0) + { + return getElementType((EnumSet) object).getCanonicalName() + "{}"; + } + + return ((EnumSet) object).toArray()[0].getClass().getCanonicalName() + "{" + object.toString() + "}"; + } + return object == null ? null : object.toString(); } @@ -924,6 +971,59 @@ public class ConfigManager } } + public static > Class getElementType(EnumSet enumSet) + { + if (enumSet.isEmpty()) + { + enumSet = EnumSet.complementOf(enumSet); + } + return enumSet.iterator().next().getDeclaringClass(); + } + + public static Class findEnumClass(String clasz, ArrayList classLoaders) + { + StringBuilder transformedString = new StringBuilder(); + for (ClassLoader cl : classLoaders) + { + try + { + String[] strings = clasz.substring(0, clasz.indexOf("{")).split("\\."); + int i = 0; + while (i != strings.length) + { + if (i == 0) + { + transformedString.append(strings[i]); + } + else if (i == strings.length - 1) + { + transformedString.append("$").append(strings[i]); + } + else + { + transformedString.append(".").append(strings[i]); + } + i++; + } + return (Class) cl.loadClass(transformedString.toString()); + } + catch (Exception e2) + { + // Will likely fail a lot + } + try + { + return (Class) cl.loadClass(clasz.substring(0, clasz.indexOf("{"))); + } + catch (Exception e) + { + // Will likely fail a lot + } + transformedString = new StringBuilder(); + } + throw new RuntimeException("Failed to find Enum for " + clasz.substring(0, clasz.indexOf("{"))); + } + @Nullable private CompletableFuture sendConfig() { 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 46a68d4ea3..29968d9cf4 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 @@ -44,7 +44,10 @@ import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.EnumSet; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.TreeMap; import javax.inject.Inject; @@ -702,6 +705,37 @@ class ConfigPanel extends PluginPanel item.add(button, BorderLayout.EAST); } + if (cid.getType() == EnumSet.class) + { + Class enumType = cid.getItem().enumClass(); + + EnumSet enumSet = configManager.getConfiguration(cd.getGroup().value(), + cid.getItem().keyName(), EnumSet.class); + if (enumSet == null || enumSet.contains(null)) + { + enumSet = EnumSet.noneOf(enumType); + } + + JPanel enumsetLayout = new JPanel(new GridLayout(0, 2)); + List jcheckboxes = new ArrayList<>(); + + for (Object obj : enumType.getEnumConstants()) + { + String option = String.valueOf(obj).toLowerCase().replace("_", " "); + + JCheckBox checkbox = new JCheckBox(option); + checkbox.setBackground(ColorScheme.LIGHT_GRAY_COLOR); + checkbox.setSelected(enumSet.contains(obj)); + jcheckboxes.add(checkbox); + + enumsetLayout.add(checkbox); + } + + jcheckboxes.forEach(checkbox -> checkbox.addActionListener(ae -> changeConfiguration(jcheckboxes, cd, cid))); + + item.add(enumsetLayout, BorderLayout.SOUTH); + } + JPanel section = sectionWidgets.get(cid.getItem().section()); JPanel title = titleWidgets.get(cid.getItem().title()); @@ -788,6 +822,32 @@ class ConfigPanel extends PluginPanel } } + private void changeConfiguration(List components, ConfigDescriptor cd, ConfigItemDescriptor cid) + { + Class enumType = cid.getItem().enumClass(); + EnumSet enumSet = configManager.getConfiguration(cd.getGroup().value(), + cid.getItem().keyName(), EnumSet.class); + if (enumSet == null) + { + //noinspection unchecked + enumSet = EnumSet.noneOf(enumType); + } + enumSet.clear(); + + EnumSet finalEnumSet = enumSet; + + //noinspection unchecked + components.forEach(value -> + { + if (value.isSelected()) + { + finalEnumSet.add(Enum.valueOf(cid.getItem().enumClass(), String.valueOf(value.getText()).toUpperCase().replace(" ", "_"))); + } + }); + + configManager.setConfiguration(cd.getGroup().value(), cid.getItem().keyName(), finalEnumSet); + } + private void changeConfiguration(Component component, ConfigDescriptor cd, ConfigItemDescriptor cid) { final ConfigItem configItem = cid.getItem();