From 2434557e1a0ecd4278c2623a66866bb6fe92f62e Mon Sep 17 00:00:00 2001 From: Max Weber Date: Mon, 8 Oct 2018 01:36:29 -0600 Subject: [PATCH] Add ChatboxPanelManager to allow for more advanced chatbox inputs --- .../main/java/net/runelite/api/FontID.java | 57 ++ .../java/net/runelite/api/FontTypeFace.java | 35 + .../main/java/net/runelite/api/ScriptID.java | 10 +- .../java/net/runelite/api/vars/InputType.java | 1 + .../java/net/runelite/api/widgets/Widget.java | 151 +++- .../net/runelite/api/widgets/WidgetID.java | 15 +- .../net/runelite/api/widgets/WidgetInfo.java | 15 +- .../api/widgets/WidgetPositionMode.java | 39 + .../runelite/api/widgets/WidgetSizeMode.java | 43 ++ .../api/widgets/WidgetTextAlignment.java | 34 + .../java/net/runelite/client/RuneLite.java | 5 + .../client/game/ChatboxInputManager.java | 2 +- .../client/game/chatbox/ChatboxInput.java | 39 + .../game/chatbox/ChatboxPanelManager.java | 177 +++++ .../client/game/chatbox/ChatboxTextInput.java | 666 ++++++++++++++++++ .../game/chatbox/ChatboxTextMenuInput.java | 212 ++++++ .../plugins/banktags/tabs/TabInterface.java | 4 +- .../devtools/WidgetInfoTableModel.java | 24 +- .../plugins/devtools/WidgetInspector.java | 11 + .../src/main/scripts/ResetChatboxInput.hash | 1 + .../src/main/scripts/ResetChatboxInput.rs2asm | 180 +++++ .../net/runelite/mixins/RSWidgetMixin.java | 11 + .../net/runelite/rs/api/RSFontTypeFace.java | 39 + .../java/net/runelite/rs/api/RSWidget.java | 85 +++ 24 files changed, 1831 insertions(+), 25 deletions(-) create mode 100644 runelite-api/src/main/java/net/runelite/api/FontID.java create mode 100644 runelite-api/src/main/java/net/runelite/api/FontTypeFace.java create mode 100644 runelite-api/src/main/java/net/runelite/api/widgets/WidgetPositionMode.java create mode 100644 runelite-api/src/main/java/net/runelite/api/widgets/WidgetSizeMode.java create mode 100644 runelite-api/src/main/java/net/runelite/api/widgets/WidgetTextAlignment.java create mode 100644 runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxInput.java create mode 100644 runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxPanelManager.java create mode 100644 runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextInput.java create mode 100644 runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextMenuInput.java create mode 100644 runelite-client/src/main/scripts/ResetChatboxInput.hash create mode 100644 runelite-client/src/main/scripts/ResetChatboxInput.rs2asm create mode 100644 runescape-api/src/main/java/net/runelite/rs/api/RSFontTypeFace.java diff --git a/runelite-api/src/main/java/net/runelite/api/FontID.java b/runelite-api/src/main/java/net/runelite/api/FontID.java new file mode 100644 index 0000000000..6f9c391e3c --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/FontID.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018 Abex + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.api; + +/** + * IDs of fonts in the cache + */ +public final class FontID +{ + public static final int PLAIN_11 = 494; + public static final int PLAIN_12 = 495; + + public static final int BOLD_12 = 496; + + public static final int QUILL_8 = 497; + public static final int QUILL_MEDIUM = 645; + public static final int QUILL_CAPS_LARGE = 646; + + public static final int FAIRY_SMALL = 647; + public static final int FAIRY_LARGE = 648; + + public static final int BARBARIAN = 764; + + public static final int SUROK = 819; + + public static final int VERDANA_11 = 1442; + public static final int VERDANA_11_BOLD = 1443; + + public static final int TAHOMA_11 = 1444; + + public static final int VERDANA_13 = 1445; + public static final int VERDANA_13_BOLD = 1446; + + public static final int VERDANA_15 = 1447; +} diff --git a/runelite-api/src/main/java/net/runelite/api/FontTypeFace.java b/runelite-api/src/main/java/net/runelite/api/FontTypeFace.java new file mode 100644 index 0000000000..59241300b3 --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/FontTypeFace.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018 Abex + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.api; + +/** + * A bitmap Font in Jagex's format + */ +public interface FontTypeFace +{ + int getTextWidth(String text); + + int getBaseline(); +} diff --git a/runelite-api/src/main/java/net/runelite/api/ScriptID.java b/runelite-api/src/main/java/net/runelite/api/ScriptID.java index 0ca8d58b07..f8cb56bcc1 100644 --- a/runelite-api/src/main/java/net/runelite/api/ScriptID.java +++ b/runelite-api/src/main/java/net/runelite/api/ScriptID.java @@ -56,10 +56,16 @@ public final class ScriptID * Closes the chatbox input * */ - public static final int CLOSE_CHATBOX_INPUT = 299; + public static final int RESET_CHATBOX_INPUT = 299; + + /** + * Readies the chatbox panel for things like the chatbox input + * Inverse of RESET_CHATBOX_INPUT + */ + public static final int CLEAR_CHATBOX_PANEL = 677; /** * Updates the Diary/Quest interface's scrollbar diff --git a/runelite-api/src/main/java/net/runelite/api/vars/InputType.java b/runelite-api/src/main/java/net/runelite/api/vars/InputType.java index 08eb727c47..db1301b281 100644 --- a/runelite-api/src/main/java/net/runelite/api/vars/InputType.java +++ b/runelite-api/src/main/java/net/runelite/api/vars/InputType.java @@ -35,6 +35,7 @@ import net.runelite.api.VarClientInt; @RequiredArgsConstructor public enum InputType { + RUNELITE_CHATBOX_PANEL(-3), RUNELITE(-2), NONE(0), SEARCH(11); diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/Widget.java b/runelite-api/src/main/java/net/runelite/api/widgets/Widget.java index 55eb56312d..958aeca008 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/Widget.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/Widget.java @@ -26,6 +26,7 @@ package net.runelite.api.widgets; import java.awt.Rectangle; import java.util.Collection; +import net.runelite.api.FontTypeFace; import net.runelite.api.Point; /** @@ -201,13 +202,22 @@ public interface Widget int getTextColor(); /** - * Sets the RGB color of the displayed text. + * Sets the RGB color of the displayed text or rectangle. * * @param textColor the new text color * @see java.awt.Color#getRGB() */ void setTextColor(int textColor); + /** + * Sets the opacity of the rectangle + */ + int getOpacity(); + /** + * Gets the opacity of the rectangle + */ + void setOpacity(int opacity); + /** * Gets the name of the widget. *

@@ -489,6 +499,11 @@ public interface Widget */ Widget createChild(int index, int type); + /** + * Removes all of this widget's dynamic children + */ + void deleteAllChildren(); + /** * Creates a menu action on the widget * @@ -505,6 +520,41 @@ public interface Widget */ void setOnOpListener(Object... args); + /** + * Sets a script to be ran when the dialog is canceled + * + * @param args A ScriptID, then the args for the script + */ + void setOnDialogAbortListener(Object... args); + + /** + * Sets a script to be ran on key input + * + * @param args A ScriptID, then the args for the script + */ + void setOnKeyListener(Object... args); + + /** + * Sets a script to be ran when the mouse enters the widget bounds + * + * @param args A ScriptID, then the args for the script + */ + void setOnMouseOverListener(Object... args); + + /** + * Sets a script to be ran when the mouse leaves the widget bounds + * + * @param args A ScriptID, then the args for the script + */ + void setOnMouseLeaveListener(Object... args); + + /** + * Sets a script to be ran every frame + * + * @param args A ScriptID, then the args for the script + */ + void setOnTimerListener(Object... args); + /** * If this widget has any listeners on it */ @@ -602,4 +652,103 @@ public interface Widget * Sets the widget {@link net.runelite.api.widgets.ItemQuantityMode} */ void setItemQuantityMode(int itemQuantityMode); + + /** + * Gets the mode that the X position is calculated from the original X position + * + * @see WidgetPositionMode + */ + int getXPositionMode(); + + /** + * Sets the mode that the X position is calculated from the original X position + * + * @see WidgetPositionMode + */ + void setXPositionMode(int xpm); + + /** + * Gets the mode that the Y position is calculated from the original Y position + * + * @see WidgetPositionMode + */ + int getYPositionMode(); + + /** + * Sets the mode that the Y position is calculated from the original Y position + * + * @see WidgetPositionMode + */ + void setYPositionMode(int ypm); + + /** + * Gets the X axis text position mode + * + * @see WidgetTextAlignment + */ + int getXTextAlignment(); + + /** + * Sets the X axis text position mode + * + * @see WidgetTextAlignment + */ + void setXTextAlignment(int xta); + + /** + * Gets the Y axis text position mode + * + * @see WidgetTextAlignment + */ + int getYTextAlignment(); + + /** + * Sets the Y axis text position mode + * + * @see WidgetTextAlignment + */ + void setYTextAlignment(int yta); + + /** + * Gets the mode controlling widget width + * + * @see WidgetSizeMode + */ + int getWidthMode(); + + /** + * Sets the mode controlling widget width + * + * @see WidgetSizeMode + */ + void setWidthMode(int widthMode); + + /** + * Gets the mode controlling widget width + * + * @see WidgetSizeMode + */ + int getHeightMode(); + + /** + * Sets the mode controlling widget width + * + * @see WidgetSizeMode + */ + void setHeightMode(int heightMode); + + /** + * Gets the font that this widget uses + */ + FontTypeFace getFont(); + + /** + * Gets if the rectangle is filled or just stroked + */ + boolean isFilled(); + + /** + * Sets if the rectangle is filled or just stroked + */ + void setFilled(boolean filled); } diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java index 068bd32612..1ad30031c2 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetID.java @@ -410,12 +410,15 @@ public class WidgetID static class Chatbox { - static final int CHATBOX_PARENT = 0; - static final int CHATBOX_BUTTONS = 1; - static final int CHATBOX_REPORT_TEXT = 36; - static final int CHATBOX_FRAME = 37; - static final int CHATBOX_MESSAGES = 55; - static final int CHATBOX_INPUT = 57; + static final int PARENT = 0; + static final int BUTTONS = 1; + static final int REPORT_TEXT = 36; + static final int FRAME = 37; + static final int CONTAINER = 40; + static final int TITLE = 44; + static final int FULL_INPUT = 45; + static final int MESSAGES = 55; + static final int INPUT = 57; } static class Prayer diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java index f501f97d8d..ccd71b3198 100644 --- a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetInfo.java @@ -322,12 +322,15 @@ public enum WidgetInfo SLAYER_REWARDS_TOPBAR(WidgetID.SLAYER_REWARDS_GROUP_ID, WidgetID.SlayerRewards.TOP_BAR), - CHATBOX_PARENT(WidgetID.CHATBOX_GROUP_ID, WidgetID.Chatbox.CHATBOX_PARENT), - CHATBOX(WidgetID.CHATBOX_GROUP_ID, WidgetID.Chatbox.CHATBOX_FRAME), - CHATBOX_MESSAGES(WidgetID.CHATBOX_GROUP_ID, WidgetID.Chatbox.CHATBOX_MESSAGES), - CHATBOX_BUTTONS(WidgetID.CHATBOX_GROUP_ID, WidgetID.Chatbox.CHATBOX_BUTTONS), - CHATBOX_REPORT_TEXT(WidgetID.CHATBOX_GROUP_ID, WidgetID.Chatbox.CHATBOX_REPORT_TEXT), - CHATBOX_INPUT(WidgetID.CHATBOX_GROUP_ID, WidgetID.Chatbox.CHATBOX_INPUT), + CHATBOX_PARENT(WidgetID.CHATBOX_GROUP_ID, WidgetID.Chatbox.PARENT), + CHATBOX(WidgetID.CHATBOX_GROUP_ID, WidgetID.Chatbox.FRAME), + CHATBOX_MESSAGES(WidgetID.CHATBOX_GROUP_ID, WidgetID.Chatbox.MESSAGES), + CHATBOX_BUTTONS(WidgetID.CHATBOX_GROUP_ID, WidgetID.Chatbox.BUTTONS), + CHATBOX_TITLE(WidgetID.CHATBOX_GROUP_ID, WidgetID.Chatbox.TITLE), + CHATBOX_FULL_INPUT(WidgetID.CHATBOX_GROUP_ID, WidgetID.Chatbox.FULL_INPUT), + CHATBOX_CONTAINER(WidgetID.CHATBOX_GROUP_ID, WidgetID.Chatbox.CONTAINER), + CHATBOX_REPORT_TEXT(WidgetID.CHATBOX_GROUP_ID, WidgetID.Chatbox.REPORT_TEXT), + CHATBOX_INPUT(WidgetID.CHATBOX_GROUP_ID, WidgetID.Chatbox.INPUT), BA_HEAL_WAVE_TEXT(WidgetID.BA_HEALER_GROUP_ID, WidgetID.BarbarianAssault.CURRENT_WAVE), BA_HEAL_CALL_TEXT(WidgetID.BA_HEALER_GROUP_ID, WidgetID.BarbarianAssault.TO_CALL), diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetPositionMode.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetPositionMode.java new file mode 100644 index 0000000000..7ebfdf3c61 --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetPositionMode.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2018 Abex + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.api.widgets; + +public final class WidgetPositionMode +{ + public static final int ABSOLUTE_LEFT = 0; + public static final int ABSOLUTE_TOP = 0; + public static final int ABSOLUTE_CENTER = 1; + public static final int ABSOLUTE_RIGHT = 2; + public static final int ABSOLUTE_BOTTOM = 2; + public static final int LEFT_16384THS = 3; + public static final int TOP_16384THS = 3; + public static final int CENTER_16384THS = 4; + public static final int RIGHT_16384THS = 5; + public static final int BOTTOM_16384THS = 5; +} diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetSizeMode.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetSizeMode.java new file mode 100644 index 0000000000..f468491d81 --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetSizeMode.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018 Abex + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.api.widgets; + +public final class WidgetSizeMode +{ + /** + * dim = originalDim + */ + public static final int ABSOLUTE = 0; + + /** + * dim = parentDim - originalDim + */ + public static final int MINUS = 1; + + /** + * dim = parentDim * (originalDim / 16384) + */ + public static final int ABSOLUTE_16384THS = 2; +} diff --git a/runelite-api/src/main/java/net/runelite/api/widgets/WidgetTextAlignment.java b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetTextAlignment.java new file mode 100644 index 0000000000..1b47301f02 --- /dev/null +++ b/runelite-api/src/main/java/net/runelite/api/widgets/WidgetTextAlignment.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018 Abex + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.api.widgets; + +public final class WidgetTextAlignment +{ + public static final int LEFT = 0; + public static final int TOP = 0; + public static final int CENTER = 1; + public static final int RIGHT = 2; + public static final int BOTTOM = 2; +} diff --git a/runelite-client/src/main/java/net/runelite/client/RuneLite.java b/runelite-client/src/main/java/net/runelite/client/RuneLite.java index 986cf46a6d..13d30d85f0 100644 --- a/runelite-client/src/main/java/net/runelite/client/RuneLite.java +++ b/runelite-client/src/main/java/net/runelite/client/RuneLite.java @@ -53,6 +53,7 @@ import net.runelite.client.discord.DiscordService; import net.runelite.client.game.ClanManager; import net.runelite.client.game.ItemManager; import net.runelite.client.game.LootManager; +import net.runelite.client.game.chatbox.ChatboxPanelManager; import net.runelite.client.menus.MenuManager; import net.runelite.client.plugins.PluginManager; import net.runelite.client.rs.ClientUpdateCheckMode; @@ -141,6 +142,9 @@ public class RuneLite @Inject private Provider lootManager; + @Inject + private Provider chatboxPanelManager; + @Inject @Nullable private Client client; @@ -278,6 +282,7 @@ public class RuneLite eventBus.register(chatMessageManager.get()); eventBus.register(commandManager.get()); eventBus.register(lootManager.get()); + eventBus.register(chatboxPanelManager.get()); // Add core overlays WidgetOverlay.createOverlays(client).forEach(overlayManager::add); diff --git a/runelite-client/src/main/java/net/runelite/client/game/ChatboxInputManager.java b/runelite-client/src/main/java/net/runelite/client/game/ChatboxInputManager.java index 9ac265dafc..2cf0a11252 100644 --- a/runelite-client/src/main/java/net/runelite/client/game/ChatboxInputManager.java +++ b/runelite-client/src/main/java/net/runelite/client/game/ChatboxInputManager.java @@ -98,7 +98,7 @@ public class ChatboxInputManager } this.open = false; clientThread.invoke(() -> client.runScript( - ScriptID.CLOSE_CHATBOX_INPUT, + ScriptID.RESET_CHATBOX_INPUT, 1, 1 )); diff --git a/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxInput.java b/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxInput.java new file mode 100644 index 0000000000..bdd7c10dda --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxInput.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2018 Abex + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.game.chatbox; + +/** + * A modal input that lives in the chatbox panel. + */ +public abstract class ChatboxInput +{ + protected void open() + { + } + + protected void close() + { + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxPanelManager.java b/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxPanelManager.java new file mode 100644 index 0000000000..3cfb2d3bde --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxPanelManager.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2018 Abex + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.game.chatbox; + +import com.google.common.eventbus.EventBus; +import com.google.common.eventbus.Subscribe; +import com.google.inject.Inject; +import com.google.inject.Provider; +import com.google.inject.Singleton; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.Client; +import net.runelite.api.ScriptID; +import net.runelite.api.VarClientInt; +import net.runelite.api.events.ScriptCallbackEvent; +import net.runelite.api.vars.InputType; +import net.runelite.api.widgets.JavaScriptCallback; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; +import net.runelite.client.callback.ClientThread; +import net.runelite.client.input.KeyListener; +import net.runelite.client.input.KeyManager; +import net.runelite.client.input.MouseListener; +import net.runelite.client.input.MouseManager; +import net.runelite.client.input.MouseWheelListener; + +@Singleton +@Slf4j +public class ChatboxPanelManager +{ + private final Client client; + private final ClientThread clientThread; + private final EventBus eventBus; + + private final KeyManager keyManager; + private final MouseManager mouseManager; + + private final Provider chatboxTextMenuInputProvider; + private final Provider chatboxTextInputProvider; + + @Getter + private ChatboxInput currentInput = null; + + @Inject + private ChatboxPanelManager(EventBus eventBus, Client client, ClientThread clientThread, + KeyManager keyManager, MouseManager mouseManager, + Provider chatboxTextMenuInputProvider, Provider chatboxTextInputProvider) + { + this.client = client; + this.clientThread = clientThread; + this.eventBus = eventBus; + + this.keyManager = keyManager; + this.mouseManager = mouseManager; + + this.chatboxTextMenuInputProvider = chatboxTextMenuInputProvider; + this.chatboxTextInputProvider = chatboxTextInputProvider; + } + + public void close() + { + clientThread.invokeLater(this::unsafeCloseInput); + } + + private void unsafeCloseInput() + { + client.runScript( + ScriptID.RESET_CHATBOX_INPUT, + 0, + 1 + ); + } + + private void unsafeOpenInput(ChatboxInput input) + { + client.runScript(ScriptID.CLEAR_CHATBOX_PANEL); + + eventBus.register(input); + if (input instanceof KeyListener) + { + keyManager.registerKeyListener((KeyListener) input); + } + if (input instanceof MouseListener) + { + mouseManager.registerMouseListener((MouseListener) input); + } + if (input instanceof MouseWheelListener) + { + mouseManager.registerMouseWheelListener((MouseWheelListener) input); + } + + currentInput = input; + client.setVar(VarClientInt.INPUT_TYPE, InputType.RUNELITE_CHATBOX_PANEL.getType()); + client.getWidget(WidgetInfo.CHATBOX_TITLE).setHidden(true); + client.getWidget(WidgetInfo.CHATBOX_FULL_INPUT).setHidden(true); + + Widget c = getContainerWidget(); + c.deleteAllChildren(); + c.setOnDialogAbortListener((JavaScriptCallback) ev -> this.unsafeCloseInput()); + input.open(); + } + + public void openInput(ChatboxInput input) + { + clientThread.invokeLater(() -> unsafeOpenInput(input)); + } + + public ChatboxTextMenuInput openTextMenuInput(String title) + { + return chatboxTextMenuInputProvider.get() + .title(title); + } + + public ChatboxTextInput openTextInput(String prompt) + { + return chatboxTextInputProvider.get() + .prompt(prompt); + } + + @Subscribe + public void onScriptCallbackEvent(ScriptCallbackEvent ev) + { + if (currentInput != null && "resetChatboxInput".equals(ev.getEventName())) + { + try + { + currentInput.close(); + } + catch (Exception e) + { + log.warn("Exception closing {}", currentInput.getClass(), e); + } + + eventBus.unregister(currentInput); + if (currentInput instanceof KeyListener) + { + keyManager.unregisterKeyListener((KeyListener) currentInput); + } + if (currentInput instanceof MouseListener) + { + mouseManager.unregisterMouseListener((MouseListener) currentInput); + } + if (currentInput instanceof MouseWheelListener) + { + mouseManager.unregisterMouseWheelListener((MouseWheelListener) currentInput); + } + currentInput = null; + } + } + + public Widget getContainerWidget() + { + return client.getWidget(WidgetInfo.CHATBOX_CONTAINER); + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextInput.java b/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextInput.java new file mode 100644 index 0000000000..83c3117406 --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextInput.java @@ -0,0 +1,666 @@ +/* + * Copyright (c) 2018 Abex + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.game.chatbox; + +import com.google.inject.Inject; +import java.awt.Rectangle; +import java.awt.Toolkit; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.StringSelection; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.io.IOException; +import java.util.function.Consumer; +import java.util.function.IntPredicate; +import java.util.function.Predicate; +import java.util.function.ToIntFunction; +import javax.swing.SwingUtilities; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.FontTypeFace; +import net.runelite.api.FontID; +import net.runelite.api.WidgetType; +import net.runelite.api.widgets.JavaScriptCallback; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetPositionMode; +import net.runelite.api.widgets.WidgetSizeMode; +import net.runelite.api.widgets.WidgetTextAlignment; +import net.runelite.client.callback.ClientThread; +import net.runelite.client.input.KeyListener; +import net.runelite.client.input.MouseListener; + +@Slf4j +public class ChatboxTextInput extends ChatboxInput implements KeyListener, MouseListener +{ + private static final int CURSOR_FLASH_RATE_MILLIS = 1000; + + private final ChatboxPanelManager chatboxPanelManager; + private final ClientThread clientThread; + + private static IntPredicate getDefaultCharValidator() + { + return i -> i >= 32 && i < 127; + } + + @Getter + private String prompt; + + private StringBuffer value = new StringBuffer(); + + @Getter + private int cursor = 0; + + @Getter + private int cursorEnd = 0; + + private int selectionStart = -1; + private int selectionEnd = -1; + + @Getter + private IntPredicate charValidator = getDefaultCharValidator(); + + @Getter + private Runnable onClose = null; + + @Getter + private Consumer onDone = null; + + @Getter + private Consumer onChanged = null; + + @Getter + private int fontID = FontID.QUILL_8; + + // This is a lambda so I can have atomic updates for it's captures + private ToIntFunction getCharOffset = null; + private Predicate isInBounds = null; + + private boolean built = false; + + @Inject + protected ChatboxTextInput(ChatboxPanelManager chatboxPanelManager, ClientThread clientThread) + { + this.chatboxPanelManager = chatboxPanelManager; + this.clientThread = clientThread; + } + + public ChatboxTextInput prompt(String prompt) + { + this.prompt = prompt; + if (built) + { + clientThread.invoke(this::update); + } + return this; + } + + public ChatboxTextInput value(String value) + { + this.value = new StringBuffer(value); + if (built) + { + clientThread.invoke(this::update); + } + return this; + } + + public ChatboxTextInput cursorAt(int index) + { + return cursorAt(index, index); + } + + public ChatboxTextInput cursorAt(int indexA, int indexB) + { + if (indexA < 0) + { + indexA = 0; + } + if (indexB < 0) + { + indexB = 0; + } + if (indexA > value.length()) + { + indexA = value.length(); + } + if (indexB > value.length()) + { + indexB = value.length(); + } + int start = indexA; + int end = indexB; + if (start > end) + { + int v = start; + start = end; + end = v; + } + + this.cursor = start; + this.cursorEnd = end; + + if (built) + { + clientThread.invoke(this::update); + } + + return this; + } + + public String getValue() + { + return value.toString(); + } + + public ChatboxTextInput charValidator(IntPredicate val) + { + if (val == null) + { + val = getDefaultCharValidator(); + } + this.charValidator = val; + return this; + } + + public ChatboxTextInput onClose(Runnable onClose) + { + this.onClose = onClose; + return this; + } + + public ChatboxTextInput onDone(Consumer onDone) + { + this.onDone = onDone; + return this; + } + + public ChatboxTextInput onChanged(Consumer onChanged) + { + this.onChanged = onChanged; + return this; + } + + public ChatboxTextInput fontID(int fontID) + { + this.fontID = fontID; + return this; + } + + protected void update() + { + this.built = true; + Widget container = chatboxPanelManager.getContainerWidget(); + container.deleteAllChildren(); + + Widget promptWidget = container.createChild(-1, WidgetType.TEXT); + promptWidget.setText(this.prompt); + promptWidget.setTextColor(0x800000); + promptWidget.setFontId(fontID); + promptWidget.setXPositionMode(WidgetPositionMode.ABSOLUTE_CENTER); + promptWidget.setOriginalX(0); + promptWidget.setYPositionMode(WidgetPositionMode.ABSOLUTE_TOP); + promptWidget.setOriginalY(8); + promptWidget.setOriginalHeight(24); + promptWidget.setXTextAlignment(WidgetTextAlignment.CENTER); + promptWidget.setYTextAlignment(WidgetTextAlignment.CENTER); + promptWidget.setWidthMode(WidgetSizeMode.MINUS); + promptWidget.revalidate(); + + buildEdit(0, 50, container.getWidth(), 0); + } + + protected void buildEdit(int x, int y, int w, int h) + { + Widget container = chatboxPanelManager.getContainerWidget(); + + String lt = value.substring(0, this.cursor); + String mt = value.substring(this.cursor, this.cursorEnd); + String rt = value.substring(this.cursorEnd); + + Widget leftText = container.createChild(-1, WidgetType.TEXT); + Widget cursor = container.createChild(-1, WidgetType.RECTANGLE); + Widget middleText = container.createChild(-1, WidgetType.TEXT); + Widget rightText = container.createChild(-1, WidgetType.TEXT); + + leftText.setFontId(fontID); + FontTypeFace font = leftText.getFont(); + + if (h <= 0) + { + h = font.getBaseline(); + } + + int ltw = font.getTextWidth(lt); + int mtw = font.getTextWidth(mt); + int rtw = font.getTextWidth(rt); + + int fullWidth = ltw + mtw + rtw; + + int ox = x; + if (w > 0) + { + x += (w - fullWidth) / 2; + } + + int ltx = x; + int mtx = ltx + ltw; + int rtx = mtx + mtw; + + leftText.setText(lt); + leftText.setOriginalX(ltx); + leftText.setOriginalY(y); + leftText.setOriginalWidth(ltw); + leftText.setOriginalHeight(h); + leftText.revalidate(); + + if (mt.length() > 0) + { + cursor.setTextColor(0x113399); + } + else + { + cursor.setTextColor(0xFFFFFF); + cursor.setOnTimerListener((JavaScriptCallback) ev -> + { + boolean on = System.currentTimeMillis() % CURSOR_FLASH_RATE_MILLIS > (CURSOR_FLASH_RATE_MILLIS / 2); + cursor.setOpacity(on ? 255 : 0); + }); + } + cursor.setFilled(true); + cursor.setOriginalX(mtx - 1); + cursor.setOriginalY(y); + cursor.setOriginalWidth(2 + mtw); + cursor.setOriginalHeight(h); + cursor.revalidate(); + + middleText.setText(mt); + middleText.setFontId(fontID); + middleText.setOriginalX(mtx); + middleText.setOriginalY(y); + middleText.setOriginalWidth(mtw); + middleText.setOriginalHeight(h); + middleText.setTextColor(0xFFFFFF); + middleText.revalidate(); + + rightText.setText(rt); + rightText.setFontId(fontID); + rightText.setOriginalX(rtx); + rightText.setOriginalY(y); + rightText.setOriginalWidth(rtw); + rightText.setOriginalHeight(h); + rightText.revalidate(); + + net.runelite.api.Point ccl = container.getCanvasLocation(); + int canvasX = ltx + ccl.getX(); + Rectangle bounds = new Rectangle(ccl.getX() + ox, ccl.getY() + y, w > 0 ? w : fullWidth, h); + + String tsValue = value.toString(); + isInBounds = ev -> bounds.contains(ev.getPoint()); + getCharOffset = ev -> + { + int cx = ev.getX() - canvasX; + + int charIndex = (tsValue.length() * cx) / fullWidth; + + // `i` is used to track max execution time incase there is a font with ligature width data that causes this to fail + for (int i = tsValue.length(); i >= 0 && charIndex >= 0 && charIndex <= tsValue.length(); i--) + { + int lcx = charIndex > 0 ? font.getTextWidth(tsValue.substring(0, charIndex - 1)) : 0; + int mcx = font.getTextWidth(tsValue.substring(0, charIndex)); + int rcx = charIndex + 1 <= tsValue.length() ? font.getTextWidth(tsValue.substring(0, charIndex + 1)) : mcx; + + int leftBound = (lcx + mcx) / 2; + int rightBound = (mcx + rcx) / 2; + + if (cx < leftBound) + { + charIndex--; + continue; + } + if (cx > rightBound) + { + charIndex++; + continue; + } + break; + } + + if (charIndex < 0) + { + charIndex = 0; + } + if (charIndex > tsValue.length()) + { + charIndex = tsValue.length(); + } + + return charIndex; + }; + } + + @Override + protected void open() + { + update(); + } + + @Override + protected void close() + { + if (this.onClose != null) + { + this.onClose.run(); + } + } + + public ChatboxTextInput build() + { + if (prompt == null) + { + throw new IllegalStateException("prompt must be non-null"); + } + chatboxPanelManager.openInput(this); + + return this; + } + + @Override + public void keyTyped(KeyEvent e) + { + char c = e.getKeyChar(); + if (charValidator.test(c)) + { + if (cursor != cursorEnd) + { + value.delete(cursor, cursorEnd); + } + value.insert(cursor, c); + cursorAt(cursor + 1); + if (onChanged != null) + { + onChanged.accept(getValue()); + } + } + } + + @Override + public void keyPressed(KeyEvent ev) + { + int code = ev.getKeyCode(); + if (ev.isControlDown()) + { + switch (code) + { + case KeyEvent.VK_X: + case KeyEvent.VK_C: + if (cursor != cursorEnd) + { + String s = value.substring(cursor, cursorEnd); + if (code == KeyEvent.VK_X) + { + value.delete(cursor, cursorEnd); + cursorAt(cursor); + } + Toolkit.getDefaultToolkit() + .getSystemClipboard() + .setContents(new StringSelection(s), null); + } + return; + case KeyEvent.VK_V: + try + { + String s = Toolkit.getDefaultToolkit() + .getSystemClipboard() + .getData(DataFlavor.stringFlavor) + .toString(); + if (cursor != cursorEnd) + { + value.delete(cursor, cursorEnd); + } + for (int i = 0; i < s.length(); i++) + { + char ch = s.charAt(i); + if (charValidator.test(ch)) + { + value.insert(cursor, ch); + cursor++; + } + } + cursorAt(cursor); + if (onChanged != null) + { + onChanged.accept(getValue()); + } + } + catch (IOException | UnsupportedFlavorException ex) + { + log.warn("Unable to get clipboard", ex); + } + return; + } + return; + } + int newPos = cursor; + if (ev.isShiftDown()) + { + if (selectionEnd == -1 || selectionStart == -1) + { + selectionStart = cursor; + selectionEnd = cursor; + } + newPos = selectionEnd; + } + else + { + selectionStart = -1; + selectionEnd = -1; + } + switch (code) + { + case KeyEvent.VK_DELETE: + if (cursor != cursorEnd) + { + value.delete(cursor, cursorEnd); + cursorAt(cursor); + if (onChanged != null) + { + onChanged.accept(getValue()); + } + return; + } + if (cursor < value.length()) + { + value.deleteCharAt(cursor); + cursorAt(cursor); + if (onChanged != null) + { + onChanged.accept(getValue()); + } + } + return; + case KeyEvent.VK_BACK_SPACE: + if (cursor != cursorEnd) + { + value.delete(cursor, cursorEnd); + cursorAt(cursor); + if (onChanged != null) + { + onChanged.accept(getValue()); + } + return; + } + if (cursor > 0) + { + value.deleteCharAt(cursor - 1); + cursorAt(cursor - 1); + if (onChanged != null) + { + onChanged.accept(getValue()); + } + } + return; + case KeyEvent.VK_LEFT: + ev.consume(); + newPos--; + break; + case KeyEvent.VK_RIGHT: + ev.consume(); + newPos++; + break; + case KeyEvent.VK_HOME: + ev.consume(); + newPos = 0; + break; + case KeyEvent.VK_END: + ev.consume(); + newPos = value.length(); + break; + case KeyEvent.VK_ENTER: + ev.consume(); + if (onDone != null) + { + onDone.accept(getValue()); + } + chatboxPanelManager.close(); + return; + case KeyEvent.VK_ESCAPE: + ev.consume(); + if (cursor != cursorEnd) + { + cursorAt(cursor); + return; + } + chatboxPanelManager.close(); + return; + default: + return; + } + if (newPos > value.length()) + { + newPos = value.length(); + } + if (newPos < 0) + { + newPos = 0; + } + if (ev.isShiftDown()) + { + selectionEnd = newPos; + cursorAt(selectionStart, newPos); + } + else + { + cursorAt(newPos); + } + } + + @Override + public void keyReleased(KeyEvent e) + { + } + + @Override + public MouseEvent mouseClicked(MouseEvent mouseEvent) + { + return mouseEvent; + } + + @Override + public MouseEvent mousePressed(MouseEvent mouseEvent) + { + if (mouseEvent.getButton() != MouseEvent.BUTTON1) + { + return mouseEvent; + } + if (isInBounds == null || !isInBounds.test(mouseEvent)) + { + if (cursor != cursorEnd) + { + selectionStart = -1; + selectionEnd = -1; + cursorAt(getCharOffset.applyAsInt(mouseEvent)); + } + return mouseEvent; + } + + int nco = getCharOffset.applyAsInt(mouseEvent); + + if (mouseEvent.isShiftDown() && selectionEnd != -1) + { + selectionEnd = nco; + cursorAt(selectionStart, selectionEnd); + } + else + { + selectionStart = nco; + cursorAt(nco); + } + + return mouseEvent; + } + + @Override + public MouseEvent mouseReleased(MouseEvent mouseEvent) + { + return mouseEvent; + } + + @Override + public MouseEvent mouseEntered(MouseEvent mouseEvent) + { + return mouseEvent; + } + + @Override + public MouseEvent mouseExited(MouseEvent mouseEvent) + { + return mouseEvent; + } + + @Override + public MouseEvent mouseDragged(MouseEvent mouseEvent) + { + if (!SwingUtilities.isLeftMouseButton(mouseEvent)) + { + return mouseEvent; + } + + int nco = getCharOffset.applyAsInt(mouseEvent); + if (selectionStart != -1) + { + selectionEnd = nco; + cursorAt(selectionStart, selectionEnd); + } + + return mouseEvent; + } + + @Override + public MouseEvent mouseMoved(MouseEvent mouseEvent) + { + return mouseEvent; + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextMenuInput.java b/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextMenuInput.java new file mode 100644 index 0000000000..91d6b9eacd --- /dev/null +++ b/runelite-client/src/main/java/net/runelite/client/game/chatbox/ChatboxTextMenuInput.java @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2018 Abex + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.client.game.chatbox; + +import com.google.inject.Inject; +import java.awt.event.KeyEvent; +import java.util.ArrayList; +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.Getter; +import lombok.extern.slf4j.Slf4j; +import net.runelite.api.FontID; +import net.runelite.api.WidgetType; +import net.runelite.api.widgets.JavaScriptCallback; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetPositionMode; +import net.runelite.api.widgets.WidgetSizeMode; +import net.runelite.api.widgets.WidgetTextAlignment; +import net.runelite.client.input.KeyListener; + +@Slf4j +public class ChatboxTextMenuInput extends ChatboxInput implements KeyListener +{ + @Data + @AllArgsConstructor + private static final class Entry + { + private String text; + private Runnable callback; + } + + private final ChatboxPanelManager chatboxPanelManager; + + @Getter + private String title; + + @Getter + private List options = new ArrayList<>(); + + @Getter + private Runnable onClose; + + @Inject + protected ChatboxTextMenuInput(ChatboxPanelManager chatboxPanelManager) + { + this.chatboxPanelManager = chatboxPanelManager; + } + + public ChatboxTextMenuInput title(String title) + { + this.title = title; + return this; + } + + public ChatboxTextMenuInput option(String text, Runnable callback) + { + options.add(new Entry(text, callback)); + return this; + } + + public ChatboxTextMenuInput onClose(Runnable onClose) + { + this.onClose = onClose; + return this; + } + + public void build() + { + if (title == null) + { + throw new IllegalStateException("Title must be set"); + } + + if (options.size() < 1) + { + throw new IllegalStateException("You must have atleast 1 option"); + } + + chatboxPanelManager.openInput(this); + } + + @Override + protected void open() + { + Widget container = chatboxPanelManager.getContainerWidget(); + + Widget prompt = container.createChild(-1, WidgetType.TEXT); + prompt.setText(title); + prompt.setTextColor(0x800000); + prompt.setFontId(FontID.QUILL_8); + prompt.setXPositionMode(WidgetPositionMode.ABSOLUTE_CENTER); + prompt.setOriginalX(0); + prompt.setYPositionMode(WidgetPositionMode.ABSOLUTE_TOP); + prompt.setOriginalY(8); + prompt.setOriginalHeight(24); + prompt.setXTextAlignment(WidgetTextAlignment.CENTER); + prompt.setYTextAlignment(WidgetTextAlignment.CENTER); + prompt.setWidthMode(WidgetSizeMode.MINUS); + prompt.revalidate(); + + int y = prompt.getRelativeX() + prompt.getHeight() + 6; + int height = container.getHeight() - y - 8; + int step = height / options.size(); + int maxStep = options.size() >= 3 ? 25 : 30; + if (step > maxStep) + { + int ds = step - maxStep; + step = maxStep; + y += (ds * options.size()) / 2; + } + + for (Entry option : options) + { + Widget optWidget = container.createChild(-1, WidgetType.TEXT); + optWidget.setText(option.text); + optWidget.setFontId(FontID.QUILL_8); + optWidget.setXPositionMode(WidgetPositionMode.ABSOLUTE_CENTER); + optWidget.setOriginalX(0); + optWidget.setYPositionMode(WidgetPositionMode.ABSOLUTE_TOP); + optWidget.setOriginalY(y); + optWidget.setOriginalHeight(24); + optWidget.setXTextAlignment(WidgetTextAlignment.CENTER); + optWidget.setYTextAlignment(WidgetTextAlignment.CENTER); + optWidget.setWidthMode(WidgetSizeMode.MINUS); + optWidget.setAction(0, "Continue"); + optWidget.setOnOpListener((JavaScriptCallback) ev -> callback(option)); + optWidget.setOnMouseOverListener((JavaScriptCallback) ev -> optWidget.setTextColor(0xFFFFFF)); + optWidget.setOnMouseLeaveListener((JavaScriptCallback) ev -> optWidget.setTextColor(0)); + optWidget.setHasListener(true); + optWidget.revalidate(); + + y += step; + } + } + + private void callback(Entry entry) + { + Widget container = chatboxPanelManager.getContainerWidget(); + container.setOnKeyListener((Object[]) null); + + chatboxPanelManager.close(); + + entry.callback.run(); + } + + @Override + protected void close() + { + if (onClose != null) + { + onClose.run(); + } + } + + + @Override + public void keyTyped(KeyEvent e) + { + char c = e.getKeyChar(); + + if (c == '\033') + { + chatboxPanelManager.close(); + e.consume(); + return; + } + + int n = c - '1'; + if (n >= 0 && n < options.size()) + { + callback(options.get(n)); + e.consume(); + } + } + + @Override + public void keyPressed(KeyEvent e) + { + if (e.getKeyCode() == KeyEvent.VK_ESCAPE) + { + e.consume(); + } + } + + @Override + public void keyReleased(KeyEvent e) + { + } +} diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TabInterface.java b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TabInterface.java index 35c2e42964..f8b25cf7b0 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TabInterface.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/banktags/tabs/TabInterface.java @@ -501,7 +501,7 @@ public class TabInterface { resetSearch(); - clientThread.invokeLater(() -> client.runScript(ScriptID.CLOSE_CHATBOX_INPUT)); + clientThread.invokeLater(() -> client.runScript(ScriptID.RESET_CHATBOX_INPUT)); } else { @@ -934,7 +934,7 @@ public class TabInterface { // 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.runScript(ScriptID.RESET_CHATBOX_INPUT); client.setVar(VarClientInt.INPUT_TYPE, inputType.getType()); client.setVar(VarClientStr.INPUT_TEXT, search); diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/WidgetInfoTableModel.java b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/WidgetInfoTableModel.java index 06124608c1..79bb99bc5a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/WidgetInfoTableModel.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/WidgetInfoTableModel.java @@ -148,6 +148,7 @@ public class WidgetInfoTableModel extends AbstractTableModel (w, str) -> w.setTextColor(Integer.parseInt(str, 16)), String.class )); + out.add(new WidgetField<>("Opacity", Widget::getOpacity, Widget::setOpacity, Integer.class)); out.add(new WidgetField<>("FontId", Widget::getFontId, Widget::setFontId, Integer.class)); out.add(new WidgetField<>("TextShadowed", Widget::getTextShadowed, Widget::setTextShadowed, Boolean.class)); out.add(new WidgetField<>("Name", w -> w.getName().trim(), Widget::setName, String.class)); @@ -156,23 +157,32 @@ public class WidgetInfoTableModel extends AbstractTableModel out.add(new WidgetField<>("ItemQuantityMode", Widget::getItemQuantityMode, Widget::setItemQuantityMode, Integer.class)); out.add(new WidgetField<>("ModelId", Widget::getModelId)); out.add(new WidgetField<>("SpriteId", Widget::getSpriteId, Widget::setSpriteId, Integer.class)); - out.add(new WidgetField<>("Width", Widget::getWidth, Widget::setWidth, Integer.class)); - out.add(new WidgetField<>("Height", Widget::getHeight, Widget::setHeight, Integer.class)); + out.add(new WidgetField<>("BorderType", Widget::getBorderType, Widget::setBorderType, Integer.class)); + out.add(new WidgetField<>("IsIf3", Widget::isIf3)); + out.add(new WidgetField<>("HasListener", Widget::hasListener, Widget::setHasListener, Boolean.class)); + out.add(new WidgetField<>("Filled", Widget::isFilled, Widget::setFilled, Boolean.class)); + out.add(new WidgetField<>("OriginalX", Widget::getOriginalX, Widget::setOriginalX, Integer.class)); + out.add(new WidgetField<>("OriginalY", Widget::getOriginalY, Widget::setOriginalY, Integer.class)); + out.add(new WidgetField<>("OriginalWidth", Widget::getOriginalWidth, Widget::setOriginalWidth, Integer.class)); + out.add(new WidgetField<>("OriginalHeight", Widget::getOriginalHeight, Widget::setOriginalHeight, Integer.class)); + out.add(new WidgetField<>("XPositionMode", Widget::getXPositionMode, Widget::setXPositionMode, Integer.class)); + out.add(new WidgetField<>("YPositionMode", Widget::getYPositionMode, Widget::setYPositionMode, Integer.class)); + out.add(new WidgetField<>("WidthMode", Widget::getWidthMode, Widget::setWidthMode, Integer.class)); + out.add(new WidgetField<>("HeightMode", Widget::getHeightMode, Widget::setHeightMode, Integer.class)); + out.add(new WidgetField<>("XTextAlignment", Widget::getXTextAlignment, Widget::setXTextAlignment, Integer.class)); + out.add(new WidgetField<>("YTextAlignment", Widget::getYTextAlignment, Widget::setYTextAlignment, Integer.class)); out.add(new WidgetField<>("RelativeX", Widget::getRelativeX, Widget::setRelativeX, Integer.class)); out.add(new WidgetField<>("RelativeY", Widget::getRelativeY, Widget::setRelativeY, Integer.class)); + out.add(new WidgetField<>("Width", Widget::getWidth, Widget::setWidth, Integer.class)); + out.add(new WidgetField<>("Height", Widget::getHeight, Widget::setHeight, Integer.class)); out.add(new WidgetField<>("CanvasLocation", Widget::getCanvasLocation)); out.add(new WidgetField<>("Bounds", Widget::getBounds)); out.add(new WidgetField<>("ScrollX", Widget::getScrollX, Widget::setScrollX, Integer.class)); out.add(new WidgetField<>("ScrollY", Widget::getScrollY, Widget::setScrollY, Integer.class)); out.add(new WidgetField<>("ScrollWidth", Widget::getScrollWidth, Widget::setScrollWidth, Integer.class)); out.add(new WidgetField<>("ScrollHeight", Widget::getScrollHeight, Widget::setScrollHeight, Integer.class)); - out.add(new WidgetField<>("OriginalX", Widget::getOriginalX)); - out.add(new WidgetField<>("OriginalY", Widget::getOriginalY)); - out.add(new WidgetField<>("BorderType", Widget::getBorderType, Widget::setBorderType, Integer.class)); out.add(new WidgetField<>("DragDeadZone", Widget::getDragDeadZone, Widget::setDragDeadZone, Integer.class)); out.add(new WidgetField<>("DragDeadTime", Widget::getDragDeadTime, Widget::setDragDeadTime, Integer.class)); - out.add(new WidgetField<>("IsIf3", Widget::isIf3)); - out.add(new WidgetField<>("HasListener", Widget::hasListener, Widget::setHasListener, Boolean.class)); return out; } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/WidgetInspector.java b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/WidgetInspector.java index 7921942948..0992bdec06 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/devtools/WidgetInspector.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/devtools/WidgetInspector.java @@ -142,6 +142,17 @@ class WidgetInspector extends JFrame onConfigChanged(null); bottomPanel.add(alwaysOnTop); + final JButton revalidateWidget = new JButton("Revalidate"); + revalidateWidget.addActionListener(ev -> clientThread.invokeLater(() -> + { + if (plugin.currentWidget == null) + { + return; + } + + plugin.currentWidget.revalidate(); + })); + bottomPanel.add(revalidateWidget); final JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, treeScrollPane, infoScrollPane); add(split, BorderLayout.CENTER); diff --git a/runelite-client/src/main/scripts/ResetChatboxInput.hash b/runelite-client/src/main/scripts/ResetChatboxInput.hash new file mode 100644 index 0000000000..9332eb1f8a --- /dev/null +++ b/runelite-client/src/main/scripts/ResetChatboxInput.hash @@ -0,0 +1 @@ +BA21C990EACCA53E54286CA139D58C3C7EA053BBB63C340B7BE4A0B91B156089 \ No newline at end of file diff --git a/runelite-client/src/main/scripts/ResetChatboxInput.rs2asm b/runelite-client/src/main/scripts/ResetChatboxInput.rs2asm new file mode 100644 index 0000000000..2ab7967304 --- /dev/null +++ b/runelite-client/src/main/scripts/ResetChatboxInput.rs2asm @@ -0,0 +1,180 @@ +.id 299 +.int_stack_count 2 +.string_stack_count 0 +.int_var_count 3 +.string_var_count 0 + load_string "resetChatboxInput" + runelite_callback + load_int 1 + load_int 10616872 + widget_put_hidden_widget + load_int 0 + load_int 10616887 + widget_put_hidden_widget + invoke 923 + load_int 0 + istore 2 + iload 1 + load_int 1 + if_icmpeq LABEL13 + jump LABEL27 +LABEL13: + invoke 553 + istore 2 + iload 2 + invoke 84 + iload 2 + invoke 89 + invoke 223 + load_int 1 + invoke 927 + invoke 1972 + load_int 1 + if_icmpeq LABEL26 + jump LABEL27 +LABEL26: + invoke 1984 +LABEL27: + invoke 1972 + load_int 1 + if_icmpeq LABEL31 + jump LABEL32 +LABEL31: + invoke 2581 +LABEL32: + load_int 0 + put_varc 5 + iload 0 + load_int 1 + if_icmpeq LABEL38 + jump LABEL40 +LABEL38: + load_string "" + put_varc_string 22 +LABEL40: + load_int 0 + load_int -8 + load_int 1 + load_int 1 + load_int 10616876 + widget_put_position_widget + load_int 0 + load_int 40 + load_int 1 + load_int 0 + load_int 10616876 + widget_put_size_widget + load_int 0 + load_int 22 + load_int 1 + load_int 1 + load_int 10616877 + widget_put_position_widget + load_int 0 + load_int 20 + load_int 1 + load_int 0 + load_int 10616877 + widget_put_size_widget + load_int 0 + load_int 10616876 + widget_put_hidden_widget + load_int 0 + load_int 10616877 + widget_put_hidden_widget + load_int 1 + load_int 10616881 + widget_put_hidden_widget + load_int 10616885 + widget_unset_children + load_int 10616886 + widget_unset_children + load_int -1 + load_string "" + load_int 10616872 + widget_put_mouse_press_listener_widget + load_int -1 + load_string "" + load_int 10616872 + widget_put_render_listener_widget + load_int 10616872 + widget_unset_children + load_int 10616878 + widget_unset_children + load_int 10616879 + widget_unset_children + load_int 10616880 + widget_unset_children + load_int 1 + load_int 10616878 + widget_put_hidden_widget + load_int 1 + load_int 10616879 + widget_put_hidden_widget + load_int 1 + load_int 10616880 + widget_put_hidden_widget + load_int -1 + load_string "" + load_int 10616878 + widget_put_mouse_hover_listener_widget + load_int -1 + load_string "" + load_int 10616879 + widget_put_mouse_hover_listener_widget + load_int -1 + load_string "" + load_int 10616880 + widget_put_mouse_hover_listener_widget + load_int -1 + load_string "" + load_int 10616878 + widget_put_mouse_exit_listener_widget + load_int -1 + load_string "" + load_int 10616879 + widget_put_mouse_exit_listener_widget + load_int -1 + load_string "" + load_int 10616880 + widget_put_mouse_exit_listener_widget + load_int -1 + load_string "" + load_int 10616878 + widget_put_render_listener_widget + load_int -1 + load_string "" + load_int 10616879 + widget_put_render_listener_widget + load_int -1 + load_string "" + load_int 10616880 + widget_put_render_listener_widget + load_int -1 + load_string "" + load_int 10616878 + widget_put_mouse_press_listener_widget + load_int -1 + load_string "" + load_int 10616879 + widget_put_mouse_press_listener_widget + load_int -1 + load_string "" + load_int 10616880 + widget_put_mouse_press_listener_widget + get_varc 41 + load_int -1 + if_icmpeq LABEL154 + jump LABEL156 +LABEL154: + invoke 2526 + pop_int +LABEL156: + invoke 1972 + load_int 1 + if_icmpeq LABEL160 + jump LABEL161 +LABEL160: + invoke 2581 +LABEL161: + return diff --git a/runelite-mixins/src/main/java/net/runelite/mixins/RSWidgetMixin.java b/runelite-mixins/src/main/java/net/runelite/mixins/RSWidgetMixin.java index a85d62000a..455c0c36a8 100644 --- a/runelite-mixins/src/main/java/net/runelite/mixins/RSWidgetMixin.java +++ b/runelite-mixins/src/main/java/net/runelite/mixins/RSWidgetMixin.java @@ -26,6 +26,7 @@ package net.runelite.mixins; import java.awt.Rectangle; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.List; import net.runelite.api.HashTable; @@ -559,4 +560,14 @@ public abstract class RSWidgetMixin implements RSWidget client.revalidateWidget(this); client.revalidateWidgetScroll(client.getWidgets()[TO_GROUP(this.getId())], this, false); } + + @Inject + @Override + public void deleteAllChildren() + { + if (getChildren() != null) + { + Arrays.fill(getChildren(), null); + } + } } diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSFontTypeFace.java b/runescape-api/src/main/java/net/runelite/rs/api/RSFontTypeFace.java new file mode 100644 index 0000000000..dca901798e --- /dev/null +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSFontTypeFace.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2018 Abex + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package net.runelite.rs.api; + +import net.runelite.api.FontTypeFace; +import net.runelite.mapping.Import; + +public interface RSFontTypeFace extends FontTypeFace +{ + @Import("getTextWidth") + @Override + int getTextWidth(String text); + + @Import("verticalSpace") + @Override + int getBaseline(); +} diff --git a/runescape-api/src/main/java/net/runelite/rs/api/RSWidget.java b/runescape-api/src/main/java/net/runelite/rs/api/RSWidget.java index 37999fae18..75315b0514 100644 --- a/runescape-api/src/main/java/net/runelite/rs/api/RSWidget.java +++ b/runescape-api/src/main/java/net/runelite/rs/api/RSWidget.java @@ -104,8 +104,13 @@ public interface RSWidget extends Widget void setTextColor(int textColor); @Import("opacity") + @Override int getOpacity(); + @Import("opacity") + @Override + void setOpacity(int opacity); + @Import("relativeX") @Override int getRelativeX(); @@ -311,6 +316,26 @@ public interface RSWidget extends Widget @Override Object[] getOnLoadListener(); + @Import("onDialogAbortListener") + @Override + void setOnDialogAbortListener(Object... args); + + @Import("onKeyListener") + @Override + void setOnKeyListener(Object... args); + + @Import("onMouseOverListener") + @Override + void setOnMouseOverListener(Object... args); + + @Import("onMouseLeaveListener") + @Override + void setOnMouseLeaveListener(Object... args); + + @Import("onTimerListener") + @Override + void setOnTimerListener(Object... args); + @Import("fontId") @Override int getFontId(); @@ -350,4 +375,64 @@ public interface RSWidget extends Widget @Import("itemQuantityMode") @Override void setItemQuantityMode(int itemQuantityMode); + + @Import("xPositionMode") + @Override + int getXPositionMode(); + + @Import("xPositionMode") + @Override + void setXPositionMode(int xpm); + + @Import("yPositionMode") + @Override + int getYPositionMode(); + + @Import("yPositionMode") + @Override + void setYPositionMode(int ypm); + + @Import("xTextAlignment") + @Override + int getXTextAlignment(); + + @Import("xTextAlignment") + @Override + void setXTextAlignment(int xta); + + @Import("yTextAlignment") + @Override + int getYTextAlignment(); + + @Import("yTextAlignment") + @Override + void setYTextAlignment(int yta); + + @Import("widthMode") + @Override + int getWidthMode(); + + @Import("widthMode") + @Override + void setWidthMode(int widthMode); + + @Import("heightMode") + @Override + int getHeightMode(); + + @Import("heightMode") + @Override + void setHeightMode(int heightMode); + + @Import("getFont") + @Override + RSFontTypeFace getFont(); + + @Import("filled") + @Override + boolean isFilled(); + + @Import("filled") + @Override + void setFilled(boolean filled); }