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
*
* - int (boolean) Clear the current text
- * - int (boolean) Unknown; set to 1
+ * - int (boolean) Restore to chat view
*
*/
- 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);
}