mirror of
https://github.com/hneemann/Digital.git
synced 2025-09-16 08:25:09 -04:00
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:
parent
d468a8d576
commit
8471ff84f3
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user