Add tag tabs to bank tags plugin
Bring the ability to add tabs to your bank for quick access to search tags. Features: * Adding a tab * Selecting and deselecting a tab * Changing a tab's icon * Reordering tabs * Scrolling of tabs (With mouse wheel, ingame buttons, and dragging an item/tab over ingame buttons) * Saving scroll position * Dragging an item to a tab to tag the item * Tagging placeholders * Removing only a tab * Removing a tab and deleting all tags from said tab * Faster bank search when using tag tabs Closes #1205 Closes #4426 Supersedes / Closes #4862 Supersedes / Closes #3750 Can close #4082. Signed-off-by: Tomas Slusny <slusnucky@gmail.com> Co-authored-by: Tomas Slusny <slusnucky@gmail.com>
This commit is contained in:
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Ron Young <https://github.com/raiyni>
|
||||||
|
* 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.banktags;
|
||||||
|
|
||||||
|
import net.runelite.client.config.Config;
|
||||||
|
import net.runelite.client.config.ConfigGroup;
|
||||||
|
import net.runelite.client.config.ConfigItem;
|
||||||
|
|
||||||
|
@ConfigGroup("banktags")
|
||||||
|
public interface BankTagsConfig extends Config
|
||||||
|
{
|
||||||
|
@ConfigItem(
|
||||||
|
keyName = "useTabs",
|
||||||
|
name = "Use Tag Tabs",
|
||||||
|
description = "Enable the ability to add tabs to your bank which allow fast access to tags.",
|
||||||
|
position = 1
|
||||||
|
)
|
||||||
|
default boolean tabs()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ConfigItem(
|
||||||
|
keyName = "position",
|
||||||
|
name = "",
|
||||||
|
description = "",
|
||||||
|
hidden = true
|
||||||
|
)
|
||||||
|
default int position()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ConfigItem(
|
||||||
|
keyName = "position",
|
||||||
|
name = "",
|
||||||
|
description = ""
|
||||||
|
)
|
||||||
|
void position(int idx);
|
||||||
|
}
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2018, Adam <Adam@sigterm.info>
|
* Copyright (c) 2018, Adam <Adam@sigterm.info>
|
||||||
|
* Copyright (c) 2018, Ron Young <https://github.com/raiyni>
|
||||||
|
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@@ -24,9 +26,12 @@
|
|||||||
*/
|
*/
|
||||||
package net.runelite.client.plugins.banktags;
|
package net.runelite.client.plugins.banktags;
|
||||||
|
|
||||||
|
import com.google.common.base.Joiner;
|
||||||
|
import com.google.common.base.Splitter;
|
||||||
import com.google.common.eventbus.Subscribe;
|
import com.google.common.eventbus.Subscribe;
|
||||||
|
import com.google.inject.Provides;
|
||||||
|
import java.awt.event.MouseWheelEvent;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import net.runelite.api.Client;
|
import net.runelite.api.Client;
|
||||||
import net.runelite.api.InventoryID;
|
import net.runelite.api.InventoryID;
|
||||||
@@ -35,86 +40,100 @@ import net.runelite.api.ItemComposition;
|
|||||||
import net.runelite.api.ItemContainer;
|
import net.runelite.api.ItemContainer;
|
||||||
import net.runelite.api.MenuAction;
|
import net.runelite.api.MenuAction;
|
||||||
import net.runelite.api.MenuEntry;
|
import net.runelite.api.MenuEntry;
|
||||||
|
import net.runelite.api.events.ConfigChanged;
|
||||||
|
import net.runelite.api.events.DraggingWidgetChanged;
|
||||||
|
import net.runelite.api.events.GameTick;
|
||||||
import net.runelite.api.events.MenuEntryAdded;
|
import net.runelite.api.events.MenuEntryAdded;
|
||||||
import net.runelite.api.events.MenuOptionClicked;
|
import net.runelite.api.events.MenuOptionClicked;
|
||||||
import net.runelite.api.events.ScriptCallbackEvent;
|
import net.runelite.api.events.ScriptCallbackEvent;
|
||||||
|
import net.runelite.api.events.WidgetLoaded;
|
||||||
import net.runelite.api.widgets.Widget;
|
import net.runelite.api.widgets.Widget;
|
||||||
|
import net.runelite.api.widgets.WidgetID;
|
||||||
import net.runelite.api.widgets.WidgetInfo;
|
import net.runelite.api.widgets.WidgetInfo;
|
||||||
|
import net.runelite.client.callback.ClientThread;
|
||||||
import net.runelite.client.config.ConfigManager;
|
import net.runelite.client.config.ConfigManager;
|
||||||
import net.runelite.client.game.ChatboxInputManager;
|
import net.runelite.client.game.ChatboxInputManager;
|
||||||
import net.runelite.client.game.ItemManager;
|
import net.runelite.client.game.ItemManager;
|
||||||
|
import net.runelite.client.input.MouseManager;
|
||||||
|
import net.runelite.client.input.MouseWheelListener;
|
||||||
import net.runelite.client.plugins.Plugin;
|
import net.runelite.client.plugins.Plugin;
|
||||||
import net.runelite.client.plugins.PluginDescriptor;
|
import net.runelite.client.plugins.PluginDescriptor;
|
||||||
|
import net.runelite.client.plugins.banktags.tabs.TabInterface;
|
||||||
|
import net.runelite.client.plugins.banktags.tabs.TabSprites;
|
||||||
|
|
||||||
@PluginDescriptor(
|
@PluginDescriptor(
|
||||||
name = "Bank Tags",
|
name = "Bank Tags",
|
||||||
description = "Enable tagging of bank items and searching of bank tags",
|
description = "Enable tagging of bank items and searching of bank tags",
|
||||||
tags = {"searching", "tagging"}
|
tags = {"searching", "tagging"}
|
||||||
)
|
)
|
||||||
public class BankTagsPlugin extends Plugin
|
public class BankTagsPlugin extends Plugin implements MouseWheelListener
|
||||||
{
|
{
|
||||||
private static final String CONFIG_GROUP = "banktags";
|
public static final Splitter SPLITTER = Splitter.on(",").omitEmptyStrings().trimResults();
|
||||||
|
public static final Joiner JOINER = Joiner.on(",").skipNulls();
|
||||||
private static final String ITEM_KEY_PREFIX = "item_";
|
public static final String CONFIG_GROUP = "banktags";
|
||||||
|
public static final String TAG_SEARCH = "tag:";
|
||||||
|
public static final String EDIT_TAGS_MENU_OPTION = "Edit-tags";
|
||||||
|
public static final String ICON_SEARCH = "icon_";
|
||||||
|
|
||||||
private static final String SEARCH_BANK_INPUT_TEXT =
|
private static final String SEARCH_BANK_INPUT_TEXT =
|
||||||
"Show items whose names or tags contain the following text:<br>" +
|
"Show items whose names or tags contain the following text:<br>" +
|
||||||
"(To show only tagged items, start your search with 'tag:')";
|
"(To show only tagged items, start your search with 'tag:')";
|
||||||
|
|
||||||
private static final String SEARCH_BANK_INPUT_TEXT_FOUND =
|
private static final String SEARCH_BANK_INPUT_TEXT_FOUND =
|
||||||
"Show items whose names or tags contain the following text: (%d found)<br>" +
|
"Show items whose names or tags contain the following text: (%d found)<br>" +
|
||||||
"(To show only tagged items, start your search with 'tag:')";
|
"(To show only tagged items, start your search with 'tag:')";
|
||||||
|
|
||||||
private static final String TAG_SEARCH = "tag:";
|
|
||||||
|
|
||||||
private static final String EDIT_TAGS_MENU_OPTION = "Edit-tags";
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private Client client;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private ItemManager itemManager;
|
private ItemManager itemManager;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private ConfigManager configManager;
|
private Client client;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private ClientThread clientThread;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private ChatboxInputManager chatboxInputManager;
|
private ChatboxInputManager chatboxInputManager;
|
||||||
|
|
||||||
private String getTags(int itemId)
|
@Inject
|
||||||
|
private MouseManager mouseManager;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private BankTagsConfig config;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private TagManager tagManager;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private TabInterface tabInterface;
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
BankTagsConfig getConfig(ConfigManager configManager)
|
||||||
{
|
{
|
||||||
String config = configManager.getConfiguration(CONFIG_GROUP, ITEM_KEY_PREFIX + itemId);
|
return configManager.getConfig(BankTagsConfig.class);
|
||||||
if (config == null)
|
|
||||||
{
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
return config;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setTags(int itemId, String tags)
|
@Override
|
||||||
|
public void startUp()
|
||||||
{
|
{
|
||||||
if (tags == null || tags.isEmpty())
|
mouseManager.registerMouseWheelListener(this);
|
||||||
{
|
clientThread.invokeLater(tabInterface::init);
|
||||||
configManager.unsetConfiguration(CONFIG_GROUP, ITEM_KEY_PREFIX + itemId);
|
client.getSpriteOverrides().putAll(TabSprites.toMap(client));
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
configManager.setConfiguration(CONFIG_GROUP, ITEM_KEY_PREFIX + itemId, tags);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getTagCount(int itemId)
|
@Override
|
||||||
|
public void shutDown()
|
||||||
{
|
{
|
||||||
String tags = getTags(itemId);
|
mouseManager.unregisterMouseWheelListener(this);
|
||||||
if (tags.length() > 0)
|
clientThread.invokeLater(tabInterface::destroy);
|
||||||
|
|
||||||
|
for (TabSprites value : TabSprites.values())
|
||||||
{
|
{
|
||||||
return tags.split(",").length;
|
client.getSpriteOverrides().remove(value.getSpriteId());
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onScriptEvent(ScriptCallbackEvent event)
|
public void onScriptCallbackEvent(ScriptCallbackEvent event)
|
||||||
{
|
{
|
||||||
String eventName = event.getEventName();
|
String eventName = event.getEventName();
|
||||||
|
|
||||||
@@ -141,29 +160,15 @@ public class BankTagsPlugin extends Plugin
|
|||||||
case "bankSearchFilter":
|
case "bankSearchFilter":
|
||||||
int itemId = itemManager.canonicalize(intStack[intStackSize - 1]);
|
int itemId = itemManager.canonicalize(intStack[intStackSize - 1]);
|
||||||
String itemName = stringStack[stringStackSize - 2];
|
String itemName = stringStack[stringStackSize - 2];
|
||||||
String searchInput = stringStack[stringStackSize - 1];
|
String search = stringStack[stringStackSize - 1];
|
||||||
|
|
||||||
String tagsConfig = configManager.getConfiguration(CONFIG_GROUP, ITEM_KEY_PREFIX + itemId);
|
boolean tagSearch = search.startsWith(TAG_SEARCH);
|
||||||
if (tagsConfig == null || tagsConfig.length() == 0)
|
|
||||||
{
|
|
||||||
intStack[intStackSize - 2] = itemName.contains(searchInput) ? 1 : 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean tagSearch = searchInput.startsWith(TAG_SEARCH);
|
|
||||||
String search;
|
|
||||||
if (tagSearch)
|
if (tagSearch)
|
||||||
{
|
{
|
||||||
search = searchInput.substring(TAG_SEARCH.length()).trim();
|
search = search.substring(TAG_SEARCH.length()).trim();
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
search = searchInput;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> tags = Arrays.asList(tagsConfig.toLowerCase().split(","));
|
if (tagManager.findTag(itemId, search))
|
||||||
|
|
||||||
if (tags.stream().anyMatch(tag -> tag.contains(search.toLowerCase())))
|
|
||||||
{
|
{
|
||||||
// return true
|
// return true
|
||||||
intStack[intStackSize - 2] = 1;
|
intStack[intStackSize - 2] = 1;
|
||||||
@@ -173,54 +178,42 @@ public class BankTagsPlugin extends Plugin
|
|||||||
intStack[intStackSize - 2] = itemName.contains(search) ? 1 : 0;
|
intStack[intStackSize - 2] = itemName.contains(search) ? 1 : 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case "getSearchingTagTab":
|
||||||
|
intStack[intStackSize - 1] = tabInterface.isActive() ? 1 : 0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onMenuEntryAdded(MenuEntryAdded event)
|
public void onMenuEntryAdded(MenuEntryAdded event)
|
||||||
{
|
{
|
||||||
int widgetId = event.getActionParam1();
|
|
||||||
if (widgetId != WidgetInfo.BANK_ITEM_CONTAINER.getId())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int index = event.getActionParam0();
|
|
||||||
if (index < 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Examine is the only guaranteed menuop to be added
|
|
||||||
if (!"Examine".equals(event.getOption()))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget container = client.getWidget(WidgetInfo.BANK_ITEM_CONTAINER);
|
|
||||||
Widget item = container.getChild(index);
|
|
||||||
int itemID = itemManager.canonicalize(item.getItemId());
|
|
||||||
|
|
||||||
String text = EDIT_TAGS_MENU_OPTION;
|
|
||||||
|
|
||||||
int tagCount = getTagCount(itemID);
|
|
||||||
if (tagCount > 0)
|
|
||||||
{
|
|
||||||
text += " (" + tagCount + ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
MenuEntry editTags = new MenuEntry();
|
|
||||||
editTags.setParam0(event.getActionParam0());
|
|
||||||
editTags.setParam1(event.getActionParam1());
|
|
||||||
editTags.setTarget(event.getTarget());
|
|
||||||
editTags.setOption(text);
|
|
||||||
editTags.setType(MenuAction.RUNELITE.getId());
|
|
||||||
editTags.setIdentifier(event.getIdentifier());
|
|
||||||
|
|
||||||
MenuEntry[] entries = client.getMenuEntries();
|
MenuEntry[] entries = client.getMenuEntries();
|
||||||
entries = Arrays.copyOf(entries, entries.length + 1);
|
|
||||||
entries[entries.length - 1] = editTags;
|
if (event.getActionParam1() == WidgetInfo.BANK_ITEM_CONTAINER.getId()
|
||||||
client.setMenuEntries(entries);
|
&& event.getOption().equals("Examine"))
|
||||||
|
{
|
||||||
|
Widget container = client.getWidget(WidgetInfo.BANK_ITEM_CONTAINER);
|
||||||
|
Widget item = container.getChild(event.getActionParam0());
|
||||||
|
int itemID = itemManager.canonicalize(item.getItemId());
|
||||||
|
String text = EDIT_TAGS_MENU_OPTION;
|
||||||
|
int tagCount = tagManager.getTags(itemID).size();
|
||||||
|
if (tagCount > 0)
|
||||||
|
{
|
||||||
|
text += " (" + tagCount + ")";
|
||||||
|
}
|
||||||
|
MenuEntry editTags = new MenuEntry();
|
||||||
|
editTags.setParam0(event.getActionParam0());
|
||||||
|
editTags.setParam1(event.getActionParam1());
|
||||||
|
editTags.setTarget(event.getTarget());
|
||||||
|
editTags.setOption(text);
|
||||||
|
editTags.setType(MenuAction.RUNELITE.getId());
|
||||||
|
editTags.setIdentifier(event.getIdentifier());
|
||||||
|
entries = Arrays.copyOf(entries, entries.length + 1);
|
||||||
|
entries[entries.length - 1] = editTags;
|
||||||
|
client.setMenuEntries(entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
tabInterface.handleAdd(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
@@ -249,11 +242,9 @@ public class BankTagsPlugin extends Plugin
|
|||||||
}
|
}
|
||||||
|
|
||||||
int itemId = itemManager.canonicalize(item.getId());
|
int itemId = itemManager.canonicalize(item.getId());
|
||||||
|
|
||||||
ItemComposition itemComposition = itemManager.getItemComposition(itemId);
|
ItemComposition itemComposition = itemManager.getItemComposition(itemId);
|
||||||
String itemName = itemComposition.getName();
|
String itemName = itemComposition.getName();
|
||||||
|
String initialValue = tagManager.getTagString(itemId);
|
||||||
String initialValue = getTags(itemId);
|
|
||||||
|
|
||||||
chatboxInputManager.openInputWindow(itemName + " tags:", initialValue, (newTags) ->
|
chatboxInputManager.openInputWindow(itemName + " tags:", initialValue, (newTags) ->
|
||||||
{
|
{
|
||||||
@@ -261,9 +252,57 @@ public class BankTagsPlugin extends Plugin
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setTags(itemId, newTags);
|
|
||||||
|
tagManager.setTagString(itemId, newTags);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tabInterface.handleClick(event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onConfigChanged(ConfigChanged configChanged)
|
||||||
|
{
|
||||||
|
if (configChanged.getGroup().equals("banktags") && configChanged.getKey().equals("useTabs"))
|
||||||
|
{
|
||||||
|
if (config.tabs())
|
||||||
|
{
|
||||||
|
clientThread.invokeLater(tabInterface::init);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
clientThread.invokeLater(tabInterface::destroy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onGameTick(GameTick event)
|
||||||
|
{
|
||||||
|
tabInterface.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onDraggingWidgetChanged(DraggingWidgetChanged event)
|
||||||
|
{
|
||||||
|
tabInterface.handleDrag(event.isDraggingWidget());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onWidgetLoaded(WidgetLoaded event)
|
||||||
|
{
|
||||||
|
if (event.getGroupId() == WidgetID.BANK_GROUP_ID)
|
||||||
|
{
|
||||||
|
tabInterface.init();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MouseWheelEvent mouseWheelMoved(MouseWheelEvent event)
|
||||||
|
{
|
||||||
|
clientThread.invokeLater(() -> tabInterface.handleWheel(event));
|
||||||
|
return event;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
|
||||||
|
* Copyright (c) 2018, Ron Young <https://github.com/raiyni>
|
||||||
|
* 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.banktags;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
import net.runelite.client.config.ConfigManager;
|
||||||
|
import static net.runelite.client.plugins.banktags.BankTagsPlugin.CONFIG_GROUP;
|
||||||
|
import static net.runelite.client.plugins.banktags.BankTagsPlugin.JOINER;
|
||||||
|
import static net.runelite.client.plugins.banktags.BankTagsPlugin.SPLITTER;
|
||||||
|
import net.runelite.client.util.Text;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class TagManager
|
||||||
|
{
|
||||||
|
private static final String ITEM_KEY_PREFIX = "item_";
|
||||||
|
private final ConfigManager configManager;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private TagManager(final ConfigManager configManager)
|
||||||
|
{
|
||||||
|
this.configManager = configManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTagString(int itemId)
|
||||||
|
{
|
||||||
|
String config = configManager.getConfiguration(CONFIG_GROUP, ITEM_KEY_PREFIX + itemId);
|
||||||
|
if (config == null)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
Collection<String> getTags(int itemId)
|
||||||
|
{
|
||||||
|
return new LinkedHashSet<>(SPLITTER.splitToList(getTagString(itemId).toLowerCase()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTagString(int itemId, String tags)
|
||||||
|
{
|
||||||
|
if (Strings.isNullOrEmpty(tags))
|
||||||
|
{
|
||||||
|
configManager.unsetConfiguration(CONFIG_GROUP, ITEM_KEY_PREFIX + itemId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
configManager.setConfiguration(CONFIG_GROUP, ITEM_KEY_PREFIX + itemId, tags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addTag(int itemId, String tag)
|
||||||
|
{
|
||||||
|
final Collection<String> tags = getTags(itemId);
|
||||||
|
if (tags.add(Text.standardize(tag)))
|
||||||
|
{
|
||||||
|
setTags(itemId, tags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setTags(int itemId, Collection<String> tags)
|
||||||
|
{
|
||||||
|
setTagString(itemId, JOINER.join(tags));
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean findTag(int itemId, String search)
|
||||||
|
{
|
||||||
|
return getTags(itemId).stream().anyMatch(tag -> tag.contains(Text.standardize(search)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeTag(String tag)
|
||||||
|
{
|
||||||
|
final String prefix = CONFIG_GROUP + "." + ITEM_KEY_PREFIX;
|
||||||
|
configManager.getConfigurationKeys(prefix).forEach(item -> removeTag(Integer.parseInt(item.replace(prefix, "")), tag));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeTag(int itemId, String tag)
|
||||||
|
{
|
||||||
|
final Collection<String> tags = getTags(itemId);
|
||||||
|
if (tags.remove(Text.standardize(tag)))
|
||||||
|
{
|
||||||
|
setTags(itemId, tags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,792 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
|
||||||
|
* Copyright (c) 2018, Ron Young <https://github.com/raiyni>
|
||||||
|
* 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.banktags.tabs;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Rectangle;
|
||||||
|
import java.awt.event.MouseWheelEvent;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
import lombok.Getter;
|
||||||
|
import net.runelite.api.Client;
|
||||||
|
import net.runelite.api.InventoryID;
|
||||||
|
import net.runelite.api.Item;
|
||||||
|
import net.runelite.api.ItemComposition;
|
||||||
|
import net.runelite.api.ItemContainer;
|
||||||
|
import net.runelite.api.MenuAction;
|
||||||
|
import net.runelite.api.MenuEntry;
|
||||||
|
import net.runelite.api.Point;
|
||||||
|
import net.runelite.api.ScriptID;
|
||||||
|
import net.runelite.api.SoundEffectID;
|
||||||
|
import net.runelite.api.SpriteID;
|
||||||
|
import net.runelite.api.VarClientInt;
|
||||||
|
import net.runelite.api.VarClientStr;
|
||||||
|
import net.runelite.api.Varbits;
|
||||||
|
import net.runelite.api.WidgetType;
|
||||||
|
import net.runelite.api.events.MenuEntryAdded;
|
||||||
|
import net.runelite.api.events.MenuOptionClicked;
|
||||||
|
import net.runelite.api.vars.InputType;
|
||||||
|
import net.runelite.api.widgets.Widget;
|
||||||
|
import net.runelite.api.widgets.WidgetConfig;
|
||||||
|
import net.runelite.api.widgets.WidgetInfo;
|
||||||
|
import net.runelite.client.callback.ClientThread;
|
||||||
|
import net.runelite.client.config.ConfigManager;
|
||||||
|
import net.runelite.client.game.ChatboxInputManager;
|
||||||
|
import net.runelite.client.game.ItemManager;
|
||||||
|
import net.runelite.client.plugins.banktags.BankTagsConfig;
|
||||||
|
import static net.runelite.client.plugins.banktags.BankTagsPlugin.CONFIG_GROUP;
|
||||||
|
import static net.runelite.client.plugins.banktags.BankTagsPlugin.ICON_SEARCH;
|
||||||
|
import static net.runelite.client.plugins.banktags.BankTagsPlugin.TAG_SEARCH;
|
||||||
|
import net.runelite.client.plugins.banktags.TagManager;
|
||||||
|
import net.runelite.client.util.ColorUtil;
|
||||||
|
import net.runelite.client.util.Text;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class TabInterface
|
||||||
|
{
|
||||||
|
private static final Color HILIGHT_COLOR = Color.decode("#ff9040");
|
||||||
|
private static final String SCROLL_UP = "Scroll up";
|
||||||
|
private static final String SCROLL_DOWN = "Scroll down";
|
||||||
|
private static final String NEW_TAB = "New tag tab";
|
||||||
|
private static final String REMOVE_TAB = "Delete tag tab";
|
||||||
|
private static final String VIEW_TAB = "View tag tab";
|
||||||
|
private static final String CHANGE_ICON = "Change icon";
|
||||||
|
private static final String REMOVE_TAG = "Remove-tag";
|
||||||
|
private static final int TAB_HEIGHT = 40;
|
||||||
|
private static final int TAB_WIDTH = 39;
|
||||||
|
private static final int BUTTON_HEIGHT = 20;
|
||||||
|
private static final int MARGIN = 1;
|
||||||
|
private static final int SCROLL_TICK = 500;
|
||||||
|
|
||||||
|
// Widget indexes for searching
|
||||||
|
private static final int INNER_CONTAINER_IDX = 2;
|
||||||
|
private static final int SETTINGS_IDX = 4;
|
||||||
|
private static final int ITEM_CONTAINER_IDX = 7;
|
||||||
|
private static final int SCROLLBAR_IDX = 8;
|
||||||
|
private static final int BOTTOM_BAR_IDX = 9;
|
||||||
|
private static final int SEARCH_BUTTON_BACKGROUND_IDX = 15;
|
||||||
|
private static final int TITLE_BAR_IDX = 16;
|
||||||
|
private static final int ITEM_COUNT_IDX = 17;
|
||||||
|
private static final int TAB_BAR_IDX = 18;
|
||||||
|
private static final int INCINERATOR_IDX = 19;
|
||||||
|
private static final int INCINERATOR_CONFIRM_IDX = 20;
|
||||||
|
private static final int HIDDEN_WIDGET_IDX = 21;
|
||||||
|
|
||||||
|
private final Client client;
|
||||||
|
private final ClientThread clientThread;
|
||||||
|
private final ItemManager itemManager;
|
||||||
|
private final ConfigManager configManager;
|
||||||
|
private final TagManager tagManager;
|
||||||
|
private final TabManager tabManager;
|
||||||
|
private final ChatboxInputManager chatboxInputManager;
|
||||||
|
private final BankTagsConfig config;
|
||||||
|
private final Rectangle bounds = new Rectangle();
|
||||||
|
private final Rectangle canvasBounds = new Rectangle();
|
||||||
|
|
||||||
|
private TagTab activeTab;
|
||||||
|
private int maxTabs;
|
||||||
|
private int currentTabIndex;
|
||||||
|
private TagTab iconToSet = null;
|
||||||
|
private Instant startScroll = Instant.now();
|
||||||
|
private Object[] widgetIds;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private Widget upButton;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private Widget downButton;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private Widget newTab;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private Widget parent;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private TabInterface(
|
||||||
|
final Client client,
|
||||||
|
final ClientThread clientThread,
|
||||||
|
final ItemManager itemManager,
|
||||||
|
final ConfigManager configManager,
|
||||||
|
final TagManager tagManager,
|
||||||
|
final TabManager tabManager,
|
||||||
|
final ChatboxInputManager chatboxInputManager,
|
||||||
|
final BankTagsConfig config)
|
||||||
|
{
|
||||||
|
this.client = client;
|
||||||
|
this.clientThread = clientThread;
|
||||||
|
this.itemManager = itemManager;
|
||||||
|
this.configManager = configManager;
|
||||||
|
this.tagManager = tagManager;
|
||||||
|
this.tabManager = tabManager;
|
||||||
|
this.chatboxInputManager = chatboxInputManager;
|
||||||
|
this.config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isActive()
|
||||||
|
{
|
||||||
|
return activeTab != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init()
|
||||||
|
{
|
||||||
|
if (isHidden())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget bankContainer = client.getWidget(WidgetInfo.BANK_CONTAINER);
|
||||||
|
widgetIds = bankContainer.getOnLoadListener();
|
||||||
|
|
||||||
|
currentTabIndex = config.position();
|
||||||
|
parent = client.getWidget(WidgetInfo.BANK_CONTENT_CONTAINER);
|
||||||
|
|
||||||
|
updateBounds();
|
||||||
|
|
||||||
|
upButton = createGraphic("", TabSprites.UP_ARROW.getSpriteId(), -1, TAB_WIDTH, BUTTON_HEIGHT, bounds.x, 0, true);
|
||||||
|
upButton.setAction(1, SCROLL_UP);
|
||||||
|
int clickmask = upButton.getClickMask();
|
||||||
|
clickmask |= WidgetConfig.DRAG;
|
||||||
|
upButton.setClickMask(clickmask);
|
||||||
|
|
||||||
|
downButton = createGraphic("", TabSprites.DOWN_ARROW.getSpriteId(), -1, TAB_WIDTH, BUTTON_HEIGHT, bounds.x, 0, true);
|
||||||
|
downButton.setAction(1, SCROLL_DOWN);
|
||||||
|
clickmask = downButton.getClickMask();
|
||||||
|
clickmask |= WidgetConfig.DRAG;
|
||||||
|
downButton.setClickMask(clickmask);
|
||||||
|
|
||||||
|
newTab = createGraphic("", TabSprites.NEW_TAB.getSpriteId(), -1, TAB_WIDTH, 39, bounds.x, 0, true);
|
||||||
|
newTab.setAction(1, NEW_TAB);
|
||||||
|
|
||||||
|
tabManager.clear();
|
||||||
|
tabManager.getAllTabs().forEach(this::loadTab);
|
||||||
|
activateTab(null);
|
||||||
|
scrollTab(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void destroy()
|
||||||
|
{
|
||||||
|
activeTab = null;
|
||||||
|
currentTabIndex = 0;
|
||||||
|
maxTabs = 0;
|
||||||
|
parent = null;
|
||||||
|
|
||||||
|
if (upButton != null)
|
||||||
|
{
|
||||||
|
upButton.setHidden(true);
|
||||||
|
downButton.setHidden(true);
|
||||||
|
newTab.setHidden(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
tabManager.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update()
|
||||||
|
{
|
||||||
|
if (isHidden())
|
||||||
|
{
|
||||||
|
parent = null;
|
||||||
|
|
||||||
|
// If bank window was just hidden, update last active tab position
|
||||||
|
if (currentTabIndex != config.position())
|
||||||
|
{
|
||||||
|
config.position(currentTabIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String str = client.getVar(VarClientStr.INPUT_TEXT);
|
||||||
|
|
||||||
|
if (Strings.isNullOrEmpty(str))
|
||||||
|
{
|
||||||
|
str = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget bankTitle = client.getWidget(WidgetInfo.BANK_TITLE_BAR);
|
||||||
|
if (bankTitle != null && !bankTitle.isHidden())
|
||||||
|
{
|
||||||
|
str = bankTitle.getText().replaceFirst("Showing items: ", "");
|
||||||
|
|
||||||
|
if (str.startsWith("Tab "))
|
||||||
|
{
|
||||||
|
str = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
str = Text.standardize(str);
|
||||||
|
|
||||||
|
if (str.startsWith("tag:"))
|
||||||
|
{
|
||||||
|
str = str.substring(4);
|
||||||
|
activateTab(tabManager.find(str));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
activateTab(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateBounds();
|
||||||
|
scrollTab(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleWheel(final MouseWheelEvent event)
|
||||||
|
{
|
||||||
|
if (isHidden())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (canvasBounds.contains(event.getPoint()))
|
||||||
|
{
|
||||||
|
scrollTab(event.getWheelRotation());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleAdd(MenuEntryAdded event)
|
||||||
|
{
|
||||||
|
if (isHidden())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuEntry[] entries = client.getMenuEntries();
|
||||||
|
MenuEntry entry = entries[entries.length - 1];
|
||||||
|
|
||||||
|
if (activeTab != null
|
||||||
|
&& event.getActionParam1() == WidgetInfo.BANK_ITEM_CONTAINER.getId()
|
||||||
|
&& event.getOption().equals("Examine"))
|
||||||
|
{
|
||||||
|
MenuEntry removeTag = new MenuEntry();
|
||||||
|
removeTag.setParam0(event.getActionParam0());
|
||||||
|
removeTag.setParam1(event.getActionParam1());
|
||||||
|
removeTag.setTarget(event.getTarget());
|
||||||
|
removeTag.setOption(REMOVE_TAG + " (" + activeTab.getTag() + ")");
|
||||||
|
removeTag.setType(MenuAction.RUNELITE.getId());
|
||||||
|
removeTag.setIdentifier(event.getIdentifier());
|
||||||
|
entries = Arrays.copyOf(entries, entries.length + 1);
|
||||||
|
entries[entries.length - 1] = removeTag;
|
||||||
|
client.setMenuEntries(entries);
|
||||||
|
}
|
||||||
|
else if (iconToSet != null && (entry.getOption().startsWith("Withdraw-") || entry.getOption().equals("Release")))
|
||||||
|
{
|
||||||
|
// TODO: Do not replace every withdraw option with change icon option
|
||||||
|
entry.setOption(CHANGE_ICON + " (" + iconToSet.getTag() + ")");
|
||||||
|
client.setMenuEntries(entries);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleClick(MenuOptionClicked event)
|
||||||
|
{
|
||||||
|
if (isHidden())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iconToSet != null)
|
||||||
|
{
|
||||||
|
if (event.getMenuOption().startsWith(CHANGE_ICON))
|
||||||
|
{
|
||||||
|
ItemComposition item = getItem(event.getActionParam());
|
||||||
|
int itemId = itemManager.canonicalize(item.getId());
|
||||||
|
iconToSet.setIconItemId(itemId);
|
||||||
|
iconToSet.getIcon().setItemId(itemId);
|
||||||
|
configManager.setConfiguration(CONFIG_GROUP, ICON_SEARCH + iconToSet.getTag(), itemId + "");
|
||||||
|
event.consume();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset icon selection even when we do not clicked item with icon
|
||||||
|
iconToSet = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (activeTab != null
|
||||||
|
&& event.getMenuOption().equals("Search")
|
||||||
|
&& client.getWidget(WidgetInfo.BANK_SEARCH_BUTTON_BACKGROUND).getSpriteId() != SpriteID.EQUIPMENT_SLOT_SELECTED)
|
||||||
|
{
|
||||||
|
activateTab(null);
|
||||||
|
// This ensures that when clicking Search when tab is selected, the search input is opened rather
|
||||||
|
// than client trying to close it first
|
||||||
|
client.setVar(VarClientStr.INPUT_TEXT, "");
|
||||||
|
client.setVar(VarClientInt.INPUT_TYPE, 0);
|
||||||
|
}
|
||||||
|
else if (activeTab != null
|
||||||
|
&& event.getMenuOption().startsWith("View tab"))
|
||||||
|
{
|
||||||
|
activateTab(null);
|
||||||
|
}
|
||||||
|
else if (activeTab != null
|
||||||
|
&& event.getWidgetId() == WidgetInfo.BANK_ITEM_CONTAINER.getId()
|
||||||
|
&& event.getMenuAction() == MenuAction.RUNELITE
|
||||||
|
&& event.getMenuOption().startsWith(REMOVE_TAG))
|
||||||
|
{
|
||||||
|
// Add "remove" menu entry to all items in bank while tab is selected
|
||||||
|
event.consume();
|
||||||
|
final ItemComposition item = getItem(event.getActionParam());
|
||||||
|
final int itemId = itemManager.canonicalize(item.getId());
|
||||||
|
tagManager.removeTag(itemId, activeTab.getTag());
|
||||||
|
doSearch(InputType.SEARCH, TAG_SEARCH + activeTab.getTag());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (event.getMenuOption())
|
||||||
|
{
|
||||||
|
case SCROLL_UP:
|
||||||
|
event.consume();
|
||||||
|
scrollTab(-1);
|
||||||
|
break;
|
||||||
|
case SCROLL_DOWN:
|
||||||
|
event.consume();
|
||||||
|
scrollTab(1);
|
||||||
|
break;
|
||||||
|
case CHANGE_ICON:
|
||||||
|
event.consume();
|
||||||
|
iconToSet = tabManager.find(Text.removeTags(event.getMenuTarget()));
|
||||||
|
break;
|
||||||
|
case VIEW_TAB:
|
||||||
|
event.consume();
|
||||||
|
client.setVarbitValue(client.getVarps(), Varbits.CURRENT_BANK_TAB.getId(), 0);
|
||||||
|
Widget[] children = parent.getDynamicChildren();
|
||||||
|
Widget clicked = children[event.getActionParam()];
|
||||||
|
|
||||||
|
TagTab tab = tabManager.find(Text.removeTags(clicked.getName()));
|
||||||
|
|
||||||
|
if (tab.equals(activeTab))
|
||||||
|
{
|
||||||
|
resetSearch();
|
||||||
|
|
||||||
|
clientThread.invokeLater(() -> client.runScript(ScriptID.CLOSE_CHATBOX_INPUT));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
openTag(TAG_SEARCH + Text.removeTags(clicked.getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
client.playSoundEffect(SoundEffectID.UI_BOOP);
|
||||||
|
|
||||||
|
break;
|
||||||
|
case NEW_TAB:
|
||||||
|
event.consume();
|
||||||
|
chatboxInputManager.openInputWindow("Tag Name", "", (tagName) ->
|
||||||
|
{
|
||||||
|
if (!Strings.isNullOrEmpty(tagName))
|
||||||
|
{
|
||||||
|
loadTab(tagName);
|
||||||
|
tabManager.save();
|
||||||
|
scrollTab(0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case REMOVE_TAB:
|
||||||
|
event.consume();
|
||||||
|
String target = Text.standardize(event.getMenuTarget());
|
||||||
|
|
||||||
|
// TODO: Replace this number input selection with actual in-game select input
|
||||||
|
chatboxInputManager.openInputWindow(
|
||||||
|
"1. Delete tab " + target + " and tag from all items<br>" +
|
||||||
|
"2. Delete tab " + target + "<br>" +
|
||||||
|
"3. Cancel", "", (response) ->
|
||||||
|
{
|
||||||
|
switch (response)
|
||||||
|
{
|
||||||
|
case "1":
|
||||||
|
tagManager.removeTag(target);
|
||||||
|
if (activeTab != null && activeTab.getTag().equals(target))
|
||||||
|
{
|
||||||
|
resetSearch();
|
||||||
|
}
|
||||||
|
case "2":
|
||||||
|
deleteTab(target);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleDrag(boolean isDragging)
|
||||||
|
{
|
||||||
|
if (isHidden())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget draggedOn = client.getDraggedOnWidget();
|
||||||
|
Widget draggedWidget = client.getDraggedWidget();
|
||||||
|
|
||||||
|
if (!isDragging || draggedOn == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// is dragging widget and mouse button released
|
||||||
|
if (client.getMouseCurrentButton() == 0)
|
||||||
|
{
|
||||||
|
if (draggedWidget.getItemId() > 0 && draggedWidget.getId() != parent.getId())
|
||||||
|
{
|
||||||
|
// Tag an item dragged on a tag tab
|
||||||
|
if (draggedOn.getId() == parent.getId())
|
||||||
|
{
|
||||||
|
int itemId = itemManager.canonicalize(draggedWidget.getItemId());
|
||||||
|
tagManager.addTag(itemId, draggedOn.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (parent.getId() == draggedOn.getId() && parent.getId() == draggedWidget.getId())
|
||||||
|
{
|
||||||
|
// Reorder tag tabs
|
||||||
|
if (!Strings.isNullOrEmpty(draggedOn.getName()))
|
||||||
|
{
|
||||||
|
tabManager.move(draggedWidget.getName(), draggedOn.getName());
|
||||||
|
tabManager.save();
|
||||||
|
updateTabs();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (draggedWidget.getItemId() > 0)
|
||||||
|
{
|
||||||
|
MenuEntry[] entries = client.getMenuEntries();
|
||||||
|
|
||||||
|
if (entries.length > 0)
|
||||||
|
{
|
||||||
|
MenuEntry entry = entries[entries.length - 1];
|
||||||
|
|
||||||
|
if (draggedWidget.getItemId() > 0 && entry.getOption().equals(VIEW_TAB) && draggedOn.getId() != draggedWidget.getId())
|
||||||
|
{
|
||||||
|
entry.setOption(TAG_SEARCH + Text.removeTags(entry.getTarget()));
|
||||||
|
entry.setTarget(draggedWidget.getName());
|
||||||
|
client.setMenuEntries(entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry.getOption().equals(SCROLL_UP))
|
||||||
|
{
|
||||||
|
scrollTick(-1);
|
||||||
|
}
|
||||||
|
else if (entry.getOption().equals(SCROLL_DOWN))
|
||||||
|
{
|
||||||
|
scrollTick(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resetSearch()
|
||||||
|
{
|
||||||
|
doSearch(InputType.NONE, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isHidden()
|
||||||
|
{
|
||||||
|
Widget widget = client.getWidget(WidgetInfo.BANK_CONTAINER);
|
||||||
|
return !config.tabs() || widget == null || widget.isHidden();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadTab(String tag)
|
||||||
|
{
|
||||||
|
TagTab tagTab = tabManager.load(tag);
|
||||||
|
|
||||||
|
if (tagTab.getBackground() == null)
|
||||||
|
{
|
||||||
|
Widget btn = createGraphic(ColorUtil.wrapWithColorTag(tagTab.getTag(), HILIGHT_COLOR), TabSprites.TAB_BACKGROUND.getSpriteId(), -1, TAB_WIDTH, TAB_HEIGHT, bounds.x, 1, true);
|
||||||
|
btn.setAction(1, VIEW_TAB);
|
||||||
|
btn.setAction(2, CHANGE_ICON);
|
||||||
|
btn.setAction(3, REMOVE_TAB);
|
||||||
|
tagTab.setBackground(btn);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tagTab.getIcon() == null)
|
||||||
|
{
|
||||||
|
Widget icon = createGraphic(ColorUtil.wrapWithColorTag(tagTab.getTag(), HILIGHT_COLOR), -1, tagTab.getIconItemId(), 36, 32, bounds.x + 3, 1, false);
|
||||||
|
int clickmask = icon.getClickMask();
|
||||||
|
clickmask |= WidgetConfig.DRAG;
|
||||||
|
clickmask |= WidgetConfig.DRAG_ON;
|
||||||
|
icon.setClickMask(clickmask);
|
||||||
|
icon.setDragDeadTime(5);
|
||||||
|
icon.setDragDeadZone(5);
|
||||||
|
tagTab.setIcon(icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
tabManager.add(tagTab);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void deleteTab(String tag)
|
||||||
|
{
|
||||||
|
if (activeTab != null && activeTab.getTag().equals(tag))
|
||||||
|
{
|
||||||
|
doSearch(InputType.SEARCH, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
tabManager.remove(tag);
|
||||||
|
configManager.unsetConfiguration(CONFIG_GROUP, ICON_SEARCH + tag);
|
||||||
|
tabManager.save();
|
||||||
|
|
||||||
|
updateBounds();
|
||||||
|
scrollTab(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void scrollTick(int direction)
|
||||||
|
{
|
||||||
|
// This ensures that dragging on scroll buttons do not scrolls too fast
|
||||||
|
if (startScroll.until(Instant.now(), ChronoUnit.MILLIS) >= SCROLL_TICK)
|
||||||
|
{
|
||||||
|
startScroll = Instant.now();
|
||||||
|
scrollTab(direction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void scrollTab(int direction)
|
||||||
|
{
|
||||||
|
maxTabs = (bounds.height - BUTTON_HEIGHT * 2 - MARGIN * 2) / TAB_HEIGHT;
|
||||||
|
|
||||||
|
// prevent running into the incinerator
|
||||||
|
while (bounds.y + maxTabs * TAB_HEIGHT + MARGIN * maxTabs + BUTTON_HEIGHT * 2 + MARGIN > bounds.y + bounds.height)
|
||||||
|
{
|
||||||
|
--maxTabs;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentTabIndex + direction >= tabManager.size() || currentTabIndex + direction < 0)
|
||||||
|
{
|
||||||
|
currentTabIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((tabManager.size() - (currentTabIndex + direction) >= maxTabs) && (currentTabIndex + direction > -1))
|
||||||
|
{
|
||||||
|
currentTabIndex += direction;
|
||||||
|
}
|
||||||
|
else if (maxTabs < tabManager.size() && tabManager.size() - (currentTabIndex + direction) < maxTabs)
|
||||||
|
{
|
||||||
|
// Edge case when only 1 tab displays instead of up to maxTabs when one is deleted at the end of the list
|
||||||
|
currentTabIndex += direction;
|
||||||
|
scrollTab(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateTabs();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void activateTab(TagTab tagTab)
|
||||||
|
{
|
||||||
|
if (activeTab != null && activeTab.equals(tagTab))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (activeTab != null)
|
||||||
|
{
|
||||||
|
Widget tab = activeTab.getBackground();
|
||||||
|
tab.setSpriteId(TabSprites.TAB_BACKGROUND.getSpriteId());
|
||||||
|
tab.revalidate();
|
||||||
|
activeTab = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tagTab != null)
|
||||||
|
{
|
||||||
|
Widget tab = tagTab.getBackground();
|
||||||
|
tab.setSpriteId(TabSprites.TAB_BACKGROUND_ACTIVE.getSpriteId());
|
||||||
|
tab.revalidate();
|
||||||
|
activeTab = tagTab;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateBounds()
|
||||||
|
{
|
||||||
|
Widget itemContainer = client.getWidget(WidgetInfo.BANK_ITEM_CONTAINER);
|
||||||
|
if (itemContainer == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int height = itemContainer.getHeight();
|
||||||
|
|
||||||
|
// If player isn't using normal bank tabs
|
||||||
|
if (itemContainer.getRelativeY() == 0)
|
||||||
|
{
|
||||||
|
height -= (TAB_HEIGHT + MARGIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
bounds.setSize(TAB_WIDTH + MARGIN * 2, height);
|
||||||
|
bounds.setLocation(MARGIN, TAB_HEIGHT + MARGIN);
|
||||||
|
|
||||||
|
Widget incinerator = client.getWidget(WidgetInfo.BANK_INCINERATOR);
|
||||||
|
|
||||||
|
if (incinerator != null && !incinerator.isHidden())
|
||||||
|
{
|
||||||
|
// This is the required way to move incinerator, don't change it!
|
||||||
|
incinerator.setOriginalHeight(39);
|
||||||
|
incinerator.setOriginalWidth(48);
|
||||||
|
incinerator.setRelativeY(itemContainer.getHeight());
|
||||||
|
incinerator.revalidate();
|
||||||
|
|
||||||
|
Widget child = incinerator.getDynamicChildren()[0];
|
||||||
|
child.setHeight(39);
|
||||||
|
child.setWidth(48);
|
||||||
|
child.setType(WidgetType.GRAPHIC);
|
||||||
|
child.setSpriteId(TabSprites.INCINERATOR.getSpriteId());
|
||||||
|
|
||||||
|
bounds.setSize(TAB_WIDTH + MARGIN * 2, height - incinerator.getHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (upButton != null)
|
||||||
|
{
|
||||||
|
Point p = upButton.getCanvasLocation();
|
||||||
|
canvasBounds.setBounds(p.getX(), p.getY() + BUTTON_HEIGHT, bounds.width, maxTabs * TAB_HEIGHT + maxTabs * MARGIN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateTabs()
|
||||||
|
{
|
||||||
|
int y = bounds.y + MARGIN + BUTTON_HEIGHT;
|
||||||
|
|
||||||
|
if (maxTabs >= tabManager.size())
|
||||||
|
{
|
||||||
|
currentTabIndex = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
y -= (currentTabIndex * TAB_HEIGHT + currentTabIndex * MARGIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (TagTab tab : tabManager.getTabs())
|
||||||
|
{
|
||||||
|
updateWidget(tab.getBackground(), y);
|
||||||
|
updateWidget(tab.getIcon(), y + 4);
|
||||||
|
|
||||||
|
// Edge case where item icon is 1 pixel out of bounds
|
||||||
|
tab.getIcon().setHidden(tab.getBackground().isHidden());
|
||||||
|
|
||||||
|
// Keep item widget shown while drag scrolling
|
||||||
|
if (client.getDraggedWidget() == tab.getIcon())
|
||||||
|
{
|
||||||
|
tab.getIcon().setHidden(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
y += TAB_HEIGHT + MARGIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean hidden = !(tabManager.size() > 0);
|
||||||
|
|
||||||
|
upButton.setHidden(hidden);
|
||||||
|
upButton.setOriginalY(bounds.y);
|
||||||
|
upButton.revalidate();
|
||||||
|
|
||||||
|
downButton.setHidden(hidden);
|
||||||
|
downButton.setOriginalY(bounds.y + maxTabs * TAB_HEIGHT + MARGIN * maxTabs + BUTTON_HEIGHT + MARGIN);
|
||||||
|
downButton.revalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Widget createGraphic(String name, int spriteId, int itemId, int width, int height, int x, int y, boolean hasListener)
|
||||||
|
{
|
||||||
|
Widget widget = parent.createChild(-1, WidgetType.GRAPHIC);
|
||||||
|
widget.setOriginalWidth(width);
|
||||||
|
widget.setOriginalHeight(height);
|
||||||
|
widget.setOriginalX(x);
|
||||||
|
widget.setOriginalY(y);
|
||||||
|
|
||||||
|
widget.setSpriteId(spriteId);
|
||||||
|
|
||||||
|
if (itemId > -1)
|
||||||
|
{
|
||||||
|
widget.setItemId(itemId);
|
||||||
|
widget.setItemQuantity(-1);
|
||||||
|
widget.setBorderType(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasListener)
|
||||||
|
{
|
||||||
|
widget.setOnOpListener(ScriptID.NULL);
|
||||||
|
widget.setHasListener(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
widget.setName(name);
|
||||||
|
widget.revalidate();
|
||||||
|
|
||||||
|
return widget;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateWidget(Widget t, int y)
|
||||||
|
{
|
||||||
|
t.setOriginalY(y);
|
||||||
|
t.setRelativeY(y);
|
||||||
|
t.setHidden(y < (bounds.y + BUTTON_HEIGHT + MARGIN) || y > (bounds.y + bounds.height - TAB_HEIGHT - MARGIN - BUTTON_HEIGHT));
|
||||||
|
t.revalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doSearch(InputType inputType, String search)
|
||||||
|
{
|
||||||
|
// In case the widget ids array is incorrect, do not proceed
|
||||||
|
if (widgetIds == null || widgetIds.length < 21)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
clientThread.invokeLater(() ->
|
||||||
|
{
|
||||||
|
// This ensures that any chatbox input (e.g from search) will not remain visible when
|
||||||
|
// selecting/changing tab
|
||||||
|
client.runScript(ScriptID.CLOSE_CHATBOX_INPUT);
|
||||||
|
|
||||||
|
client.setVar(VarClientInt.INPUT_TYPE, inputType.getType());
|
||||||
|
client.setVar(VarClientStr.INPUT_TEXT, search);
|
||||||
|
|
||||||
|
client.runScript(ScriptID.BANK_LAYOUT,
|
||||||
|
WidgetInfo.BANK_CONTAINER.getId(),
|
||||||
|
widgetIds[INNER_CONTAINER_IDX],
|
||||||
|
widgetIds[SETTINGS_IDX],
|
||||||
|
widgetIds[ITEM_CONTAINER_IDX],
|
||||||
|
widgetIds[SCROLLBAR_IDX],
|
||||||
|
widgetIds[BOTTOM_BAR_IDX],
|
||||||
|
widgetIds[TITLE_BAR_IDX],
|
||||||
|
widgetIds[ITEM_COUNT_IDX],
|
||||||
|
widgetIds[SEARCH_BUTTON_BACKGROUND_IDX],
|
||||||
|
widgetIds[TAB_BAR_IDX],
|
||||||
|
widgetIds[INCINERATOR_IDX],
|
||||||
|
widgetIds[INCINERATOR_CONFIRM_IDX],
|
||||||
|
widgetIds[HIDDEN_WIDGET_IDX]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private ItemComposition getItem(int idx)
|
||||||
|
{
|
||||||
|
ItemContainer bankContainer = client.getItemContainer(InventoryID.BANK);
|
||||||
|
Item item = bankContainer.getItems()[idx];
|
||||||
|
return itemManager.getItemComposition(item.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openTag(String tag)
|
||||||
|
{
|
||||||
|
doSearch(InputType.SEARCH, tag);
|
||||||
|
activateTab(tabManager.find(tag.substring(4)));
|
||||||
|
|
||||||
|
// When tab is selected with search window open, the search window closes but the search button
|
||||||
|
// stays highlighted, this solves that issue
|
||||||
|
Widget searchBackground = client.getWidget(WidgetInfo.BANK_SEARCH_BUTTON_BACKGROUND);
|
||||||
|
searchBackground.setSpriteId(SpriteID.EQUIPMENT_SLOT_TILE);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,148 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
|
||||||
|
* Copyright (c) 2018, Ron Young <https://github.com/raiyni>
|
||||||
|
* 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.banktags.tabs;
|
||||||
|
|
||||||
|
import com.google.common.base.MoreObjects;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
import lombok.Getter;
|
||||||
|
import net.runelite.api.ItemID;
|
||||||
|
import net.runelite.client.config.ConfigManager;
|
||||||
|
import static net.runelite.client.plugins.banktags.BankTagsPlugin.CONFIG_GROUP;
|
||||||
|
import static net.runelite.client.plugins.banktags.BankTagsPlugin.ICON_SEARCH;
|
||||||
|
import static net.runelite.client.plugins.banktags.BankTagsPlugin.JOINER;
|
||||||
|
import static net.runelite.client.plugins.banktags.BankTagsPlugin.SPLITTER;
|
||||||
|
import net.runelite.client.util.Text;
|
||||||
|
import org.apache.commons.lang3.math.NumberUtils;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class TabManager
|
||||||
|
{
|
||||||
|
private static final String TAG_TABS_CONFIG = "tagtabs";
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private final List<TagTab> tabs = new ArrayList<>();
|
||||||
|
private final ConfigManager configManager;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private TabManager(ConfigManager configManager)
|
||||||
|
{
|
||||||
|
this.configManager = configManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(TagTab tagTab)
|
||||||
|
{
|
||||||
|
if (!contains(tagTab.getTag()))
|
||||||
|
{
|
||||||
|
tabs.add(tagTab);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
tabs.forEach(t -> t.setHidden(true));
|
||||||
|
tabs.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
TagTab find(String tag)
|
||||||
|
{
|
||||||
|
Optional<TagTab> first = tabs.stream().filter(t -> t.getTag().equals(Text.standardize(tag))).findAny();
|
||||||
|
return first.orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> getAllTabs()
|
||||||
|
{
|
||||||
|
return SPLITTER.splitToList(MoreObjects.firstNonNull(configManager.getConfiguration(CONFIG_GROUP, TAG_TABS_CONFIG), ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
TagTab load(String tag)
|
||||||
|
{
|
||||||
|
TagTab tagTab = find(tag);
|
||||||
|
|
||||||
|
if (tagTab == null)
|
||||||
|
{
|
||||||
|
tag = Text.standardize(tag);
|
||||||
|
String item = configManager.getConfiguration(CONFIG_GROUP, ICON_SEARCH + tag);
|
||||||
|
int itemid = NumberUtils.toInt(item, ItemID.SPADE);
|
||||||
|
tagTab = new TagTab(itemid, tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tagTab;
|
||||||
|
}
|
||||||
|
|
||||||
|
void move(String tagToMove, String tagDestination)
|
||||||
|
{
|
||||||
|
tagToMove = Text.standardize(tagToMove);
|
||||||
|
tagDestination = Text.standardize(tagDestination);
|
||||||
|
|
||||||
|
if (contains(tagToMove) && contains(tagDestination))
|
||||||
|
{
|
||||||
|
Collections.swap(tabs, indexOf(tagToMove), indexOf(tagDestination));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove(String tag)
|
||||||
|
{
|
||||||
|
TagTab tagTab = find(tag);
|
||||||
|
|
||||||
|
if (tagTab != null)
|
||||||
|
{
|
||||||
|
tagTab.setHidden(true);
|
||||||
|
tabs.remove(tagTab);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void save()
|
||||||
|
{
|
||||||
|
String tags = JOINER.join(tabs.stream().map(TagTab::getTag).collect(Collectors.toList()));
|
||||||
|
configManager.setConfiguration(CONFIG_GROUP, TAG_TABS_CONFIG, tags);
|
||||||
|
}
|
||||||
|
|
||||||
|
int size()
|
||||||
|
{
|
||||||
|
return tabs.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean contains(String tag)
|
||||||
|
{
|
||||||
|
return tabs.stream().anyMatch(t -> t.getTag().equals(tag));
|
||||||
|
}
|
||||||
|
|
||||||
|
private int indexOf(TagTab tagTab)
|
||||||
|
{
|
||||||
|
return tabs.indexOf(tagTab);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int indexOf(String tag)
|
||||||
|
{
|
||||||
|
return indexOf(find(tag));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
|
||||||
|
* Copyright (c) 2018, Ron Young <https://github.com/raiyni>
|
||||||
|
* 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.banktags.tabs;
|
||||||
|
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.awt.image.PixelGrabber;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import net.runelite.api.Client;
|
||||||
|
import net.runelite.api.SpritePixels;
|
||||||
|
import net.runelite.client.util.ImageUtil;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
public enum TabSprites
|
||||||
|
{
|
||||||
|
INCINERATOR(-200, "incinerator.png"),
|
||||||
|
TAB_BACKGROUND(-201, "tag-tab.png"),
|
||||||
|
TAB_BACKGROUND_ACTIVE(-202, "tag-tab-active.png"),
|
||||||
|
UP_ARROW(-203, "up-arrow.png"),
|
||||||
|
DOWN_ARROW(-204, "down-arrow.png"),
|
||||||
|
NEW_TAB(-205, "new-tab.png");
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private final int spriteId;
|
||||||
|
private final BufferedImage image;
|
||||||
|
|
||||||
|
TabSprites(final int spriteId, final String imageName)
|
||||||
|
{
|
||||||
|
this.spriteId = spriteId;
|
||||||
|
this.image = ImageUtil.getResourceStreamFromClass(this.getClass(), imageName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<Integer, SpritePixels> toMap(Client client)
|
||||||
|
{
|
||||||
|
final Map<Integer, SpritePixels> map = new HashMap<>();
|
||||||
|
|
||||||
|
for (TabSprites value : values())
|
||||||
|
{
|
||||||
|
map.put(value.spriteId, getSpritePixels(client, value.image));
|
||||||
|
}
|
||||||
|
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static SpritePixels getSpritePixels(Client client, BufferedImage image)
|
||||||
|
{
|
||||||
|
int[] pixels = new int[image.getWidth() * image.getHeight()];
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
new PixelGrabber(image, 0, 0, image.getWidth(), image.getHeight(), pixels, 0, image.getWidth())
|
||||||
|
.grabPixels();
|
||||||
|
}
|
||||||
|
catch (InterruptedException ex)
|
||||||
|
{
|
||||||
|
log.debug("PixelGrabber was interrupted: ", ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
return client.createSpritePixels(pixels, image.getWidth(), image.getHeight());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
|
||||||
|
* Copyright (c) 2018, Ron Young <https://github.com/raiyni>
|
||||||
|
* 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.banktags.tabs;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import net.runelite.api.widgets.Widget;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(of = "tag")
|
||||||
|
class TagTab
|
||||||
|
{
|
||||||
|
private final String tag;
|
||||||
|
private int iconItemId;
|
||||||
|
private Widget background;
|
||||||
|
private Widget icon;
|
||||||
|
|
||||||
|
TagTab(int iconItemId, String tag)
|
||||||
|
{
|
||||||
|
this.iconItemId = iconItemId;
|
||||||
|
this.tag = tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setHidden(boolean hide)
|
||||||
|
{
|
||||||
|
if (background != null)
|
||||||
|
{
|
||||||
|
background.setHidden(hide);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (icon != null)
|
||||||
|
{
|
||||||
|
icon.setHidden(hide);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 720 B |
Binary file not shown.
|
After Width: | Height: | Size: 3.1 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 943 B |
Binary file not shown.
|
After Width: | Height: | Size: 759 B |
Binary file not shown.
|
After Width: | Height: | Size: 824 B |
Binary file not shown.
|
After Width: | Height: | Size: 716 B |
Reference in New Issue
Block a user