From 7c5fe94421418ffc390aec82f5bf9a8661a873c0 Mon Sep 17 00:00:00 2001
From: Lukas Ladenberger <lukas.ladenberger@googlemail.com>
Date: Fri, 9 Nov 2012 10:31:39 +0100
Subject: [PATCH] fixed copy/paste controls (correct handling of connections)

---
 .../gef/editor/command/CopyCommand.java       |   4 +-
 .../gef/editor/command/CopyPasteHelper.java   |   7 +
 .../gef/editor/command/PasteCommand.java      | 121 +++++++++++++-----
 .../gef/editor/model/BConnection.java         |   7 -
 .../gef/editor/model/BControl.java            |  10 +-
 .../gef/editor/part/SwitchPart.java           |  25 ++--
 6 files changed, 117 insertions(+), 57 deletions(-)

diff --git a/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/command/CopyCommand.java b/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/command/CopyCommand.java
index 2fa07577..86190dff 100644
--- a/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/command/CopyCommand.java
+++ b/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/command/CopyCommand.java
@@ -12,6 +12,7 @@ import java.util.Iterator;
 import org.eclipse.gef.commands.Command;
 import org.eclipse.gef.ui.actions.Clipboard;
 
+import de.bmotionstudio.gef.editor.model.BConnection;
 import de.bmotionstudio.gef.editor.model.BControl;
 import de.bmotionstudio.gef.editor.model.Visualization;
 
@@ -51,7 +52,8 @@ public class CopyCommand extends Command {
 	}
 
 	public boolean isCopyableControl(BControl control) {
-		if (!(control instanceof Visualization))
+		if (!(control instanceof Visualization)
+				&& !(control instanceof BConnection))
 			return true;
 		return false;
 	}
