From ae18d2a865240103a0a58b564f32e6de6f20499e Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 6 Jan 2021 17:39:14 -0500 Subject: [PATCH] overlay: fix layouted overlays not respecting parent bounds This clamps layouted overlays to their parent's bounds, and also adjusts the snap corner for the shifted position that is a result of the clamp, so that the following overlays correctly get layouted. --- .../client/ui/overlay/OverlayRenderer.java | 48 +++++++++++-------- .../client/ui/overlay/OverlayUtil.java | 10 ++-- 2 files changed, 33 insertions(+), 25 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java index e1666d8b14..5c01f578c8 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayRenderer.java @@ -266,29 +266,35 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener else { final Rectangle bounds = overlay.getBounds(); - final Point location = bounds.getLocation(); final Dimension dimension = bounds.getSize(); - final Point preferredLocation = overlay.getPreferredLocation(); + Point location; // If the final position is not modified, layout it if (overlayPosition != OverlayPosition.DETACHED && (preferredLocation == null || overlay.getPreferredPosition() != null)) { final Rectangle snapCorner = snapCorners.forPosition(overlayPosition); - final Point translation = OverlayUtil.transformPosition(overlayPosition, dimension); - location.setLocation(snapCorner.getX() + translation.x, snapCorner.getY() + translation.y); - final Point padding = OverlayUtil.padPosition(overlayPosition, dimension, PADDING); - snapCorner.translate(padding.x, padding.y); + final Point translation = OverlayUtil.transformPosition(overlayPosition, dimension); // offset from corner + // Target x/y to draw the overlay + int destX = (int) snapCorner.getX() + translation.x; + int destY = (int) snapCorner.getY() + translation.y; + // Clamp the target position to ensure it is on screen or within parent bounds + location = clampOverlayLocation(destX, destY, dimension.width, dimension.height, overlay); + // Diff final position to target position in order to add it to the snap corner padding. The + // overlay effectively takes up the difference of (clamped location - target location) in + // addition to its normal dimensions. + int dX = location.x - destX; + int dY = location.y - destY; + final Point padding = OverlayUtil.padPosition(overlayPosition, dimension, PADDING); // overlay size + fixed padding + // translate corner for padding and any difference due to the position clamping + snapCorner.translate(padding.x + dX, padding.y + dY); } else { - if (preferredLocation != null) - { - location.setLocation(preferredLocation); - } + location = preferredLocation != null ? preferredLocation : bounds.getLocation(); // Clamp the overlay position to ensure it is on screen or within parent bounds - clampOverlayLocation(location, dimension.width, dimension.height, overlay); + location = clampOverlayLocation(location.x, location.y, dimension.width, dimension.height, overlay); } if (overlay.getPreferredSize() != null) @@ -605,7 +611,7 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener // Clamp drag to parent component final Rectangle overlayBounds = currentManagedOverlay.getBounds(); - clampOverlayLocation(overlayPosition, overlayBounds.width, overlayBounds.height, currentManagedOverlay); + overlayPosition = clampOverlayLocation(overlayPosition.x, overlayPosition.y, overlayBounds.width, overlayBounds.height, currentManagedOverlay); currentManagedOverlay.setPreferredPosition(null); currentManagedOverlay.setPreferredLocation(overlayPosition); } @@ -920,12 +926,14 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener /** * Adjust the given overlay position to be within its parent's bounds. * - * @param overlayPosition the overlay position, which is modified in place + * @param overlayX + * @param overlayY * @param overlayWidth * @param overlayHeight - * @param overlay the overlay + * @param overlay the overlay + * @return the clamped position */ - private void clampOverlayLocation(Point overlayPosition, int overlayWidth, int overlayHeight, Overlay overlay) + private Point clampOverlayLocation(int overlayX, int overlayY, int overlayWidth, int overlayHeight, Overlay overlay) { Rectangle parentBounds = overlay.getParentBounds(); if (parentBounds == null || parentBounds.isEmpty()) @@ -936,9 +944,11 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener } // Constrain overlay position to be within the parent bounds - overlayPosition.x = Ints.constrainToRange(overlayPosition.x, parentBounds.x, - Math.max(parentBounds.x, parentBounds.width - overlayWidth)); - overlayPosition.y = Ints.constrainToRange(overlayPosition.y, parentBounds.y, - Math.max(parentBounds.y, parentBounds.height - overlayHeight)); + return new Point( + Ints.constrainToRange(overlayX, parentBounds.x, + Math.max(parentBounds.x, parentBounds.width - overlayWidth)), + Ints.constrainToRange(overlayY, parentBounds.y, + Math.max(parentBounds.y, parentBounds.height - overlayHeight)) + ); } } diff --git a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayUtil.java b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayUtil.java index e5fc071ae3..7a59965f68 100644 --- a/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayUtil.java +++ b/runelite-client/src/main/java/net/runelite/client/ui/overlay/OverlayUtil.java @@ -217,8 +217,6 @@ public class OverlayUtil break; case TOP_LEFT: case TOP_CENTER: - result.y += dimension.height + (dimension.height == 0 ? 0 : padding); - break; case CANVAS_TOP_RIGHT: case TOP_RIGHT: result.y += dimension.height + (dimension.height == 0 ? 0 : padding); @@ -242,18 +240,18 @@ public class OverlayUtil case TOP_LEFT: break; case TOP_CENTER: - result.x = result.x - dimension.width / 2; + result.x = -dimension.width / 2; break; case BOTTOM_LEFT: - result.y = result.y - dimension.height; + result.y = -dimension.height; break; case BOTTOM_RIGHT: case ABOVE_CHATBOX_RIGHT: - result.y = result.y - dimension.height; + result.y = -dimension.height; // FALLTHROUGH case CANVAS_TOP_RIGHT: case TOP_RIGHT: - result.x = result.x - dimension.width; + result.x = -dimension.width; break; }