diff --git a/diylc/diylc-core/src/main/resources/update.xml b/diylc/diylc-core/src/main/resources/update.xml
index 2b0ebadd..a68e0f3d 100644
--- a/diylc/diylc-core/src/main/resources/update.xml
+++ b/diylc/diylc-core/src/main/resources/update.xml
@@ -597,6 +597,10 @@
IMPROVEMENT
'S1 Switch' can now be rotated to match the orientation of the potentiometer it is mounted on, so the switching matrix stays correct relative to the pot lugs
+
+ IMPROVEMENT
+ 'Cut Line' can be rotated using keyboard shortcuts
+
https://github.com/bancika/diy-layout-creator/releases
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/CutLine.java b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/CutLine.java
index 751e9c36..60cb000c 100644
--- a/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/CutLine.java
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/connectivity/CutLine.java
@@ -26,7 +26,7 @@ import java.awt.geom.Point2D;
import org.diylc.common.ObjectCache;
import org.diylc.common.OrientationHV;
import org.diylc.components.AbstractTransparentComponent;
-import org.diylc.components.transform.SimpleComponentTransformer;
+import org.diylc.components.transform.CutLineTransformer;
import org.diylc.core.ComponentState;
import org.diylc.core.IDIYComponent;
import org.diylc.core.IDrawingObserver;
@@ -40,7 +40,7 @@ import org.diylc.core.measures.SizeUnit;
@ComponentDescriptor(name = "Cut Line", category = "Connectivity", author = "Branislav Stojkovic",
description = "Cut line", instanceNamePrefix = "CL", zOrder = IDIYComponent.COMPONENT,
- bomPolicy = BomPolicy.NEVER_SHOW, autoEdit = false, transformer = SimpleComponentTransformer.class)
+ bomPolicy = BomPolicy.NEVER_SHOW, autoEdit = false, transformer = CutLineTransformer.class)
public class CutLine extends AbstractTransparentComponent {
private static final long serialVersionUID = 1L;
diff --git a/diylc/diylc-library/src/main/java/org/diylc/components/transform/CutLineTransformer.java b/diylc/diylc-library/src/main/java/org/diylc/components/transform/CutLineTransformer.java
new file mode 100644
index 00000000..ee4d6a2c
--- /dev/null
+++ b/diylc/diylc-library/src/main/java/org/diylc/components/transform/CutLineTransformer.java
@@ -0,0 +1,95 @@
+/*
+
+ DIY Layout Creator (DIYLC).
+ Copyright (c) 2009-2025 held jointly by the individual authors.
+
+ This file is part of DIYLC.
+
+ DIYLC is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ DIYLC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with DIYLC. If not, see .
+
+*/
+package org.diylc.components.transform;
+
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+
+import org.diylc.common.IComponentTransformer;
+import org.diylc.common.OrientationHV;
+import org.diylc.components.connectivity.CutLine;
+import org.diylc.core.IDIYComponent;
+
+public class CutLineTransformer implements IComponentTransformer {
+
+ @Override
+ public boolean canRotate(IDIYComponent> component) {
+ return component.getClass().equals(CutLine.class);
+ }
+
+ @Override
+ public boolean canMirror(IDIYComponent> component) {
+ return component.getClass().equals(CutLine.class);
+ }
+
+ @Override
+ public boolean mirroringChangesCircuit() {
+ return false;
+ }
+
+ @Override
+ public void rotate(IDIYComponent> component, Point2D center, int direction) {
+ CutLine line = (CutLine) component;
+ AffineTransform rotate =
+ AffineTransform.getRotateInstance(Math.PI / 2 * direction, center.getX(), center.getY());
+ Point2D start = rotate.transform(line.getControlPoint(0), null);
+ Point2D end = rotate.transform(getEnd(line), null);
+
+ if (line.getOrientation() == OrientationHV.HORIZONTAL) {
+ line.setOrientation(OrientationHV.VERTICAL);
+ } else {
+ line.setOrientation(OrientationHV.HORIZONTAL);
+ }
+ setEndpoints(line, start, end);
+ }
+
+ @Override
+ public void mirror(IDIYComponent> component, Point2D center, int direction) {
+ CutLine line = (CutLine) component;
+ Point2D start = mirror(line.getControlPoint(0), center, direction);
+ Point2D end = mirror(getEnd(line), center, direction);
+ setEndpoints(line, start, end);
+ }
+
+ // the line always extends right or down from its control point, so after a transform the
+ // control point has to move to whichever end is now top-left
+ private void setEndpoints(CutLine line, Point2D start, Point2D end) {
+ line.setControlPoint(new Point2D.Double(Math.min(start.getX(), end.getX()),
+ Math.min(start.getY(), end.getY())), 0);
+ }
+
+ private Point2D getEnd(CutLine line) {
+ Point2D start = line.getControlPoint(0);
+ double length = line.getLength().convertToPixels();
+ if (line.getOrientation() == OrientationHV.HORIZONTAL) {
+ return new Point2D.Double(start.getX() + length, start.getY());
+ }
+ return new Point2D.Double(start.getX(), start.getY() + length);
+ }
+
+ private Point2D mirror(Point2D p, Point2D center, int direction) {
+ if (direction == IComponentTransformer.HORIZONTAL) {
+ return new Point2D.Double(2 * center.getX() - p.getX(), p.getY());
+ }
+ return new Point2D.Double(p.getX(), 2 * center.getY() - p.getY());
+ }
+}