Allow overlay renderer to restrict overlay parent bounds

This removes the hack of double setting the widget position in
WidgetOverlay, which was required to override the overlay renderers
clamping code in both overlay drag and in overlay rendering.
This commit is contained in:
Adam
2020-12-12 16:15:17 -05:00
parent 59bccf2c6f
commit 70a2e41db0
3 changed files with 69 additions and 53 deletions

View File

@@ -97,4 +97,15 @@ public abstract class Overlay implements LayoutableRenderableEntity
{
return false;
}
/**
* Get the parent bounds for overlay dragging. The overlay will
* not be allowed to be moved outside of the parent bounds.
* @return
*/
@Nullable
public Rectangle getParentBounds()
{
return null;
}
}

View File

@@ -246,11 +246,14 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
}
else
{
final Point location = overlay.getBounds().getLocation();
final Dimension dimension = overlay.getBounds().getSize();
final Rectangle bounds = overlay.getBounds();
final Point location = bounds.getLocation();
final Dimension dimension = bounds.getSize();
final Point preferredLocation = overlay.getPreferredLocation();
// If the final position is not modified, layout it
if (overlayPosition != OverlayPosition.DETACHED && (overlay.getPreferredLocation() == null || overlay.getPreferredPosition() != null))
if (overlayPosition != OverlayPosition.DETACHED && (preferredLocation == null || overlay.getPreferredPosition() != null))
{
final Rectangle snapCorner = snapCorners.forPosition(overlayPosition);
final Point translation = OverlayUtil.transformPosition(overlayPosition, dimension);
@@ -260,21 +263,18 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
}
else
{
final Point preferredLocation = overlay.getPreferredLocation();
if (preferredLocation != null)
{
location.setLocation(preferredLocation);
}
final Dimension realDimensions = client.getRealDimensions();
location.x = Ints.constrainToRange(location.x, 0, Math.max(0, realDimensions.width - dimension.width));
location.y = Ints.constrainToRange(location.y, 0, Math.max(0, realDimensions.height - dimension.height));
// Clamp the overlay position to ensure it is on screen or within parent bounds
clampOverlayLocation(location, dimension.width, dimension.height, overlay);
}
if (overlay.getPreferredSize() != null)
{
overlay.getBounds().setSize(overlay.getPreferredSize());
bounds.setSize(overlay.getPreferredSize());
}
safeRender(client, overlay, layer, graphics, location);
@@ -287,8 +287,6 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
graphics.setRenderingHints(renderingHints);
graphics.setBackground(background);
final Rectangle bounds = overlay.getBounds();
if (!bounds.isEmpty())
{
if (inOverlayManagingMode)
@@ -583,12 +581,14 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
}
else if (inOverlayDraggingMode)
{
final Dimension realDimension = client.getRealDimensions();
p.translate(-overlayOffset.x, -overlayOffset.y);
p.x = Ints.constrainToRange(p.x, 0, Math.max(0, realDimension.width - currentManagedOverlay.getBounds().width));
p.y = Ints.constrainToRange(p.y, 0, Math.max(0, realDimension.height - currentManagedOverlay.getBounds().height));
Point overlayPosition = new Point(p);
overlayPosition.translate(-overlayOffset.x, -overlayOffset.y); // adjust by mouse offset to get overlay position
// Clamp drag to parent component
final Rectangle overlayBounds = currentManagedOverlay.getBounds();
clampOverlayLocation(overlayPosition, overlayBounds.width, overlayBounds.height, currentManagedOverlay);
currentManagedOverlay.setPreferredPosition(null);
currentManagedOverlay.setPreferredLocation(p);
currentManagedOverlay.setPreferredLocation(overlayPosition);
}
else
{
@@ -887,4 +887,29 @@ public class OverlayRenderer extends MouseAdapter implements KeyListener
return entries;
}
/**
* Adjust the given overlay position to be within its parent's bounds.
*
* @param overlayPosition the overlay position, which is modified in place
* @param overlayWidth
* @param overlayHeight
* @param overlay the overlay
*/
private void clampOverlayLocation(Point overlayPosition, int overlayWidth, int overlayHeight, Overlay overlay)
{
Rectangle parentBounds = overlay.getParentBounds();
if (parentBounds == null || parentBounds.isEmpty())
{
// If no bounds are set, use the full client bounds
Dimension dim = client.getRealDimensions();
parentBounds = new Rectangle(0, 0, dim.width, dim.height);
}
// 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));
}
}

View File

@@ -88,32 +88,10 @@ public class WidgetOverlay extends Overlay
return Objects.toString(widgetInfo);
}
@Override
public Rectangle getBounds()
{
final Rectangle bounds = super.getBounds();
final Rectangle parent = getParentBounds(client.getWidget(widgetInfo));
if (parent.isEmpty())
{
return bounds;
}
int x = bounds.x;
int y = bounds.y;
x = Math.max(parent.x, x);
y = Math.max(parent.y, y);
x = Math.min((int)parent.getMaxX() - bounds.width, x);
y = Math.min((int)parent.getMaxY() - bounds.height, y);
bounds.setLocation(x, y);
return bounds;
}
@Override
public Dimension render(Graphics2D graphics)
{
final Widget widget = client.getWidget(widgetInfo);
final Rectangle bounds = super.getBounds();
final Rectangle parent = getParentBounds(widget);
if (parent.isEmpty())
@@ -121,15 +99,8 @@ public class WidgetOverlay extends Overlay
return null;
}
int x = bounds.x;
int y = bounds.y;
x = Math.max(parent.x, x);
y = Math.max(parent.y, y);
x = Math.min((int)parent.getMaxX() - bounds.width, x);
y = Math.min((int)parent.getMaxY() - bounds.height, y);
bounds.setLocation(x, y);
widget.setOriginalX(0);
widget.setOriginalY(0);
final Rectangle bounds = getBounds();
// The widget relative pos is relative to the parent
widget.setRelativeX(bounds.x - parent.x);
widget.setRelativeY(bounds.y - parent.y);
return new Dimension(widget.getWidth(), widget.getHeight());
@@ -137,11 +108,6 @@ public class WidgetOverlay extends Overlay
private Rectangle getParentBounds(final Widget widget)
{
if (!client.isClientThread())
{
return parentBounds;
}
if (widget == null || widget.isHidden())
{
parentBounds.setBounds(new Rectangle());
@@ -157,13 +123,27 @@ public class WidgetOverlay extends Overlay
}
else
{
bounds = new Rectangle(parent.getCanvasLocation().getX(), parent.getCanvasLocation().getY(), parent.getWidth(), parent.getHeight());
bounds = parent.getBounds();
}
parentBounds.setBounds(bounds);
return bounds;
}
@Override
public Rectangle getParentBounds()
{
if (!client.isClientThread())
{
// During overlay drag this is called on the EDT, so we just
// cache and reuse the last known parent bounds.
return parentBounds;
}
final Widget widget = client.getWidget(widgetInfo);
return getParentBounds(widget);
}
private static class XpTrackerWidgetOverlay extends WidgetOverlay
{
private XpTrackerWidgetOverlay(Client client, WidgetInfo widgetInfo, OverlayPosition overlayPosition)