Skip to content

Commit

Permalink
Respect anchor settings when resizing entity (#2551)
Browse files Browse the repository at this point in the history
  • Loading branch information
breiler committed Jun 17, 2024
1 parent 78f4159 commit da7d167
Show file tree
Hide file tree
Showing 13 changed files with 291 additions and 101 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ This file is part of Universal Gcode Sender (UGS).
*/
package com.willwinder.ugs.nbp.designer.actions;

import com.willwinder.ugs.nbp.designer.entities.Anchor;
import com.willwinder.ugs.nbp.designer.entities.Entity;
import com.willwinder.ugs.nbp.designer.entities.EntityGroup;
import com.willwinder.ugs.nbp.designer.entities.controls.Location;
import com.willwinder.ugs.nbp.designer.entities.controls.ResizeUtils;
import com.willwinder.ugs.nbp.designer.model.Size;

Expand All @@ -34,30 +34,38 @@ This file is part of Universal Gcode Sender (UGS).
* @author Joacim Breiler
*/
public class ResizeAction implements UndoableAction {
private final Location location;
private final Anchor anchor;
private final List<Entity> entities;
private final Size originalSize;
private final Size newSize;

public ResizeAction(List<Entity> entities, Location location, Size originalSize, Size newSize) {
/**
* Resizes the entities from an anchor position
*
* @param entities a list of entities that is being resized
* @param anchor the corner that is being anchored
* @param originalSize the original size
* @param newSize the new size
*/
public ResizeAction(List<Entity> entities, Anchor anchor, Size originalSize, Size newSize) {
this.entities = new ArrayList<>(entities);
this.location = location;
this.originalSize = originalSize;
this.newSize = newSize;
this.anchor = anchor;
}

@Override
public void redo() {
EntityGroup entityGroup = new EntityGroup();
entityGroup.addAll(entities);
ResizeUtils.performScaling(entityGroup, location, originalSize, newSize);
ResizeUtils.performScaling(entityGroup, anchor, originalSize, newSize);
}

@Override
public void undo() {
EntityGroup entityGroup = new EntityGroup();
entityGroup.addAll(entities);
ResizeUtils.performScaling(entityGroup, location, newSize, originalSize);
ResizeUtils.performScaling(entityGroup, anchor, newSize, originalSize);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ public Size getSize() {

@Override
public void setSize(Size size) {
setSize(Anchor.BOTTOM_LEFT, size);
}

@Override
public void setSize(Anchor anchor, Size size) {
Point2D position = getPosition(anchor);
if (size.getWidth() <= 0) {
size = new Size(0.0001, size.getHeight());
}
Expand All @@ -97,6 +103,7 @@ public void setSize(Size size) {

Size currentSize = getSize();
scale(size.getWidth() / currentSize.getWidth(), size.getHeight() / currentSize.getHeight());
setPosition(anchor, position);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@

public enum Anchor {
TOP_LEFT,
TOP_CENTER,
TOP_RIGHT,
CENTER,
BOTTOM_LEFT,
BOTTOM_CENTER,
LEFT_CENTER,
RIGHT_CENTER,
BOTTOM_RIGHT
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,14 @@ public interface Entity {
*/
void setSize(Size size);

/**
* Changes the size of the entity from the given anchor.
*
* @param anchor the anchor to keep
* @param size the new size
*/
void setSize(Anchor anchor, Size size);

/**
* Gets the bounds of the entity with the position and size in real space
*
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ This file is part of Universal Gcode Sender (UGS).
import com.willwinder.ugs.nbp.designer.Utils;
import com.willwinder.ugs.nbp.designer.actions.ResizeAction;
import com.willwinder.ugs.nbp.designer.actions.UndoManager;
import com.willwinder.ugs.nbp.designer.entities.Anchor;
import com.willwinder.ugs.nbp.designer.entities.Entity;
import com.willwinder.ugs.nbp.designer.entities.EntityEvent;
import com.willwinder.ugs.nbp.designer.entities.EventType;
Expand Down Expand Up @@ -51,40 +52,41 @@ public class ResizeControl extends AbstractControl {
public static final int SIZE = 8;
public static final int MARGIN = 6;
public static final double ARC_SIZE = 1d;
private final Location location;

private final RoundRectangle2D.Double shape;
private final Controller controller;
private final Anchor anchor;
private AffineTransform transform = new AffineTransform();
private Point2D.Double startOffset = new Point2D.Double();
private boolean isHovered;
private Size originalSize;
private Point2D originalPosition;

public ResizeControl(Controller controller, Location location) {
public ResizeControl(Controller controller, Anchor anchor) {
super(controller.getSelectionManager());
this.controller = controller;
this.location = location;
this.shape = new RoundRectangle2D.Double(0, 0, SIZE, SIZE, ARC_SIZE, ARC_SIZE);
this.anchor = anchor;
}

@Override
public Optional<Cursor> getHoverCursor() {
Cursor cursor = null;
if (location == Location.TOP_LEFT) {
if (anchor == Anchor.BOTTOM_RIGHT) {
cursor = new Cursor(Cursor.NW_RESIZE_CURSOR);
} else if (location == Location.TOP_RIGHT) {
} else if (anchor == Anchor.BOTTOM_LEFT) {
cursor = new Cursor(Cursor.NE_RESIZE_CURSOR);
} else if (location == Location.BOTTOM_LEFT) {
} else if (anchor == Anchor.TOP_RIGHT) {
cursor = new Cursor(Cursor.SW_RESIZE_CURSOR);
} else if (location == Location.BOTTOM_RIGHT) {
} else if (anchor == Anchor.TOP_LEFT) {
cursor = new Cursor(Cursor.SE_RESIZE_CURSOR);
} else if (location == Location.BOTTOM) {
} else if (anchor == Anchor.TOP_CENTER) {
cursor = new Cursor(Cursor.S_RESIZE_CURSOR);
} else if (location == Location.TOP) {
} else if (anchor == Anchor.BOTTOM_CENTER) {
cursor = new Cursor(Cursor.N_RESIZE_CURSOR);
} else if (location == Location.LEFT) {
} else if (anchor == Anchor.RIGHT_CENTER) {
cursor = new Cursor(Cursor.W_RESIZE_CURSOR);
} else if (location == Location.RIGHT) {
} else if (anchor == Anchor.LEFT_CENTER) {
cursor = new Cursor(Cursor.E_RESIZE_CURSOR);
}
return Optional.ofNullable(cursor);
Expand Down Expand Up @@ -138,11 +140,11 @@ public void onEvent(EntityEvent entityEvent) {
} else if (mouseShapeEvent.getType() == EventType.MOUSE_DRAGGED) {
Size size = getSelectionManager().getSize();
Size newSize = calculateNewSize(size, mousePosition);
ResizeUtils.performScaling(getSelectionManager(), location, size, newSize);
ResizeUtils.performScaling(getSelectionManager(), anchor, size, newSize);
} else if (mouseShapeEvent.getType() == EventType.MOUSE_RELEASED) {
getSelectionManager().setPosition(originalPosition);
Size newSize = calculateNewSize(originalSize, mousePosition);
addUndoAction(getSelectionManager(), location, originalSize, newSize);
addUndoAction(getSelectionManager(), anchor, originalSize, newSize);
} else if (mouseShapeEvent.getType() == EventType.MOUSE_IN) {
isHovered = true;
} else if (mouseShapeEvent.getType() == EventType.MOUSE_OUT) {
Expand All @@ -151,7 +153,7 @@ public void onEvent(EntityEvent entityEvent) {
}
}

private void addUndoAction(Entity target, Location location, Size originalSize, Size newSize) {
private void addUndoAction(Entity target, Anchor anchor, Size originalSize, Size newSize) {
UndoManager undoManager = ControllerFactory.getUndoManager();
if (undoManager != null) {
List<Entity> entityList = new ArrayList<>();
Expand All @@ -160,7 +162,7 @@ private void addUndoAction(Entity target, Location location, Size originalSize,
} else {
entityList.add(target);
}
ResizeAction resizeAction = new ResizeAction(entityList, location, originalSize, newSize);
ResizeAction resizeAction = new ResizeAction(entityList, anchor, originalSize, newSize);
resizeAction.redo();
undoManager.addAction(resizeAction);
}
Expand All @@ -179,21 +181,21 @@ private void updatePosition(Drawing drawing) {
Rectangle2D bounds = getSelectionManager().getRelativeShape().getBounds2D();
t.translate(bounds.getX(), bounds.getY());

if (location == Location.BOTTOM_RIGHT) {
if (anchor == Anchor.TOP_LEFT) {
t.translate(bounds.getWidth() + margin, -margin);
} else if (location == Location.TOP_LEFT) {
} else if (anchor == Anchor.BOTTOM_RIGHT) {
t.translate(-margin, bounds.getHeight() + margin);
} else if (location == Location.TOP_RIGHT) {
} else if (anchor == Anchor.BOTTOM_LEFT) {
t.translate(bounds.getWidth() + margin, bounds.getHeight() + margin);
} else if (location == Location.BOTTOM_LEFT) {
} else if (anchor == Anchor.TOP_RIGHT) {
t.translate(-margin, -margin);
} else if (location == Location.TOP) {
} else if (anchor == Anchor.BOTTOM_CENTER) {
t.translate(bounds.getWidth() / 2d, bounds.getHeight() + margin);
} else if (location == Location.BOTTOM) {
} else if (anchor == Anchor.TOP_CENTER) {
t.translate(bounds.getWidth() / 2d, -margin);
} else if (location == Location.LEFT) {
} else if (anchor == Anchor.RIGHT_CENTER) {
t.translate(-margin, bounds.getHeight() / 2d);
} else if (location == Location.RIGHT) {
} else if (anchor == Anchor.LEFT_CENTER) {
t.translate(bounds.getWidth() + margin, bounds.getHeight() / 2d);
}

Expand All @@ -218,21 +220,21 @@ private Size calculateNewSize(Size size, Point2D mousePosition) {

private Point2D getScaleFactor(double deltaX, double deltaY) {
Point2D scaleFactor = new Point2D.Double(0, 0);
if (location == Location.BOTTOM_LEFT) {
if (anchor == Anchor.TOP_RIGHT) {
scaleFactor.setLocation(1d - deltaX, 1d - deltaX);
} else if (location == Location.TOP_RIGHT) {
} else if (anchor == Anchor.BOTTOM_LEFT) {
scaleFactor.setLocation(1d + deltaX, 1d + deltaX);
} else if (location == Location.BOTTOM_RIGHT) {
} else if (anchor == Anchor.TOP_LEFT) {
scaleFactor.setLocation(1d + deltaX, 1d + deltaX);
} else if (location == Location.TOP_LEFT) {
} else if (anchor == Anchor.BOTTOM_RIGHT) {
scaleFactor.setLocation(1d - deltaX, 1d - deltaX);
} else if (location == Location.LEFT) {
} else if (anchor == Anchor.RIGHT_CENTER) {
scaleFactor.setLocation(1d - deltaX, 1d);
} else if (location == Location.BOTTOM) {
} else if (anchor == Anchor.TOP_CENTER) {
scaleFactor.setLocation(1d, 1d - deltaY);
} else if (location == Location.TOP) {
} else if (anchor == Anchor.BOTTOM_CENTER) {
scaleFactor.setLocation(1d, 1d + deltaY);
} else if (location == Location.RIGHT) {
} else if (anchor == Anchor.LEFT_CENTER) {
scaleFactor.setLocation(1d + deltaX, 1d);
}
return scaleFactor;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ This file is part of Universal Gcode Sender (UGS).
*/
package com.willwinder.ugs.nbp.designer.entities.controls;

import com.willwinder.ugs.nbp.designer.entities.Anchor;
import com.willwinder.ugs.nbp.designer.entities.Entity;
import com.willwinder.ugs.nbp.designer.model.Size;

Expand All @@ -28,30 +29,35 @@ public class ResizeUtils {
private ResizeUtils() {
}

public static Point2D getDeltaMovement(Location location, Size size, Size newSize) {
public static Point2D getDeltaMovement(Anchor anchor, Size size, Size newSize) {
Size deltaSize = new Size(size.getWidth() - newSize.getWidth(), size.getHeight() - newSize.getHeight());
Point2D movement = new Point2D.Double(0, 0);
if (location == Location.BOTTOM_LEFT) {
if (anchor == Anchor.TOP_RIGHT) {
movement.setLocation(deltaSize.getWidth(), deltaSize.getHeight());
} else if (location == Location.BOTTOM_RIGHT) {
} else if (anchor == Anchor.TOP_LEFT) {
movement.setLocation(0, deltaSize.getHeight());
} else if (location == Location.TOP_LEFT) {
} else if (anchor == Anchor.BOTTOM_RIGHT) {
movement.setLocation(deltaSize.getWidth(), 0);
} else if (location == Location.LEFT) {
movement.setLocation(deltaSize.getWidth(), 0);
} else if (location == Location.BOTTOM) {
movement.setLocation(0, deltaSize.getHeight());
} else if (anchor == Anchor.RIGHT_CENTER) {
movement.setLocation(deltaSize.getWidth(), deltaSize.getHeight() / 2);
} else if (anchor == Anchor.TOP_CENTER) {
movement.setLocation(deltaSize.getWidth() / 2, deltaSize.getHeight());
} else if (anchor == Anchor.CENTER) {
movement.setLocation(deltaSize.getWidth() / 2, deltaSize.getHeight() / 2);
} else if (anchor == Anchor.BOTTOM_CENTER) {
movement.setLocation(deltaSize.getWidth() / 2, 0);
} else if (anchor == Anchor.LEFT_CENTER) {
movement.setLocation(0, deltaSize.getHeight() / 2);
}
return movement;
}

public static void performScaling(Entity target, Location location, Size originalSize, Size newSize) {
public static void performScaling(Entity target, Anchor anchor, Size originalSize, Size newSize) {
// Do not scale if the entity will become too small after operation
if (newSize.getWidth() <= 0 || newSize.getHeight() <= 0) {
return;
}

target.move(getDeltaMovement(location, originalSize, newSize));
target.move(getDeltaMovement(anchor, originalSize, newSize));
target.setSize(newSize);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ This file is part of Universal Gcode Sender (UGS).

import com.google.common.collect.Sets;
import com.willwinder.ugs.nbp.designer.Throttler;
import com.willwinder.ugs.nbp.designer.entities.Anchor;
import com.willwinder.ugs.nbp.designer.entities.Entity;
import com.willwinder.ugs.nbp.designer.entities.EntityGroup;
import com.willwinder.ugs.nbp.designer.entities.controls.Control;
Expand All @@ -30,7 +31,6 @@ This file is part of Universal Gcode Sender (UGS).
import com.willwinder.ugs.nbp.designer.entities.controls.EditTextControl;
import com.willwinder.ugs.nbp.designer.entities.controls.GridControl;
import com.willwinder.ugs.nbp.designer.entities.controls.HighlightModelControl;
import com.willwinder.ugs.nbp.designer.entities.controls.Location;
import com.willwinder.ugs.nbp.designer.entities.controls.MoveControl;
import com.willwinder.ugs.nbp.designer.entities.controls.ResizeControl;
import com.willwinder.ugs.nbp.designer.entities.controls.RotationControl;
Expand Down Expand Up @@ -86,14 +86,14 @@ public Drawing(Controller controller) {

controlsRoot = new EntityGroup();
globalRoot.addChild(controlsRoot);
controlsRoot.addChild(new ResizeControl(controller, Location.TOP));
controlsRoot.addChild(new ResizeControl(controller, Location.LEFT));
controlsRoot.addChild(new ResizeControl(controller, Location.RIGHT));
controlsRoot.addChild(new ResizeControl(controller, Location.BOTTOM));
controlsRoot.addChild(new ResizeControl(controller, Location.BOTTOM_LEFT));
controlsRoot.addChild(new ResizeControl(controller, Location.BOTTOM_RIGHT));
controlsRoot.addChild(new ResizeControl(controller, Location.TOP_LEFT));
controlsRoot.addChild(new ResizeControl(controller, Location.TOP_RIGHT));
controlsRoot.addChild(new ResizeControl(controller, Anchor.TOP_CENTER));
controlsRoot.addChild(new ResizeControl(controller, Anchor.LEFT_CENTER));
controlsRoot.addChild(new ResizeControl(controller, Anchor.RIGHT_CENTER));
controlsRoot.addChild(new ResizeControl(controller, Anchor.BOTTOM_CENTER));
controlsRoot.addChild(new ResizeControl(controller, Anchor.BOTTOM_LEFT));
controlsRoot.addChild(new ResizeControl(controller, Anchor.BOTTOM_RIGHT));
controlsRoot.addChild(new ResizeControl(controller, Anchor.TOP_LEFT));
controlsRoot.addChild(new ResizeControl(controller, Anchor.TOP_RIGHT));
controlsRoot.addChild(new HighlightModelControl(controller.getSelectionManager()));
controlsRoot.addChild(new MoveControl(controller));
controlsRoot.addChild(new RotationControl(controller));
Expand Down
Loading

0 comments on commit da7d167

Please sign in to comment.