* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,7 +36,7 @@ public enum ControlFunction
CONTROL_TO_ZOOM("Hold to zoom"),
CONTROL_TO_RESET("Reset zoom");
- private String name;
+ private final String name;
@Override
public String toString()
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/zoom/ZoomConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/zoom/ZoomConfig.java
index d3fb50007b..91821ba91b 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/zoom/ZoomConfig.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/zoom/ZoomConfig.java
@@ -1,3 +1,27 @@
+/*
+ * 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.plugins.zoom;
import net.runelite.client.config.Config;
@@ -48,12 +72,11 @@ public interface ZoomConfig extends Config
return false;
}
-
@ConfigItem(
keyName = "controlFunction",
name = "Control Function",
description = "Configures the zoom function when control is pressed",
- position = 5
+ position = 4
)
default ControlFunction controlFunction()
{
@@ -64,18 +87,22 @@ public interface ZoomConfig extends Config
keyName = "ctrlZoomValue",
name = "Reset zoom position",
description = "Position of zoom when it is reset",
- position = 6
+ position = 5
+ )
+ @Range(
+ min = OUTER_LIMIT_MIN,
+ max = OUTER_LIMIT_MAX
)
default int ctrlZoomValue()
{
- return 600;
+ return 512;
}
@ConfigItem(
keyName = "zoomIncrement",
name = "Zoom Speed",
description = "Speed of zoom",
- position = 7
+ position = 6
)
default int zoomIncrement()
{
diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/zoom/ZoomPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/zoom/ZoomPlugin.java
index 634c9fe06a..86ab17454d 100644
--- a/runelite-client/src/main/java/net/runelite/client/plugins/zoom/ZoomPlugin.java
+++ b/runelite-client/src/main/java/net/runelite/client/plugins/zoom/ZoomPlugin.java
@@ -52,10 +52,11 @@ public class ZoomPlugin extends Plugin implements KeyListener
{
/**
* The largest (most zoomed in) value that can be used without the client crashing.
- *
+ *
* Larger values trigger an overflow in the engine's fov to scale code.
*/
private static final int INNER_ZOOM_LIMIT = 1004;
+ private static final int DEFAULT_ZOOM_INCREMENT = 25;
private boolean controlDown;
@@ -90,7 +91,7 @@ public class ZoomPlugin extends Plugin implements KeyListener
int[] intStack = client.getIntStack();
int intStackSize = client.getIntStackSize();
- if ("scrollWheelZoom".equals(event.getEventName()) && zoomConfig.controlFunction() == ControlFunction.CONTROL_TO_ZOOM && !controlDown)
+ if (!controlDown && "scrollWheelZoom".equals(event.getEventName()) && zoomConfig.controlFunction() == ControlFunction.CONTROL_TO_ZOOM)
{
intStack[intStackSize - 1] = 1;
}
@@ -109,9 +110,10 @@ public class ZoomPlugin extends Plugin implements KeyListener
return;
}
- if ("scrollWheelZoomIncrement".equals(event.getEventName()) && zoomConfig.zoomIncrement() != 25)
+ if ("scrollWheelZoomIncrement".equals(event.getEventName()) && zoomConfig.zoomIncrement() != DEFAULT_ZOOM_INCREMENT)
{
intStack[intStackSize - 1] = zoomConfig.zoomIncrement();
+ return;
}
if (zoomConfig.innerLimit())
@@ -190,6 +192,7 @@ public class ZoomPlugin extends Plugin implements KeyListener
if (e.getKeyCode() == KeyEvent.VK_CONTROL)
{
controlDown = false;
+
if (zoomConfig.controlFunction() == ControlFunction.CONTROL_TO_RESET)
{
final int zoomValue = MiscUtils.clamp(zoomConfig.ctrlZoomValue(), zoomConfig.OUTER_LIMIT_MIN, INNER_ZOOM_LIMIT);
diff --git a/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java b/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java
index 8b3fc96130..4433d3824f 100644
--- a/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java
+++ b/runelite-client/src/main/java/net/runelite/client/ui/ClientUI.java
@@ -871,7 +871,15 @@ public class ClientUI
}
frame.setExpandResizeType(config.automaticResizeType());
- frame.setContainedInScreen(config.containInScreen() && withTitleBar);
+
+ ContainableFrame.Mode containMode = config.containInScreen();
+ if (containMode == ContainableFrame.Mode.ALWAYS && !withTitleBar)
+ {
+ // When native window decorations are enabled we don't have a way to receive window move events
+ // so we can't contain to screen always.
+ containMode = ContainableFrame.Mode.RESIZING;
+ }
+ frame.setContainedInScreen(containMode);
if (!config.rememberScreenBounds())
{
diff --git a/runelite-client/src/main/java/net/runelite/client/ui/ContainableFrame.java b/runelite-client/src/main/java/net/runelite/client/ui/ContainableFrame.java
index 1a528f75aa..7d03d05ef3 100644
--- a/runelite-client/src/main/java/net/runelite/client/ui/ContainableFrame.java
+++ b/runelite-client/src/main/java/net/runelite/client/ui/ContainableFrame.java
@@ -32,11 +32,18 @@ import net.runelite.client.config.ExpandResizeType;
public class ContainableFrame extends JFrame
{
+ public enum Mode
+ {
+ ALWAYS,
+ RESIZING,
+ NEVER;
+ }
+
private static final int SCREEN_EDGE_CLOSE_DISTANCE = 40;
@Setter
private ExpandResizeType expandResizeType;
- private boolean containedInScreen;
+ private Mode containedInScreen;
private boolean expandedClientOppositeDirection;
ContainableFrame()
@@ -50,11 +57,11 @@ public class ContainableFrame extends JFrame
});
}
- public void setContainedInScreen(boolean value)
+ public void setContainedInScreen(Mode value)
{
this.containedInScreen = value;
- if (value)
+ if (this.containedInScreen == Mode.ALWAYS)
{
// Reposition the frame if it is intersecting with the bounds
this.setLocation(this.getX(), this.getY());
@@ -65,7 +72,7 @@ public class ContainableFrame extends JFrame
@Override
public void setLocation(int x, int y)
{
- if (containedInScreen)
+ if (this.containedInScreen == Mode.ALWAYS)
{
Rectangle bounds = this.getGraphicsConfiguration().getBounds();
x = Math.max(x, (int) bounds.getX());
@@ -80,8 +87,10 @@ public class ContainableFrame extends JFrame
@Override
public void setBounds(int x, int y, int width, int height)
{
- if (containedInScreen)
+ if (this.containedInScreen == Mode.ALWAYS)
{
+ // XXX: this is wrong if setSize/resize is called because Component::resize sets private state that is read
+ // in Window::setBounds
Rectangle bounds = this.getGraphicsConfiguration().getBounds();
width = Math.min(width, width - (int) bounds.getX() + x);
x = Math.max(x, (int) bounds.getX());
@@ -127,7 +136,7 @@ public class ContainableFrame extends JFrame
final int newWindowWidth = getWidth() + increment;
int newWindowX = getX();
- if (containedInScreen)
+ if (this.containedInScreen != Mode.NEVER)
{
final Rectangle screenBounds = getGraphicsConfiguration().getBounds();
final boolean wouldExpandThroughEdge = getX() + newWindowWidth > screenBounds.getX() + screenBounds.getWidth();
diff --git a/runelite-client/src/main/java/net/runelite/client/ui/components/colorpicker/ColorPickerManager.java b/runelite-client/src/main/java/net/runelite/client/ui/components/colorpicker/ColorPickerManager.java
new file mode 100644
index 0000000000..f85c226784
--- /dev/null
+++ b/runelite-client/src/main/java/net/runelite/client/ui/components/colorpicker/ColorPickerManager.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2019, Ron Young
+ * 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.ui.components.colorpicker;
+
+import java.awt.Color;
+import java.awt.Window;
+import java.awt.event.WindowEvent;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.Setter;
+import net.runelite.client.config.ConfigManager;
+
+@Singleton
+public class ColorPickerManager
+{
+ private final ConfigManager configManager;
+
+ @Setter(AccessLevel.PACKAGE)
+ @Getter(AccessLevel.PACKAGE)
+ private RuneliteColorPicker currentPicker;
+
+ @Inject
+ private ColorPickerManager(final ConfigManager configManager)
+ {
+ this.configManager = configManager;
+ }
+
+ public RuneliteColorPicker create(Window owner, Color previousColor, String title, boolean alphaHidden)
+ {
+ if (currentPicker != null)
+ {
+ currentPicker.dispatchEvent(new WindowEvent(currentPicker, WindowEvent.WINDOW_CLOSING));
+ }
+
+ currentPicker = new RuneliteColorPicker(owner, previousColor, title, alphaHidden, configManager, this);
+ return currentPicker;
+ }
+}
diff --git a/runelite-client/src/main/java/net/runelite/client/ui/components/colorpicker/RecentColors.java b/runelite-client/src/main/java/net/runelite/client/ui/components/colorpicker/RecentColors.java
new file mode 100644
index 0000000000..fcb69a3198
--- /dev/null
+++ b/runelite-client/src/main/java/net/runelite/client/ui/components/colorpicker/RecentColors.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2019, Ron Young
+ * 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.ui.components.colorpicker;
+
+import com.google.common.collect.EvictingQueue;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.function.Consumer;
+import javax.swing.JPanel;
+import net.runelite.client.config.ConfigManager;
+import static net.runelite.client.ui.components.colorpicker.RuneliteColorPicker.CONFIG_GROUP;
+import net.runelite.client.util.ColorUtil;
+import net.runelite.client.util.Text;
+
+final class RecentColors
+{
+ private static final String CONFIG_KEY = "recentColors";
+ private static final int MAX = 16;
+ private static final int BOX_SIZE = 16;
+
+ private final EvictingQueue recentColors = EvictingQueue.create(MAX);
+ private final ConfigManager configManager;
+
+ RecentColors(final ConfigManager configManager)
+ {
+ this.configManager = configManager;
+ }
+
+ private void load()
+ {
+ String str = configManager.getConfiguration(CONFIG_GROUP, CONFIG_KEY);
+ if (str != null)
+ {
+ recentColors.addAll(Text.fromCSV(str));
+ }
+ }
+
+ void add(final String color)
+ {
+ if (ColorUtil.fromString(color) == null)
+ {
+ return;
+ }
+
+ recentColors.remove(color);
+ recentColors.add(color);
+
+ configManager.setConfiguration(CONFIG_GROUP, CONFIG_KEY, Text.toCSV(recentColors));
+ }
+
+ JPanel build(final Consumer consumer, final boolean alphaHidden)
+ {
+ load();
+
+ JPanel container = new JPanel(new GridBagLayout());
+
+ GridBagConstraints cx = new GridBagConstraints();
+ cx.insets = new Insets(0, 1, 4, 2);
+ cx.gridy = 0;
+ cx.gridx = 0;
+ cx.anchor = GridBagConstraints.WEST;
+
+ for (String s : recentColors)
+ {
+ if (cx.gridx == MAX / 2)
+ {
+ cx.gridy++;
+ cx.gridx = 0;
+ }
+
+ // Make sure the last element stays in line with all of the others
+ if (container.getComponentCount() == recentColors.size() - 1)
+ {
+ cx.weightx = 1;
+ cx.gridwidth = MAX / 2 - cx.gridx;
+ }
+
+ container.add(createBox(ColorUtil.fromString(s), consumer, alphaHidden), cx);
+ cx.gridx++;
+ }
+
+ return container;
+ }
+
+ private static JPanel createBox(final Color color, final Consumer consumer, final boolean alphaHidden)
+ {
+ final JPanel box = new JPanel();
+ String hex = alphaHidden ? ColorUtil.colorToHexCode(color) : ColorUtil.colorToAlphaHexCode(color);
+
+ box.setBackground(color);
+ box.setOpaque(true);
+ box.setPreferredSize(new Dimension(BOX_SIZE, BOX_SIZE));
+ box.setToolTipText("#" + hex.toUpperCase());
+ box.addMouseListener(new MouseAdapter()
+ {
+ @Override
+ public void mouseClicked(MouseEvent e)
+ {
+ consumer.accept(color);
+ }
+ });
+
+ return box;
+ }
+}
diff --git a/runelite-client/src/main/java/net/runelite/client/ui/components/colorpicker/RuneliteColorPicker.java b/runelite-client/src/main/java/net/runelite/client/ui/components/colorpicker/RuneliteColorPicker.java
index 81d6780d70..653d31ecf8 100644
--- a/runelite-client/src/main/java/net/runelite/client/ui/components/colorpicker/RuneliteColorPicker.java
+++ b/runelite-client/src/main/java/net/runelite/client/ui/components/colorpicker/RuneliteColorPicker.java
@@ -39,6 +39,9 @@ import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.util.Objects;
import java.util.function.Consumer;
import javax.swing.JDialog;
import javax.swing.JFrame;
@@ -53,12 +56,15 @@ import javax.swing.text.Document;
import javax.swing.text.DocumentFilter;
import lombok.Getter;
import lombok.Setter;
+import net.runelite.client.config.ConfigManager;
import net.runelite.client.ui.ColorScheme;
import net.runelite.client.util.ColorUtil;
import org.pushingpixels.substance.internal.SubstanceSynapse;
public class RuneliteColorPicker extends JDialog
{
+ static final String CONFIG_GROUP = "colorpicker";
+
private final static int FRAME_WIDTH = 400;
private final static int FRAME_HEIGHT = 380;
private final static int TONE_PANEL_SIZE = 160;
@@ -84,16 +90,24 @@ public class RuneliteColorPicker extends JDialog
@Setter
private Consumer onColorChange;
- public RuneliteColorPicker(Window parent, Color previousColor, String title, boolean alphaHidden)
+ @Setter
+ private Consumer onClose;
+
+ RuneliteColorPicker(Window parent, Color previousColor, String title, boolean alphaHidden,
+ final ConfigManager configManager, final ColorPickerManager colorPickerManager)
{
super(parent, "RuneLite Color Picker - " + title, ModalityType.MODELESS);
this.selectedColor = previousColor;
+ this.alphaHidden = alphaHidden;
+
+ RecentColors recentColors = new RecentColors(configManager);
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setResizable(false);
setSize(FRAME_WIDTH, FRAME_HEIGHT);
setBackground(ColorScheme.PROGRESS_COMPLETE_COLOR);
+ setDefaultCloseOperation(DISPOSE_ON_CLOSE);
JPanel content = new JPanel(new BorderLayout());
content.putClientProperty(SubstanceSynapse.COLORIZATION_FACTOR, 1.0);
@@ -109,7 +123,6 @@ public class RuneliteColorPicker extends JDialog
rightPanel.setLayout(new GridBagLayout());
GridBagConstraints cx = new GridBagConstraints();
-
cx.insets = new Insets(0, 0, 0, 0);
JLabel old = new JLabel("Previous");
old.setHorizontalAlignment(JLabel.CENTER);
@@ -140,11 +153,26 @@ public class RuneliteColorPicker extends JDialog
hexContainer.add(hexInput, cx);
cx.fill = GridBagConstraints.BOTH;
- cx.gridwidth = GridBagConstraints.RELATIVE;
cx.weightx = 1;
cx.weighty = 1;
cx.gridy = 0;
cx.gridx = 0;
+
+ JPanel recentColorsContainer = recentColors.build(c ->
+ {
+ if (!alphaHidden)
+ {
+ alphaSlider.update(c.getAlpha());
+ }
+
+ colorChange(c);
+ updatePanels();
+ }, alphaHidden);
+
+ rightPanel.add(recentColorsContainer, cx);
+
+ cx.gridwidth = GridBagConstraints.RELATIVE;
+ cx.gridy++;
rightPanel.add(old, cx);
cx.gridx++;
@@ -176,7 +204,6 @@ public class RuneliteColorPicker extends JDialog
slidersContainer.add(blueSlider);
slidersContainer.add(alphaSlider);
- this.alphaHidden = alphaHidden;
if (alphaHidden)
{
alphaSlider.setVisible(false);
@@ -265,6 +292,29 @@ public class RuneliteColorPicker extends JDialog
updatePanels();
updateText();
+
+ addWindowListener(new WindowAdapter()
+ {
+ @Override
+ public void windowClosing(WindowEvent e)
+ {
+ if (onClose != null)
+ {
+ onClose.accept(selectedColor);
+ }
+
+ if (!Objects.equals(previousColor, selectedColor))
+ {
+ recentColors.add(selectedColor.getRGB() + "");
+ }
+
+ RuneliteColorPicker cp = colorPickerManager.getCurrentPicker();
+ if (Objects.equals(cp, RuneliteColorPicker.this))
+ {
+ colorPickerManager.setCurrentPicker(null);
+ }
+ }
+ });
}
private void updatePanels()
diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/InfoBoxComponent.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/InfoBoxComponent.java
index 3a433ffb15..b643bc0062 100644
--- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/InfoBoxComponent.java
+++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/components/InfoBoxComponent.java
@@ -29,9 +29,9 @@ import java.awt.Color;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
-import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
+import java.awt.image.BufferedImage;
import lombok.Getter;
import lombok.Setter;
import net.runelite.client.ui.FontManager;
@@ -53,7 +53,7 @@ public class InfoBoxComponent implements LayoutableRenderableEntity
private String text;
private Color color = Color.WHITE;
private Color backgroundColor = ComponentConstants.STANDARD_BACKGROUND_COLOR;
- private Image image;
+ private BufferedImage image;
@Override
public Dimension render(Graphics2D graphics)
diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBox.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBox.java
index 8c2889e8e6..fab945c11b 100644
--- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBox.java
+++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBox.java
@@ -25,7 +25,7 @@
package net.runelite.client.ui.overlay.infobox;
import java.awt.Color;
-import java.awt.Image;
+import java.awt.image.BufferedImage;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.Setter;
@@ -38,11 +38,11 @@ public abstract class InfoBox
@Getter
@Setter
- private Image image;
+ private BufferedImage image;
@Getter(AccessLevel.PACKAGE)
@Setter(AccessLevel.PACKAGE)
- private Image scaledImage;
+ private BufferedImage scaledImage;
@Getter(AccessLevel.PACKAGE)
@Setter
@@ -52,7 +52,7 @@ public abstract class InfoBox
@Setter
private String tooltip;
- public InfoBox(Image image, Plugin plugin)
+ public InfoBox(BufferedImage image, Plugin plugin)
{
this.plugin = plugin;
setImage(image);
diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxManager.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxManager.java
index 56ef1a66fd..203af21939 100644
--- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxManager.java
+++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/infobox/InfoBoxManager.java
@@ -27,7 +27,6 @@ package net.runelite.client.ui.overlay.infobox;
import com.google.common.base.Preconditions;
import com.google.common.collect.ComparisonChain;
import java.awt.Graphics;
-import java.awt.Image;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.Collections;
@@ -40,6 +39,7 @@ import lombok.extern.slf4j.Slf4j;
import net.runelite.api.events.ConfigChanged;
import net.runelite.client.config.RuneLiteConfig;
import net.runelite.client.eventbus.Subscribe;
+import net.runelite.client.game.AsyncBufferedImage;
import net.runelite.client.plugins.PluginDescriptor;
@Singleton
@@ -72,6 +72,14 @@ public class InfoBoxManager
updateInfoBoxImage(infoBox);
infoBoxes.add(infoBox);
refreshInfoBoxes();
+
+ BufferedImage image = infoBox.getImage();
+
+ if (image instanceof AsyncBufferedImage)
+ {
+ AsyncBufferedImage abi = (AsyncBufferedImage) image;
+ abi.onChanged(() -> updateInfoBoxImage(infoBox));
+ }
}
public void removeInfoBox(InfoBox infoBox)
@@ -118,7 +126,7 @@ public class InfoBoxManager
}
}
- private void updateInfoBoxImage(final InfoBox infoBox)
+ public void updateInfoBoxImage(final InfoBox infoBox)
{
if (infoBox.getImage() == null)
{
@@ -126,8 +134,8 @@ public class InfoBoxManager
}
// Set scaled InfoBox image
- final Image image = infoBox.getImage();
- Image resultImage = image;
+ final BufferedImage image = infoBox.getImage();
+ BufferedImage resultImage = image;
final double width = image.getWidth(null);
final double height = image.getHeight(null);
final double size = Math.max(2, runeLiteConfig.infoBoxSize()); // Limit size to 2 as that is minimum size not causing breakage
diff --git a/runelite-client/src/main/resources/net/runelite/client/plugins/grandexchange/ge_limits.json b/runelite-client/src/main/resources/net/runelite/client/plugins/grandexchange/ge_limits.json
index 37072ae9b1..bba7233ee1 100644
--- a/runelite-client/src/main/resources/net/runelite/client/plugins/grandexchange/ge_limits.json
+++ b/runelite-client/src/main/resources/net/runelite/client/plugins/grandexchange/ge_limits.json
@@ -3088,6 +3088,7 @@
"19627": 10000,
"19629": 10000,
"19631": 10000,
+ "19653": 100,
"19656": 13000,
"19662": 10000,
"19665": 13000,
diff --git a/runelite-client/src/main/scripts/ScrollWheelZoomHandler.rs2asm b/runelite-client/src/main/scripts/ScrollWheelZoomHandler.rs2asm
index c9a0d99f8d..b5f275eab2 100644
--- a/runelite-client/src/main/scripts/ScrollWheelZoomHandler.rs2asm
+++ b/runelite-client/src/main/scripts/ScrollWheelZoomHandler.rs2asm
@@ -11,9 +11,9 @@
iconst 0
iload 0
iconst 25
- sconst "scrollWheelZoomIncrement"
+ sconst "scrollWheelZoomIncrement"
runelite_callback
- multiply
+ multiply
sub
istore 1
iconst 512
diff --git a/runelite-client/src/test/java/net/runelite/client/plugins/slayer/SlayerPluginTest.java b/runelite-client/src/test/java/net/runelite/client/plugins/slayer/SlayerPluginTest.java
index 169caac2a9..07cb08987b 100644
--- a/runelite-client/src/test/java/net/runelite/client/plugins/slayer/SlayerPluginTest.java
+++ b/runelite-client/src/test/java/net/runelite/client/plugins/slayer/SlayerPluginTest.java
@@ -34,8 +34,10 @@ import net.runelite.api.ChatMessageType;
import static net.runelite.api.ChatMessageType.GAMEMESSAGE;
import net.runelite.api.Client;
import net.runelite.api.MessageNode;
+import net.runelite.api.Skill;
import net.runelite.api.Varbits;
import net.runelite.api.events.ChatMessage;
+import net.runelite.api.events.ExperienceChanged;
import net.runelite.api.events.GameTick;
import net.runelite.api.events.VarbitChanged;
import net.runelite.api.widgets.Widget;
@@ -362,6 +364,9 @@ public class SlayerPluginTest
slayerPlugin.getCurrentTask().setTaskName("cows");
slayerPlugin.getCurrentTask().setAmount(42);
+ final ExperienceChanged experienceChanged = new ExperienceChanged();
+ experienceChanged.setSkill(Skill.SLAYER);
+
ChatMessage chatMessageEvent = new ChatMessage(null, GAMEMESSAGE, "Perterter", TASK_COMPLETE, null, 0);
slayerPlugin.onChatMessage(chatMessageEvent);