From cd8c57c6b045990a042e54e7d8e55ba2f486df9a Mon Sep 17 00:00:00 2001 From: Baaaaaz <131240480+Baaaaaz@users.noreply.github.com> Date: Wed, 15 Jul 2026 06:34:42 +0100 Subject: [PATCH 1/6] change movement and size label positions --- .../tool/drawing/DrawingPointerTool.java | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/main/java/net/rptools/maptool/client/tool/drawing/DrawingPointerTool.java b/src/main/java/net/rptools/maptool/client/tool/drawing/DrawingPointerTool.java index 606917e4e3..f41d08bb80 100644 --- a/src/main/java/net/rptools/maptool/client/tool/drawing/DrawingPointerTool.java +++ b/src/main/java/net/rptools/maptool/client/tool/drawing/DrawingPointerTool.java @@ -1085,9 +1085,9 @@ private void paintTemplateCursor( } /** - * Paint the dragged movement distance in feet according to the Movement Metric setting. + * Paint the dragged movement distance according to the Movement Metric setting. * - *

Label is displayed below the template (i.e. similar to dragging a token) + *

Label is displayed near the dragged terminus * * @param g where to draw. * @param startVertex the starting point. @@ -1112,10 +1112,9 @@ private void paintTemplateMovementLabel( if (moveDistance != 0) { Rectangle bounds = at.getBounds(zone); - int x = (int) (bounds.getMinX() + bounds.getMaxX()) / 2; - int y = (int) (bounds.getMaxY()); - ScreenPoint centerText = renderer.getViewModel().getZoneScale().toScreenSpace(x, y); - + ScreenPoint centerText = + renderer.getViewModel().getZoneScale().toScreenSpace(endVertex.x, endVertex.y); + centerText.translate(CURSOR_WIDTH, CURSOR_WIDTH); ToolHelper.drawMeasurement(g, moveDistance, (int) centerText.x, (int) centerText.y); } } @@ -1176,19 +1175,23 @@ private void paintTemplateMovementLine( } /** - * Paint the radius value in feet. To be displayed above the template vertex (i.e. same as when - * drawing a template) + * Paint the template radius value label. + * + *

Label is displayed to the right of the template. * * @param g where to paint. * @param zp where on the map to paint the radius label. */ private void paintTemplateRadiusLabel(Graphics2D g, ZonePoint zp, AbstractTemplate at) { if (at.getRadius() > 0) { - ScreenPoint centerText = renderer.getViewModel().getZoneScale().toScreenSpace(zp.x, zp.y); - centerText.translate(CURSOR_WIDTH, -CURSOR_WIDTH); + Zone zone = getZone(); + Rectangle bounds = at.getBounds(zone); + int x = (int) bounds.getMaxX(); + int y = (int) (bounds.getMinY() + bounds.getMaxY()) / 2; + ScreenPoint centerText = renderer.getViewModel().getZoneScale().toScreenSpace(x, y); ToolHelper.drawMeasurement( g, at.getRadius() * getZone().getUnitsPerCell(), (int) centerText.x, (int) centerText.y); - } // endif + } } /** From 873c8c6000115dc98d59077c883473ddeb561bcc Mon Sep 17 00:00:00 2001 From: Baaaaaz <131240480+Baaaaaz@users.noreply.github.com> Date: Wed, 15 Jul 2026 06:38:41 +0100 Subject: [PATCH 2/6] fix selection border not appearing when right clicking on an drawable that was previously unselected --- .../rptools/maptool/client/tool/drawing/DrawingPointerTool.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/rptools/maptool/client/tool/drawing/DrawingPointerTool.java b/src/main/java/net/rptools/maptool/client/tool/drawing/DrawingPointerTool.java index f41d08bb80..980f0469a6 100644 --- a/src/main/java/net/rptools/maptool/client/tool/drawing/DrawingPointerTool.java +++ b/src/main/java/net/rptools/maptool/client/tool/drawing/DrawingPointerTool.java @@ -436,7 +436,7 @@ public void mouseReleased(MouseEvent e) { } } - if (SwingUtilities.isRightMouseButton(e)) { + if (SwingUtilities.isRightMouseButton(e) && isDraggingMap()) { cancelMapDrag(); // We no longer drag the map. Fixes bug #616 return; } From c1f6109a881ddc2896875a17bf59d8f08f335a7e Mon Sep 17 00:00:00 2001 From: Baaaaaz <131240480+Baaaaaz@users.noreply.github.com> Date: Wed, 15 Jul 2026 07:00:38 +0100 Subject: [PATCH 3/6] change duplicate action to Ctrl+D --- .../maptool/client/tool/drawing/DrawingPointerTool.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/rptools/maptool/client/tool/drawing/DrawingPointerTool.java b/src/main/java/net/rptools/maptool/client/tool/drawing/DrawingPointerTool.java index 980f0469a6..6f7f7a4d23 100644 --- a/src/main/java/net/rptools/maptool/client/tool/drawing/DrawingPointerTool.java +++ b/src/main/java/net/rptools/maptool/client/tool/drawing/DrawingPointerTool.java @@ -240,7 +240,7 @@ protected void detachFrom(ZoneRenderer renderer) { } /** - * Set DELETE to delete selected drawn elements. Set CTRL+V to + * Set DELETE to delete selected drawn elements. Set CTRL+D to * duplicate selected drawn elements. * * @param actionMap What keys do what action. @@ -250,7 +250,7 @@ protected void installKeystrokes(Map actionMap) { super.installKeystrokes(actionMap); actionMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), deleteAction); actionMap.put( - KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_DOWN_MASK), duplicateAction); + KeyStroke.getKeyStroke(KeyEvent.VK_D, InputEvent.CTRL_DOWN_MASK), duplicateAction); } /** From 4fba42a1ffd3e1062a3a8bfa988b86753158e79c Mon Sep 17 00:00:00 2001 From: Baaaaaz <131240480+Baaaaaz@users.noreply.github.com> Date: Wed, 15 Jul 2026 17:49:42 +0100 Subject: [PATCH 4/6] fix being unable to drag certain types of shape (e.g. drawings that had been merged) --- .../tool/drawing/DrawingPointerTool.java | 45 ++++++++++++++++--- 1 file changed, 38 insertions(+), 7 deletions(-) diff --git a/src/main/java/net/rptools/maptool/client/tool/drawing/DrawingPointerTool.java b/src/main/java/net/rptools/maptool/client/tool/drawing/DrawingPointerTool.java index 6f7f7a4d23..4330180704 100644 --- a/src/main/java/net/rptools/maptool/client/tool/drawing/DrawingPointerTool.java +++ b/src/main/java/net/rptools/maptool/client/tool/drawing/DrawingPointerTool.java @@ -21,9 +21,7 @@ import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; -import java.awt.geom.AffineTransform; -import java.awt.geom.Area; -import java.awt.geom.RectangularShape; +import java.awt.geom.*; import java.io.Serial; import java.util.*; import java.util.List; @@ -1362,14 +1360,47 @@ private void updateDraggedDrawnElements(MouseEvent e, ShapeDrawable sd) { dragPointOffset.y = dragWorkingZonePoint.y - dragPointOffset.y; } - if (sd.getShape() instanceof RectangularShape rs) { + Shape s = sd.getShape(); + if (s instanceof RectangularShape rs) { rs.setFrame( - rs.getBounds().x - dragPointOffset.x, - rs.getBounds().y - dragPointOffset.y, + rs.getX() - dragPointOffset.x, + rs.getY() - dragPointOffset.y, rs.getWidth(), rs.getHeight()); - } else if (sd.getShape() instanceof Polygon p) { + } else if (s instanceof Polygon p) { p.translate(-dragPointOffset.x, -dragPointOffset.y); + } else if (s instanceof Area a) { + AffineTransform tx = + AffineTransform.getTranslateInstance(-dragPointOffset.x, -dragPointOffset.y); + a.transform(tx); + } else if (s instanceof Path2D p2d) { + AffineTransform tx = + AffineTransform.getTranslateInstance(-dragPointOffset.x, -dragPointOffset.y); + p2d.transform(tx); + } else if (s instanceof Line2D line) { + line.setLine( + line.getX1() - dragPointOffset.x, + line.getY1() - dragPointOffset.y, + line.getX2() - dragPointOffset.x, + line.getY2() - dragPointOffset.y); + } else if (s instanceof QuadCurve2D quad) { + quad.setCurve( + quad.getX1() - dragPointOffset.x, + quad.getY1() - dragPointOffset.y, + quad.getCtrlX() - dragPointOffset.x, + quad.getCtrlY() - dragPointOffset.y, + quad.getX2() - dragPointOffset.x, + quad.getY2() - dragPointOffset.y); + } else if (s instanceof CubicCurve2D cubic) { + cubic.setCurve( + cubic.getX1() - dragPointOffset.x, + cubic.getY1() - dragPointOffset.y, + cubic.getCtrlX1() - dragPointOffset.x, + cubic.getCtrlY1() - dragPointOffset.y, + cubic.getCtrlX2() - dragPointOffset.x, + cubic.getCtrlY2() - dragPointOffset.y, + cubic.getX2() - dragPointOffset.x, + cubic.getY2() - dragPointOffset.y); } } From f87a4c16701024f39267d09cb21c71209819ea99 Mon Sep 17 00:00:00 2001 From: Baaaaaz <131240480+Baaaaaz@users.noreply.github.com> Date: Wed, 15 Jul 2026 17:52:25 +0100 Subject: [PATCH 5/6] log that we cannot drag certain types of shape that are being dragged --- .../maptool/client/tool/drawing/DrawingPointerTool.java | 9 +++++++++ .../net/rptools/maptool/language/i18n.properties | 1 + 2 files changed, 10 insertions(+) diff --git a/src/main/java/net/rptools/maptool/client/tool/drawing/DrawingPointerTool.java b/src/main/java/net/rptools/maptool/client/tool/drawing/DrawingPointerTool.java index 4330180704..ac576f5965 100644 --- a/src/main/java/net/rptools/maptool/client/tool/drawing/DrawingPointerTool.java +++ b/src/main/java/net/rptools/maptool/client/tool/drawing/DrawingPointerTool.java @@ -41,6 +41,7 @@ import net.rptools.maptool.client.ui.zone.renderer.ZoneRenderer; import net.rptools.maptool.client.walker.WalkerMetric; import net.rptools.maptool.events.MapToolEventBus; +import net.rptools.maptool.language.I18N; import net.rptools.maptool.model.*; import net.rptools.maptool.model.drawing.*; import org.apache.logging.log4j.LogManager; @@ -1401,6 +1402,14 @@ private void updateDraggedDrawnElements(MouseEvent e, ShapeDrawable sd) { cubic.getCtrlY2() - dragPointOffset.y, cubic.getX2() - dragPointOffset.x, cubic.getY2() - dragPointOffset.y); + } else { + // log that we cannot drag certain types of shape that are being dragged + log.warn( + I18N.getText( + "tool.drawingpointer.draggingUnsupportedShapeType", + s.getClass().getSimpleName(), + sd.getId(), + sd.getName())); } } diff --git a/src/main/resources/net/rptools/maptool/language/i18n.properties b/src/main/resources/net/rptools/maptool/language/i18n.properties index cbd24579f0..df6c7b5919 100644 --- a/src/main/resources/net/rptools/maptool/language/i18n.properties +++ b/src/main/resources/net/rptools/maptool/language/i18n.properties @@ -2954,6 +2954,7 @@ tool.deletedrawing.instructions = LClick: Select drawings Double-Click: Delete tool.deletedrawing.tooltip = Delete drawing tool tool.drawingpointer.tooltip = Drawing pointer tool. tool.drawingpointer.instructions = Hover: show label. RClick: Popupmenu. LClick: Select drawings. LClick+Shift: multiselect. LClick+Ctrl: select stack next. LDrag: Selection box. LDrag+Shift: multiselect. LDrag+Ctrl: Selection box match stroke color. LDrag+Alt: Selection box match fill color. Selected+DELETE: delete. +tool.drawingpointer.draggingUnsupportedShapeType = Dragging {0} shape types is not supported. Shape id: {1} Shape name: {2} tool.templatepointer.tooltip = Template pointer tool. tool.templatepointer.instructions= Hover: show label. RClick: Popupmenu. LClick: Select templates. LClick+Shift: multiselect. LClick+Ctrl: select stack next. LDrag: Selection box. LDrag+Shift: multiselect. LDrag+Ctrl: Selection box match stroke color. LDrag+Alt: Selection box match fill color. LDrag selected template: Move. LDrag+Ctrl+single template: change radius/size. LDrag+Alt+single template: change path vertex. Selected+DELETE: delete. Selected+CTRL+V: duplicate. tool.isorectangle.tooltip = Draw an isometric rectangle. From e9503935605787cd536e2add23125433b9ad99de Mon Sep 17 00:00:00 2001 From: Baaaaaz <131240480+Baaaaaz@users.noreply.github.com> Date: Wed, 15 Jul 2026 17:57:55 +0100 Subject: [PATCH 6/6] fix for not displaying line segments being dragged by invalidating area and bounds caches when adding points or translating point co-ordinates. --- .../maptool/model/drawing/LineSegment.java | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/main/java/net/rptools/maptool/model/drawing/LineSegment.java b/src/main/java/net/rptools/maptool/model/drawing/LineSegment.java index 18e615e63d..77092cca40 100644 --- a/src/main/java/net/rptools/maptool/model/drawing/LineSegment.java +++ b/src/main/java/net/rptools/maptool/model/drawing/LineSegment.java @@ -41,7 +41,6 @@ public class LineSegment extends AbstractDrawing { private final List points = new ArrayList(); private @Nonnull Float width; private boolean squareCap; - private transient int lastPointCount = -1; private transient Rectangle cachedBounds; private transient Area area; @@ -109,8 +108,8 @@ private Object readResolve() { * @param y */ public void addPoint(int x, int y) { - area = null; points.add(new Point(x, y)); + invalidateGeometryCache(); } /** @@ -137,10 +136,10 @@ public List getPoints() { * @param deltaY offset in the Y axis */ public void translate(int deltaX, int deltaY) { - points.replaceAll(point1 -> new Point(point1.x + deltaX, point1.y + deltaY)); - if (cachedBounds != null) { - cachedBounds.translate(deltaX, deltaY); + for (Point p : points) { + p.translate(deltaX, deltaY); } + invalidateGeometryCache(); } @Override @@ -179,7 +178,7 @@ public static LineSegment fromDto(LineSegmentDrawableDto dto) { } private Area createLineArea() { - if (points.size() < 1) { + if (points.isEmpty()) { return null; } GeneralPath gp = null; @@ -210,11 +209,13 @@ protected void drawBackground(Zone zone, Graphics2D g) { @Override public Rectangle getBounds(Zone zone) { - if (lastPointCount == points.size()) { + if (cachedBounds != null) { return cachedBounds; } - if (points.size() < 1) return null; - Rectangle bounds = new Rectangle(points.get(0)); + if (points.isEmpty()) { + return null; + } + Rectangle bounds = new Rectangle(points.getFirst()); for (Point point : points) { bounds.add(point); } @@ -227,7 +228,6 @@ public Rectangle getBounds(Zone zone) { bounds.height = 1; } cachedBounds = bounds; - lastPointCount = points.size(); return bounds; } @@ -248,4 +248,13 @@ public int getStrokeJoin() { if (squareCap) return BasicStroke.JOIN_MITER; else return BasicStroke.JOIN_ROUND; } + + /** + * Line segment geometry can mutate with either the number of points or point co-ordinate change. + * Whenever one of these change the bounds and area caches should be invalidated. + */ + private void invalidateGeometryCache() { + cachedBounds = null; + area = null; + } }