copy is now implemented using the common ctrl-c and ctrl-v.

It is possible to copy from one window to an other.
This commit is contained in:
hneemann 2016-05-31 16:41:28 +02:00
parent d468a8d576
commit 8471ff84f3
2 changed files with 164 additions and 26 deletions

View File

@ -19,6 +19,9 @@ import de.neemann.gui.ToolTipAction;
import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
@ -27,6 +30,7 @@ import java.awt.geom.AffineTransform;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.Point2D;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
@ -42,7 +46,6 @@ public class CircuitComponent extends JComponent {
private static final String DEL_ACTION = "myDelAction";
private final ElementLibrary library;
private final ShapeFactory shapeFactory;
private final SavedListener parentsSavedListener;
private final HashSet<Drawable> highLighted;
private final ToolTipAction deleteAction;
@ -53,14 +56,15 @@ public class CircuitComponent extends JComponent {
private final MouseControllerWire mouseWire;
private final MouseControllerSelect mouseSelect;
private final MouseControllerMoveSelected mouseMoveSelected;
private final MouseControllerCopySelected mouseCopySelected;
private final MouseController mouseRun;
private final MouseControllerInsertCopied mouseInsertList;
private final Cursor moveCursor;
private Circuit circuit;
private MouseController activeMouseController;
private AffineTransform transform = new AffineTransform();
private Observer manualChangeObserver;
private Vector lastMousePos;
/**
* Creates a new instance
@ -70,10 +74,42 @@ public class CircuitComponent extends JComponent {
*/
public CircuitComponent(ElementLibrary library, ShapeFactory shapeFactory, SavedListener parentsSavedListener) {
this.library = library;
this.shapeFactory = shapeFactory;
this.parentsSavedListener = parentsSavedListener;
highLighted = new HashSet<>();
AbstractAction copyAction = new AbstractAction("Copy") {
@Override
public void actionPerformed(ActionEvent e) {
if (activeMouseController instanceof MouseControllerSelect) {
MouseControllerSelect mcs = ((MouseControllerSelect) activeMouseController);
ArrayList<Moveable> elements = circuit.getElementsToCopy(Vector.min(mcs.corner1, mcs.corner2), Vector.max(mcs.corner1, mcs.corner2), shapeFactory);
Clipboard clpbrd = Toolkit.getDefaultToolkit().getSystemClipboard();
clpbrd.setContents(new CircuitTransferable(elements), null);
removeHighLighted();
mouseNormal.activate();
}
}
};
AbstractAction pasteAction = new AbstractAction("Paste") {
@Override
public void actionPerformed(ActionEvent e) {
Clipboard clpbrd = Toolkit.getDefaultToolkit().getSystemClipboard();
try {
Object data = clpbrd.getData(DataFlavor.stringFlavor);
if (data instanceof String) {
Vector posVector = getPosVector(lastMousePos.x, lastMousePos.y);
ArrayList<Moveable> elements = CircuitTransferable.createList(data, shapeFactory, posVector);
if (elements != null) {
mouseInsertList.activate(elements, posVector);
}
}
} catch (UnsupportedFlavorException | IOException e1) {
e1.printStackTrace();
}
}
};
deleteAction = new ToolTipAction(Lang.get("menu_delete"), ICON_DELETE) {
@Override
public void actionPerformed(ActionEvent e) {
@ -81,9 +117,13 @@ public class CircuitComponent extends JComponent {
}
}.setToolTip(Lang.get("menu_delete_tt"));
KeyStroke delKey = KeyStroke.getKeyStroke("DELETE");
getInputMap().put(delKey, DEL_ACTION);
getInputMap().put(KeyStroke.getKeyStroke("DELETE"), DEL_ACTION);
getActionMap().put(DEL_ACTION, deleteAction);
getInputMap().put(KeyStroke.getKeyStroke("control C"), "myCopy");
getActionMap().put("myCopy", copyAction);
getInputMap().put(KeyStroke.getKeyStroke("control V"), "myPaste");
getActionMap().put("myPaste", pasteAction);
setFocusable(true);
@ -100,11 +140,11 @@ public class CircuitComponent extends JComponent {
moveCursor = new Cursor(Cursor.MOVE_CURSOR);
mouseNormal = new MouseControllerNormal(normalCursor);
mouseInsertElement = new MouseControllerInsertElement(normalCursor);
mouseInsertList = new MouseControllerInsertCopied(normalCursor);
mouseMoveElement = new MouseControllerMoveElement(normalCursor);
mouseWire = new MouseControllerWire(normalCursor);
mouseSelect = new MouseControllerSelect(new Cursor(Cursor.CROSSHAIR_CURSOR));
mouseMoveSelected = new MouseControllerMoveSelected(moveCursor);
mouseCopySelected = new MouseControllerCopySelected(moveCursor);
mouseRun = new MouseControllerRun(normalCursor);
setCircuit(new Circuit());
@ -256,7 +296,13 @@ public class CircuitComponent extends JComponent {
}
}
private Vector raster(Vector pos) {
/**
* rounds the given vector to the raster
*
* @param pos the vector
* @return pos round to raster
*/
public static Vector raster(Vector pos) {
return new Vector((int) Math.round((double) pos.x / SIZE) * SIZE,
(int) Math.round((double) pos.y / SIZE) * SIZE);
}
@ -370,6 +416,7 @@ public class CircuitComponent extends JComponent {
@Override
public void mouseMoved(MouseEvent e) {
lastMousePos = new Vector(e.getX(), e.getY());
activeMouseController.moved(e);
}
@ -641,13 +688,8 @@ public class CircuitComponent extends JComponent {
@Override
boolean dragged(MouseEvent e) {
if (wasReleased) {
if (downButton == MouseEvent.BUTTON1) {
removeHighLighted();
mouseMoveSelected.activate(corner1, corner2, getPosVector(e));
} else if (downButton == MouseEvent.BUTTON3) {
removeHighLighted();
mouseCopySelected.activate(corner1, corner2, getPosVector(e));
}
} else {
corner2 = getPosVector(e);
ArrayList<Drawable> elements = circuit.getElementsToHighlight(Vector.min(corner1, corner2), Vector.max(corner1, corner2));
@ -719,25 +761,23 @@ public class CircuitComponent extends JComponent {
}
}
private final class MouseControllerCopySelected extends MouseController {
private final class MouseControllerInsertCopied extends MouseController {
private ArrayList<Moveable> elements;
private Vector lastPos;
private Vector movement;
private MouseControllerCopySelected(Cursor cursor) {
private MouseControllerInsertCopied(Cursor cursor) {
super(cursor);
}
private void activate(Vector corner1, Vector corner2, Vector pos) {
private void activate(ArrayList<Moveable> elements, Vector pos) {
super.activate();
this.elements = elements;
lastPos = pos;
movement = new Vector(0, 0);
deleteAction.setActive(true);
elements = circuit.getElementsToCopy(Vector.min(corner1, corner2), Vector.max(corner1, corner2), shapeFactory);
}
@Override
boolean dragged(MouseEvent e) {
void moved(MouseEvent e) {
if (elements != null) {
Vector pos = getPosVector(e);
Vector delta = raster(pos.sub(lastPos));
@ -746,13 +786,10 @@ public class CircuitComponent extends JComponent {
for (Moveable m : elements)
m.move(delta);
movement = movement.add(delta);
repaint();
lastPos = lastPos.add(delta);
}
}
return true;
}
@Override
@ -769,8 +806,8 @@ public class CircuitComponent extends JComponent {
}
@Override
void released(MouseEvent e) {
if (elements != null && !movement.isZero()) {
void clicked(MouseEvent e) {
if (elements != null) {
for (Moveable m : elements) {
if (m instanceof Wire)
circuit.add((Wire) m);
@ -782,6 +819,7 @@ public class CircuitComponent extends JComponent {
}
}
private interface Actor {
boolean interact(CircuitComponent cc, Point p);
}

View File

@ -0,0 +1,100 @@
package de.neemann.digital.gui.components;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import de.neemann.digital.draw.elements.Circuit;
import de.neemann.digital.draw.elements.Moveable;
import de.neemann.digital.draw.elements.VisualElement;
import de.neemann.digital.draw.graphics.GraphicMinMax;
import de.neemann.digital.draw.graphics.Vector;
import de.neemann.digital.draw.shapes.ShapeFactory;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
/**
* @author hneemann
*/
public class CircuitTransferable implements Transferable {
private String data;
/**
* Creates a new instance
*
* @param data the data to copy
*/
public CircuitTransferable(ArrayList<Moveable> data) {
XStream xStream = Circuit.getxStream();
try (StringWriter out = new StringWriter()) {
out.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
xStream.marshal(data, new PrettyPrintWriter(out));
this.data = out.toString();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public DataFlavor[] getTransferDataFlavors() {
return new DataFlavor[]{DataFlavor.stringFlavor};
}
@Override
public boolean isDataFlavorSupported(DataFlavor flavor) {
return flavor == DataFlavor.stringFlavor;
}
@Override
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
if (!isDataFlavorSupported(flavor))
throw new UnsupportedFlavorException(flavor);
return data;
}
/**
* Creates a list of objects from inserted data
*
* @param data the inserted data
* @param shapeFactory the shapeFactory to set to the elements
* @param lastMousePos the actual mouse position
* @return the elements or null
*/
public static ArrayList<Moveable> createList(Object data, ShapeFactory shapeFactory, Vector lastMousePos) {
if (!(data instanceof String))
return null;
XStream xStream = Circuit.getxStream();
Vector max = null;
try (Reader in = new StringReader(data.toString())) {
ArrayList<Moveable> elements = (ArrayList<Moveable>) xStream.fromXML(in);
for (Moveable m : elements)
if (m instanceof VisualElement) {
((VisualElement) m).setShapeFactory(shapeFactory);
GraphicMinMax mm = ((VisualElement) m).getMinMax();
if (max == null)
max = mm.getMax();
else
max = Vector.max(max, mm.getMax());
}
if (max != null) {
Vector delta = CircuitComponent.raster(lastMousePos.sub(max));
for (Moveable m : elements)
m.move(delta);
}
return elements;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}