diff --git a/src/main/java/de/neemann/digital/draw/elements/Moveable.java b/src/main/java/de/neemann/digital/draw/elements/Moveable.java index 195aa80fb..d6c6af10c 100644 --- a/src/main/java/de/neemann/digital/draw/elements/Moveable.java +++ b/src/main/java/de/neemann/digital/draw/elements/Moveable.java @@ -15,4 +15,6 @@ public interface Moveable { * @param delta the movement */ void move(Vector delta); + + Vector getPos(); } diff --git a/src/main/java/de/neemann/digital/draw/elements/Wire.java b/src/main/java/de/neemann/digital/draw/elements/Wire.java index 3ae200ac2..c3321b6fb 100644 --- a/src/main/java/de/neemann/digital/draw/elements/Wire.java +++ b/src/main/java/de/neemann/digital/draw/elements/Wire.java @@ -76,6 +76,11 @@ public class Wire implements Drawable, Moveable { p2 = p2.add(delta); } + @Override + public Vector getPos() { + return p1; + } + /** * Setter for point 2. * Is used to move the line with the mouse @@ -178,14 +183,34 @@ public class Wire implements Drawable, Moveable { * @return a moveable representing point one */ public Moveable getMovableP1() { - return delta -> p1 = p1.add(delta); + return new Moveable() { + @Override + public void move(Vector delta) { + p1 = p1.add(delta); + } + + @Override + public Vector getPos() { + return p1; + } + }; } /** * @return a moveable representing point two */ public Moveable getMovableP2() { - return delta -> p2 = p2.add(delta); + return new Moveable() { + @Override + public void move(Vector delta) { + p2 = p2.add(delta); + } + + @Override + public Vector getPos() { + return p2; + } + }; } enum Orientation {horzontal, vertical, diagonal} diff --git a/src/main/java/de/neemann/digital/gui/Main.java b/src/main/java/de/neemann/digital/gui/Main.java index b9107ce11..e1fea63a5 100644 --- a/src/main/java/de/neemann/digital/gui/Main.java +++ b/src/main/java/de/neemann/digital/gui/Main.java @@ -402,8 +402,16 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave, E edit.add(orderOutputs.createJMenuItem()); edit.add(orderMeasurements.createJMenuItem()); edit.addSeparator(); - edit.add(circuitComponent.getCopyAction()); - edit.add(circuitComponent.getPasteAction()); + + JMenuItem copyItem = new JMenuItem(circuitComponent.getCopyAction()); + copyItem.setAccelerator(KeyStroke.getKeyStroke('C', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); + edit.add(copyItem); + JMenuItem pasteItem = new JMenuItem(circuitComponent.getPasteAction()); + pasteItem.setAccelerator(KeyStroke.getKeyStroke('V', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask())); + edit.add(pasteItem); + JMenuItem rotateItem = new JMenuItem(circuitComponent.getRotateAction()); + rotateItem.setAccelerator(KeyStroke.getKeyStroke('R')); + edit.add(rotateItem); edit.addSeparator(); edit.add(editSettings.createJMenuItem()); } diff --git a/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java b/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java index 7bbccc3c7..729b88cb6 100644 --- a/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java +++ b/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java @@ -37,6 +37,7 @@ import java.util.HashSet; import static de.neemann.digital.draw.shapes.GenericShape.SIZE; import static de.neemann.digital.draw.shapes.GenericShape.SIZE2; +import static java.awt.event.InputEvent.CTRL_DOWN_MASK; /** * @author hneemann @@ -61,6 +62,7 @@ public class CircuitComponent extends JComponent { private final Cursor moveCursor; private final AbstractAction copyAction; private final AbstractAction pasteAction; + private final AbstractAction rotateAction; private Circuit circuit; private MouseController activeMouseController; @@ -80,6 +82,20 @@ public class CircuitComponent extends JComponent { this.parentsSavedListener = parentsSavedListener; highLighted = new HashSet<>(); + rotateAction = new AbstractAction(Lang.get("menu_rotate")) { + @Override + public void actionPerformed(ActionEvent e) { + if (activeMouseController instanceof MouseControllerSelect) { + MouseControllerSelect mcs = ((MouseControllerSelect) activeMouseController); + ArrayList elements = circuit.getElementsToMove(Vector.min(mcs.corner1, mcs.corner2), Vector.max(mcs.corner1, mcs.corner2)); + if (elements != null) + rotateElements(elements, mcs); + } + } + }; + rotateAction.setEnabled(false); + + copyAction = new AbstractAction(Lang.get("menu_copy")) { @Override public void actionPerformed(ActionEvent e) { @@ -123,10 +139,12 @@ public class CircuitComponent extends JComponent { getInputMap().put(KeyStroke.getKeyStroke("DELETE"), DEL_ACTION); getActionMap().put(DEL_ACTION, deleteAction); - getInputMap().put(KeyStroke.getKeyStroke("control C"), "myCopy"); + getInputMap().put(KeyStroke.getKeyStroke('C', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), "myCopy"); getActionMap().put("myCopy", copyAction); - getInputMap().put(KeyStroke.getKeyStroke("control V"), "myPaste"); + getInputMap().put(KeyStroke.getKeyStroke('V', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()), "myPaste"); getActionMap().put("myPaste", pasteAction); + getInputMap().put(KeyStroke.getKeyStroke("R"), "myRotate"); + getActionMap().put("myRotate", rotateAction); setFocusable(true); @@ -202,6 +220,44 @@ public class CircuitComponent extends JComponent { return pasteAction; } + /** + * @return the rotate action + */ + public AbstractAction getRotateAction() { + return rotateAction; + } + + private void rotateElements(ArrayList elements, MouseControllerSelect mcs) { + Vector p1 = Vector.min(mcs.corner1, mcs.corner2); + Vector p2 = Vector.max(mcs.corner1, mcs.corner2); + + Transform transform = new TransformRotate(p1.add(0, p2.y - p1.y), 1) { + @Override + public Vector transform(Vector v) { + return super.transform(v.sub(p1)); + } + }; + + for (Moveable m : elements) { + Vector p = m.getPos(); + Vector t = transform.transform(p); + m.move(t.sub(p)); + + if (m instanceof VisualElement) { + VisualElement ve = (VisualElement) m; + int r = ve.getRotate() + 1; + if (r > 3) r -= 4; + ve.setRotate(r); + } + + } + + mcs.corner1 = transform.transform(mcs.corner1); + mcs.corner2 = transform.transform(mcs.corner2); + circuit.modified(); + repaint(); + } + /** * Sets the observer to call if the user is clicking on elements while running. * @@ -485,6 +541,7 @@ public class CircuitComponent extends JComponent { activeMouseController = this; deleteAction.setActive(false); copyAction.setEnabled(false); + rotateAction.setEnabled(false); setCursor(mouseCursor); repaint(); } @@ -697,6 +754,7 @@ public class CircuitComponent extends JComponent { this.corner2 = corner2; deleteAction.setActive(true); copyAction.setEnabled(true); + rotateAction.setEnabled(true); wasReleased = false; } @@ -724,7 +782,26 @@ public class CircuitComponent extends JComponent { removeHighLighted(); mouseMoveSelected.activate(corner1, corner2, getPosVector(e)); } else { + corner2 = getPosVector(e); + if ((e.getModifiersEx() & CTRL_DOWN_MASK) != 0) { + Vector dif = corner2.sub(corner1); + int dx = dif.x; + int dy = dif.y; + int absDx = Math.abs(dx); + int absDy = Math.abs(dy); + if (absDx != absDy) { + if (absDx > absDy) { + if (dx > absDy) dx = absDy; + else dx = -absDy; + } else { + if (dy > absDx) dy = absDx; + else dy = -absDx; + } + } + corner2 = corner1.add(dx, dy); + } + ArrayList elements = circuit.getElementsToHighlight(Vector.min(corner1, corner2), Vector.max(corner1, corner2)); removeHighLighted(); if (elements != null) diff --git a/src/main/resources/lang/lang_de.properties b/src/main/resources/lang/lang_de.properties index 56ceecaf0..397127b8c 100644 --- a/src/main/resources/lang/lang_de.properties +++ b/src/main/resources/lang/lang_de.properties @@ -333,6 +333,8 @@ menu_table_create_jedec_tt=Erzeugt eine JEDEC Datei f\u00FCr den Baustein menu_table_exportTableLaTeX=Export LaTeX menu_copy=Kopieren menu_paste=Einf\u00FCgen +menu_rotate=Rotieren + menu_editSettings=Einstellungen menu_editSettings_tt=Bearbeitet die globalen Einstellungen diff --git a/src/main/resources/lang/lang_en.properties b/src/main/resources/lang/lang_en.properties index ea2e63af1..7244483ce 100644 --- a/src/main/resources/lang/lang_en.properties +++ b/src/main/resources/lang/lang_en.properties @@ -314,7 +314,7 @@ menu_editSettings=Settings menu_editSettings_tt=Edits Digitals Preferences menu_copy=Copy menu_paste=Paste - +menu_rotate=Rotate win_saveChanges=Save Changes? win_confirmExit=Confirm Exit!