diff --git a/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java b/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java index df9ad2245c..80ca50edf9 100644 --- a/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java +++ b/runelite-client/src/main/java/net/runelite/client/callback/Hooks.java @@ -296,6 +296,9 @@ public class Hooks implements Callbacks notifier.processFlash(graphics2d); + // Draw clientUI overlays + clientUi.paintOverlays(graphics2d); + // Stretch the game image if the user has that enabled if (client.isStretchedEnabled()) { 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 48ed636d98..04017b3a42 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 @@ -34,12 +34,14 @@ import java.awt.Container; import java.awt.Cursor; import java.awt.Dimension; import java.awt.Graphics; +import java.awt.Graphics2D; import java.awt.GraphicsConfiguration; import java.awt.LayoutManager; import java.awt.Rectangle; import java.awt.TrayIcon; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; import javax.annotation.Nullable; import javax.inject.Inject; @@ -64,6 +66,8 @@ import net.runelite.api.Player; import net.runelite.api.Point; import net.runelite.api.events.ConfigChanged; import net.runelite.api.events.GameStateChanged; +import net.runelite.api.widgets.Widget; +import net.runelite.api.widgets.WidgetInfo; import net.runelite.client.RuneLite; import net.runelite.client.RuneLiteProperties; import net.runelite.client.callback.ClientThread; @@ -75,6 +79,9 @@ import net.runelite.client.config.WarningOnExit; import net.runelite.client.events.NavigationButtonAdded; import net.runelite.client.events.NavigationButtonRemoved; import net.runelite.client.input.KeyManager; +import net.runelite.client.input.MouseAdapter; +import net.runelite.client.input.MouseListener; +import net.runelite.client.input.MouseManager; import net.runelite.client.ui.skin.SubstanceRuneLiteLookAndFeel; import net.runelite.client.util.HotkeyListener; import net.runelite.client.util.ImageUtil; @@ -114,10 +121,12 @@ public class ClientUI private final RuneLiteProperties properties; private final RuneLiteConfig config; private final KeyManager keyManager; + private final MouseManager mouseManager; private final Applet client; private final ConfigManager configManager; private final Provider clientThreadProvider; private final CardLayout cardLayout = new CardLayout(); + private final Rectangle sidebarButtonPosition = new Rectangle(); private ContainableFrame frame; private JPanel navContainer; private PluginPanel pluginPanel; @@ -136,6 +145,7 @@ public class ClientUI RuneLiteProperties properties, RuneLiteConfig config, KeyManager keyManager, + MouseManager mouseManager, @Nullable Applet client, ConfigManager configManager, Provider clientThreadProvider) @@ -143,6 +153,7 @@ public class ClientUI this.properties = properties; this.config = config; this.keyManager = keyManager; + this.mouseManager = mouseManager; this.client = client; this.configManager = configManager; this.clientThreadProvider = clientThreadProvider; @@ -352,6 +363,24 @@ public class ClientUI keyManager.registerKeyListener(sidebarListener); + // Add mouse listener + final MouseListener mouseListener = new MouseAdapter() + { + @Override + public MouseEvent mousePressed(MouseEvent mouseEvent) + { + if (SwingUtilities.isLeftMouseButton(mouseEvent) && sidebarButtonPosition.contains(mouseEvent.getPoint())) + { + SwingUtilities.invokeLater(ClientUI.this::toggleSidebar); + mouseEvent.consume(); + } + + return mouseEvent; + } + }; + + mouseManager.registerMouseListener(mouseListener); + // Decorate window with custom chrome and titlebar if needed final boolean withTitleBar = config.enableCustomChrome(); frame.setUndecorated(withTitleBar); @@ -583,12 +612,39 @@ public class ClientUI return new Point(0, 0); } + /** + * Paint UI related overlays to target graphics + * @param graphics target graphics + */ + public void paintOverlays(final Graphics2D graphics) + { + if (!(client instanceof Client) || config.enableCustomChrome()) + { + return; + } + + final Client client = (Client)this.client; + final int x = client.getRealDimensions().width - SIDEBAR_OPEN.getWidth() - 5; + + // Offset sidebar button if resizable mode logout is visible + final Widget logoutButton = client.getWidget(WidgetInfo.RESIZABLE_VIEWPORT_BOTTOM_LINE_LOGOUT_BUTTON); + final int y = logoutButton != null && !logoutButton.isHidden() && logoutButton.getParent() != null + ? logoutButton.getHeight() + logoutButton.getRelativeY() + 5 + : 5; + + final BufferedImage image = sidebarOpen ? SIDEBAR_OPEN : SIDEBAR_CLOSE; + graphics.drawImage(image, x, y, null); + + // Update button dimensions + sidebarButtonPosition.setBounds(x, y, image.getWidth(), image.getHeight()); + } + public GraphicsConfiguration getGraphicsConfiguration() { return frame.getGraphicsConfiguration(); } - void toggleSidebar() + private void toggleSidebar() { // Toggle sidebar open boolean isSidebarOpen = sidebarOpen; diff --git a/runelite-client/src/main/java/net/runelite/client/util/SwingUtil.java b/runelite-client/src/main/java/net/runelite/client/util/SwingUtil.java index e951393709..7caa72308a 100644 --- a/runelite-client/src/main/java/net/runelite/client/util/SwingUtil.java +++ b/runelite-client/src/main/java/net/runelite/client/util/SwingUtil.java @@ -26,13 +26,10 @@ package net.runelite.client.util; import java.awt.AWTException; import java.awt.Color; -import java.awt.Dimension; import java.awt.Font; import java.awt.Frame; import java.awt.Image; -import java.awt.Rectangle; import java.awt.SystemTray; -import java.awt.Toolkit; import java.awt.TrayIcon; import java.awt.Window; import java.awt.event.MouseAdapter; @@ -186,20 +183,6 @@ public class SwingUtil return trayIcon; } - /** - * Check if point is in screen bounds. - * - * @param x the x - * @param y the y - * @return the boolean - */ - public static boolean isInScreenBounds(final int x, final int y) - { - final Dimension size = Toolkit.getDefaultToolkit().getScreenSize(); - final Rectangle bounds = new Rectangle(size); - return bounds.contains(x, y); - } - /** * Add graceful exit callback. * @@ -261,7 +244,7 @@ public class SwingUtil : navigationButton.getIcon(); final JButton button = new JButton(); - button.setMaximumSize(new Dimension(30, 30)); + button.setSize(scaledImage.getWidth(), scaledImage.getHeight()); button.setToolTipText(navigationButton.getTooltip()); button.setIcon(new ImageIcon(scaledImage)); button.putClientProperty(SubstanceSynapse.FLAT_LOOK, Boolean.TRUE);