Repository: workcraft/workcraft
Issue: Anchor points are not moved on DFS copying for wagging

If there is an anchor point on the ark where wagging is applied, then the result may be confusing, as in all copies the anchor points will have the same coordinate -- it looks like an intersection of arcs.

The relative position of anchor points to the arc should be preserved relative to the arc, not their global position.

Changed files:
WorkcraftCore/src/org/workcraft/workspace/WorkspaceEntry.java, DfsPlugin/src/org/workcraft/plugins/dfs/commands/WaggingGenerator.java, WorkcraftCore/src/org/workcraft/dom/visual/ConnectionHelper.java, WorkcraftCore/src/org/workcraft/gui/MainWindow.java

diff --git a/DfsPlugin/src/org/workcraft/plugins/dfs/commands/WaggingGenerator.java b/DfsPlugin/src/org/workcraft/plugins/dfs/commands/WaggingGenerator.java
index 54b60bc9a..0a89e25ec 100644
--- a/DfsPlugin/src/org/workcraft/plugins/dfs/commands/WaggingGenerator.java
+++ b/DfsPlugin/src/org/workcraft/plugins/dfs/commands/WaggingGenerator.java
@@ -11,6 +11,7 @@ import org.workcraft.dom.Node;
 import org.workcraft.dom.math.MathConnection;
 import org.workcraft.dom.math.MathNode;
 import org.workcraft.dom.visual.BoundingBoxHelper;
+import org.workcraft.dom.visual.ConnectionHelper;
 import org.workcraft.dom.visual.VisualComponent;
 import org.workcraft.dom.visual.VisualTransformableNode;
 import org.workcraft.dom.visual.connections.ControlPoint;
@@ -81,7 +82,8 @@ public class WaggingGenerator {
         if (hasInterface.getSecond()) {
             insertPopControl();
         }
-        createGroups();
+        cleanup();
+        group();
     }
 
     private void replicateSelection() {
@@ -151,6 +153,9 @@ public class WaggingGenerator {
             }
             replica.copyStyle(connection);
             replica.copyShape(connection);
+            Point2D p = connection.getFirstCenter();
+            Point2D offset = new Point2D.Double(first.getX() - p.getX(), first.getY() - p.getY());
+            ConnectionHelper.moveControlPoints(replica, offset);
         }
         return replica;
     }
@@ -281,12 +286,15 @@ public class WaggingGenerator {
         }
     }
 
-    private void createGroups() {
+    private void cleanup() {
         dfs.selectNone();
         for (VisualComponent component: selectedComponents) {
             dfs.addToSelection(component);
         }
         dfs.deleteSelection();
+    }
+
+    private void group() {
         // data components
         ArrayList<Node> dataNodes = new ArrayList<>();
         for (WaggingData waggingData: wagging) {
diff --git a/WorkcraftCore/src/org/workcraft/dom/visual/ConnectionHelper.java b/WorkcraftCore/src/org/workcraft/dom/visual/ConnectionHelper.java
index 01d02b8c8..0803c5c47 100644
--- a/WorkcraftCore/src/org/workcraft/dom/visual/ConnectionHelper.java
+++ b/WorkcraftCore/src/org/workcraft/dom/visual/ConnectionHelper.java
@@ -199,6 +199,17 @@ public class ConnectionHelper {
         }
     }
 
+    public static void moveControlPoints(VisualConnection connection, Point2D offset) {
+        if ((connection != null) && (offset != null)) {
+            ConnectionGraphic graphic = connection.getGraphic();
+            for (ControlPoint cp:  graphic.getControlPoints()) {
+                Point2D p1 = cp.getPosition();
+                Point2D p2 = new Point2D.Double(p1.getX() + offset.getX(), p1.getY() + offset.getY());
+                cp.setPosition(p2);
+            }
+        }
+    }
+
     public static void removeControlPointsByDistance(Polyline polyline, Point2D pos, double threshold) {
         List<ControlPoint> controlPoints = new LinkedList<>(polyline.getControlPoints());
         for (ControlPoint cp:  controlPoints) {
diff --git a/WorkcraftCore/src/org/workcraft/gui/MainWindow.java b/WorkcraftCore/src/org/workcraft/gui/MainWindow.java
index 0803f8656..59010fcbe 100644
--- a/WorkcraftCore/src/org/workcraft/gui/MainWindow.java
+++ b/WorkcraftCore/src/org/workcraft/gui/MainWindow.java
@@ -139,8 +139,8 @@ public class MainWindow extends JFrame {
     private static final String DIALOG_RESET_LAYOUT = "Reset layout";
 
     private final ScriptedActionListener defaultActionListener = new ScriptedActionListener() {
-        public void actionPerformed(Action e) {
-            e.run();
+        public void actionPerformed(Action action) {
+            action.run();
         }
     };
 
@@ -784,8 +784,9 @@ public class MainWindow extends JFrame {
         }
         // Set file filters
         fc.setAcceptAllFileFilterUsed(false);
-        fc.setFileFilter(FileFilters.DOCUMENT_FILES);
-        if (importers != null) {
+        if ((importers == null) || (importers.length == 0)) {
+            fc.setFileFilter(FileFilters.DOCUMENT_FILES);
+        } else {
             for (Importer importer : importers) {
                 fc.addChoosableFileFilter(new ImporterFileFilter(importer));
             }
@@ -1034,8 +1035,8 @@ public class MainWindow extends JFrame {
 
         JFileChooser fc = createOpenDialog("Import model(s)", true, importers);
         if (fc.showDialog(this, "Open") == JFileChooser.APPROVE_OPTION) {
-            for (File f : fc.getSelectedFiles()) {
-                importFrom(f, importers);
+            for (File file : fc.getSelectedFiles()) {
+                importFrom(file, importers);
             }
         }
     }
diff --git a/WorkcraftCore/src/org/workcraft/workspace/WorkspaceEntry.java b/WorkcraftCore/src/org/workcraft/workspace/WorkspaceEntry.java
index d2ff7d380..7391acdd7 100644
--- a/WorkcraftCore/src/org/workcraft/workspace/WorkspaceEntry.java
+++ b/WorkcraftCore/src/org/workcraft/workspace/WorkspaceEntry.java
@@ -332,7 +332,7 @@ public class WorkspaceEntry implements ObservableState {
         if (model.getSelection().size() > 0) {
             captureMemento();
             try {
-                // copy selected nodes inside a group as if it was the root
+                // Copy selected nodes inside a group as if it was the root.
                 while (model.getCurrentLevel() != model.getRoot()) {
                     Collection<Node> nodes = new HashSet<>(model.getSelection());
                     Container level = model.getCurrentLevel();
@@ -349,8 +349,7 @@ public class WorkspaceEntry implements ObservableState {
                 final Framework framework = Framework.getInstance();
                 framework.clipboard = framework.saveModel(modelEntry);
                 if (CommonDebugSettings.getCopyModelOnChange()) {
-                    // copy the memento clipboard into the system-wide clipboard
-                    // as a string
+                    // Copy the memento clipboard into the system-wide clipboard as a string.
                     Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
                     clipboard.setContents(new StringSelection(getClipboardAsString()), null);
                 }