diff --git a/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/command/CopyPasteHelper.java b/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/command/CopyPasteHelper.java
index 5d23251f..119d6ffe 100644
--- a/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/command/CopyPasteHelper.java
+++ b/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/command/CopyPasteHelper.java
@@ -7,12 +7,15 @@
 package de.bmotionstudio.gef.editor.command;
 
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
 
 import de.bmotionstudio.gef.editor.model.BControl;
 
 public class CopyPasteHelper {
 
 	private ArrayList<BControl> list = new ArrayList<BControl>();
+	private Map<BControl, BControl> alreadyCloned = new HashMap<BControl, BControl>();
 	private int distance = 10;
 
 	public CopyPasteHelper(ArrayList<BControl> list, int distance) {
@@ -36,4 +39,8 @@ public class CopyPasteHelper {
 		return distance;
 	}
 
+	public Map<BControl, BControl> getAlreadyClonedMap() {
+		return alreadyCloned;
+	}
+
 }
diff --git a/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/command/PasteCommand.java b/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/command/PasteCommand.java
index 7ecb8ecb..0932a3ed 100644
--- a/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/command/PasteCommand.java
+++ b/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/command/PasteCommand.java
@@ -24,12 +24,11 @@ public class PasteCommand extends Command {
 	private CopyPasteHelper cHelper;
 
 	// List with mapping original BControl ==> cloned BControl
-	private HashMap<BControl, BControl> list = new HashMap<BControl, BControl>();
+	private HashMap<BControl, BControl> mappingControl = new HashMap<BControl, BControl>();
+	private HashMap<BConnection, BConnection> mappingConnection = new HashMap<BConnection, BConnection>();
 
 	private List<BControl> parentControls = new ArrayList<BControl>();
 
-	private List<ConnectionCreateCommand> connectionCreateCmds = new ArrayList<ConnectionCreateCommand>();
-
 	@Override
 	public boolean canExecute() {
 		cHelper = (CopyPasteHelper) Clipboard.getDefault().getContents();
@@ -42,7 +41,7 @@ public class PasteCommand extends Command {
 		while (it.hasNext()) {
 			BControl node = (BControl) it.next();
 			if (isPastableControl(node)) {
-				list.put(node, null);
+				mappingControl.put(node, null);
 			}
 		}
 		return true;
@@ -65,13 +64,15 @@ public class PasteCommand extends Command {
 		if (!canExecute())
 			return;
 
-		for (BControl parent : parentControls) {
+		try {
+
+			for (BControl parent : parentControls) {
 
-			Iterator<BControl> it = list.keySet().iterator();
-			while (it.hasNext()) {
-				BControl control = (BControl) it.next();
-				control.setParent(parent);
-				try {
+				// Copy/Paste controls
+				Iterator<BControl> it = mappingControl.keySet().iterator();
+				while (it.hasNext()) {
+					BControl control = (BControl) it.next();
+					control.setParent(parent);
 					BControl clone = (BControl) control.clone();
 					clone.setParent(parent);
 					int x = Integer.valueOf(Integer.valueOf(clone
@@ -84,67 +85,119 @@ public class PasteCommand extends Command {
 							+ cHelper.getDistance());
 					clone.setAttributeValue(AttributeConstants.ATTRIBUTE_Y, y
 							+ cHelper.getDistance());
-					list.put(control, clone);
+					mappingControl.put(control, clone);
 					cHelper.setDistance(cHelper.getDistance() + 10);
+				}
+				
+				// Copy/Paste connections
+				HashMap<BControl, BControl> helpMap = new HashMap<BControl, BControl>();
+				helpMap.putAll(cHelper.getAlreadyClonedMap());
+				helpMap.putAll(mappingControl);
+
+				Iterator<BControl> it2 = helpMap.keySet().iterator();
+				while (it2.hasNext()) {
+					BControl control = it2.next();
 
 					// Clone connections
 					for (BConnection c : control.getSourceConnections()) {
-						BConnection cb = (BConnection) c.clone();
-						cb.setSource(clone);
-						ConnectionCreateCommand connectionCreateCommand = new ConnectionCreateCommand(
-								clone);
-						connectionCreateCommand.setConnection(cb);
-						connectionCreateCmds.add(connectionCreateCommand);
+
+						BConnection newConnection = mappingConnection.get(c);
+						if (newConnection == null) {
+							newConnection = (BConnection) c.clone();
+							newConnection.disconnect();
+							mappingConnection.put(c, newConnection);
+						}
+
+						BControl s = helpMap.get(newConnection
+								.getSource());
+						if (s == null)
+							s = newConnection.getSource();
+						BControl t = helpMap.get(newConnection
+								.getTarget());
+						if (t == null)
+							t = newConnection.getTarget();
+
+						newConnection.setTarget(t);
+						newConnection.setSource(s);
+
 					}
 
 					for (BConnection c : control.getTargetConnections()) {
-						BConnection cb = (BConnection) c.clone();
-						cb.setTarget(clone);
-						ConnectionCreateCommand connectionCreateCommand = new ConnectionCreateCommand(
-								cb.getSource());
-						connectionCreateCommand.setConnection(cb);
-						connectionCreateCmds.add(connectionCreateCommand);
+
+						BConnection newConnection = mappingConnection.get(c);
+						if (newConnection == null) {
+							newConnection = (BConnection) c.clone();
+							newConnection.disconnect();
+							mappingConnection.put(c, newConnection);
+						}
+
+						BControl t = helpMap.get(newConnection
+								.getTarget());
+						if (t == null)
+							t = newConnection.getTarget();
+						BControl s = helpMap.get(newConnection
+								.getSource());
+						if (s == null)
+							s = newConnection.getSource();
+
+						newConnection.setTarget(t);
+						newConnection.setSource(s);
+
 					}
 
-				} catch (CloneNotSupportedException e) {
-					e.printStackTrace();
 				}
+
+				redo();
+
 			}
-			redo();
 
+		} catch (CloneNotSupportedException e) {
+			e.printStackTrace();
 		}
 
 	}
 
 	@Override
 	public void redo() {
-		Iterator<BControl> it = list.values().iterator();
+
+		Iterator<BControl> it = mappingControl.values().iterator();
 		while (it.hasNext()) {
 			BControl control = it.next();
 			if (isPastableControl(control)) {
 				control.getParent().addChild(control);
-				for (ConnectionCreateCommand cmd : connectionCreateCmds)
-					cmd.redo();
 			}
 		}
+
+		Iterator<BConnection> it2 = mappingConnection.values().iterator();
+		while (it2.hasNext()) {
+			BConnection connection = it2.next();
+			connection.reconnect();
+		}
+
 	}
 
 	@Override
 	public boolean canUndo() {
-		return !(list.isEmpty());
+		return !(mappingControl.isEmpty());
 	}
 
 	@Override
 	public void undo() {
-		Iterator<BControl> it = list.values().iterator();
+
+		Iterator<BControl> it = mappingControl.values().iterator();
 		while (it.hasNext()) {
 			BControl bcontrol = it.next();
 			if (isPastableControl(bcontrol)) {
 				bcontrol.getParent().removeChild(bcontrol);
-				for (ConnectionCreateCommand cmd : connectionCreateCmds)
-					cmd.undo();
 			}
 		}
+
+		Iterator<BConnection> it2 = mappingConnection.values().iterator();
+		while (it2.hasNext()) {
+			BConnection connection = it2.next();
+			connection.disconnect();
+		}
+
 	}
 
 	public boolean isPastableControl(BControl control) {
@@ -154,7 +207,7 @@ public class PasteCommand extends Command {
 	}
 
 	public HashMap<BControl, BControl> getList() {
-		return this.list;
+		return this.mappingControl;
 	}
 
 }
diff --git a/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/model/BConnection.java b/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/model/BConnection.java
index e984e672..6b36f515 100644
--- a/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/model/BConnection.java
+++ b/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/model/BConnection.java
@@ -156,11 +156,4 @@ public class BConnection extends BControl {
 
 	}
 
-	@Override
-	public BControl clone() throws CloneNotSupportedException {
-		BConnection clonedControl = (BConnection) super.clone();
-		clonedControl.isConnected = false;
-		return clonedControl;
-	}
-
 }
\ No newline at end of file
diff --git a/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/model/BControl.java b/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/model/BControl.java
index 90b285c2..8013e19f 100644
--- a/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/model/BControl.java
+++ b/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/model/BControl.java
@@ -21,6 +21,7 @@ import org.eclipse.core.runtime.IConfigurationElement;
 import org.eclipse.draw2d.geometry.Dimension;
 import org.eclipse.draw2d.geometry.Point;
 import org.eclipse.draw2d.geometry.Rectangle;
+import org.eclipse.gef.ui.actions.Clipboard;
 import org.eclipse.swt.graphics.Image;
 import org.eclipse.ui.views.properties.IPropertySource;
 
@@ -39,6 +40,7 @@ import de.bmotionstudio.gef.editor.attribute.BAttributeVisible;
 import de.bmotionstudio.gef.editor.attribute.BAttributeWidth;
 import de.bmotionstudio.gef.editor.attribute.BAttributeX;
 import de.bmotionstudio.gef.editor.attribute.BAttributeY;
+import de.bmotionstudio.gef.editor.command.CopyPasteHelper;
 import de.bmotionstudio.gef.editor.internal.BControlPropertySource;
 import de.bmotionstudio.gef.editor.observer.IObserverListener;
 import de.bmotionstudio.gef.editor.observer.Observer;
@@ -666,7 +668,13 @@ public abstract class BControl implements IAdaptable, Cloneable {
 		clonedControl.setChildrenArray(new BControlList());
 		Iterator<BControl> it = getChildrenArray().iterator();
 		while (it.hasNext()) {
-			clonedControl.addChild(((BControl) it.next()).clone());
+			BControl next = (BControl) it.next();
+			BControl childClone = next.clone();
+			CopyPasteHelper cHelper = (CopyPasteHelper) Clipboard.getDefault()
+					.getContents();
+			if (cHelper != null)
+				cHelper.getAlreadyClonedMap().put(next, childClone);
+			clonedControl.addChild(childClone);
 		}
 
 		// Clone observer
diff --git a/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/part/SwitchPart.java b/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/part/SwitchPart.java
index 61ee4e3d..c9473dee 100644
--- a/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/part/SwitchPart.java
+++ b/de.bmotionstudio.gef.editor/src/de/bmotionstudio/gef/editor/part/SwitchPart.java
@@ -36,18 +36,15 @@ public class SwitchPart extends BMSAbstractEditPart {
 		String aID = evt.getPropertyName();
 		Switch sw = (Switch) model;
 		
-		if (aID.equals(AttributeConstants.ATTRIBUTE_SWITCH_POSITION)) {
-
-			Track track1 = sw.getTrack1();
-			Track track2 = sw.getTrack2();
+		Track track1 = sw.getTrack1();
+		Track track2 = sw.getTrack2();
 
+		if (aID.equals(AttributeConstants.ATTRIBUTE_SWITCH_POSITION)) {
 			if (track1 != null && track2 != null) {
-
 				track1.setAttributeValue(AttributeConstants.ATTRIBUTE_VISIBLE,
 						true);
 				track2.setAttributeValue(AttributeConstants.ATTRIBUTE_VISIBLE,
 						true);
-
 				if (value.equals(AttributeSwitchPosition.LEFT)) {
 					track1.setAttributeValue(
 							AttributeConstants.ATTRIBUTE_VISIBLE, false);
@@ -55,21 +52,21 @@ public class SwitchPart extends BMSAbstractEditPart {
 					track2.setAttributeValue(
 							AttributeConstants.ATTRIBUTE_VISIBLE, false);
 				}
-
 			}
-
 		}
 
 		if (aID.equals(AttributeConstants.ATTRIBUTE_SWITCH_DIRECTION))
 			refreshEditLayout(figure, model);
 
 		if (aID.equals(AttributeConstants.ATTRIBUTE_VISIBLE)) {
-			Boolean visible = Boolean.valueOf(value.toString());
-			((SwitchFigure) figure).setVisible(visible);
-			sw.getTrack1().setAttributeValue(
-					AttributeConstants.ATTRIBUTE_VISIBLE, visible);
-			sw.getTrack2().setAttributeValue(
-					AttributeConstants.ATTRIBUTE_VISIBLE, visible);
+			if (track1 != null && track2 != null) {
+				Boolean visible = Boolean.valueOf(value.toString());
+				((SwitchFigure) figure).setVisible(visible);
+				track1.setAttributeValue(
+						AttributeConstants.ATTRIBUTE_VISIBLE, visible);
+				track2.setAttributeValue(
+						AttributeConstants.ATTRIBUTE_VISIBLE, visible);
+			}
 		}
 
 	}
-- 
GitLab