Browse Source

FTG+PM: Auto-correct direction of arrow when connecting in -> out.

Joeri Exelmans 4 years ago
parent
commit
84d4402884
1 changed files with 53 additions and 19 deletions
  1. 53 19
      src/main/webapp/plugins/cdf/ftgpm-edit.js

+ 53 - 19
src/main/webapp/plugins/cdf/ftgpm-edit.js

@@ -70,12 +70,12 @@ Draw.loadPlugin(function(ui) {
     if (!sourceCell || !targetCell) {
       return;
     }
-
+    
     const sourceType = sourceCell.getAttribute("pmRole");
     const targetType = targetCell.getAttribute("pmRole");
 
-    for (const [from, to, linkType] of fromTo) {
-      if (from(sourceType) && to(targetType)) {
+    for (const [cond, linkType] of fromTo) {
+      if (cond(sourceType, targetType)) {
         setStyle(linkType);
       }
     }
@@ -120,6 +120,8 @@ Draw.loadPlugin(function(ui) {
     ui.editor.graph.addListener(mxEvent.CELL_CONNECTED, (_, eventObj) => {
       // Happens whenever an edge is (dis)connected.
 
+      const edge = eventObj.properties.edge;
+
       // This will change the edge style WITHIN the transaction of the edit operation.
       // The terminal-change and style-change will be one edit operation from point of view of undo manager.
 
@@ -129,6 +131,12 @@ Draw.loadPlugin(function(ui) {
       function isDataPort(type) {
         return type === "data_in" || type === "data_out";
       }
+      function isInport(type) {
+        return type === "data_in" || type === "ctrl_in";
+      }
+      function isOutport(type) {
+        return type === "data_out" || type === "ctrl_out";
+      }
       function isControlFlowNode(type) {
         return isControlFlowPort(type) || type === "initial" || type === "final" || type === "fork_join";
       }
@@ -136,21 +144,38 @@ Draw.loadPlugin(function(ui) {
         return isDataPort(type) || isArtifact(type);
       }
 
-      // [ from, to, style ]
+      // [ condition, style ]
       const fromTo = [
         // PM control flow
-        [ isControlFlowNode, isControlFlowNode, "control_flow" ],
+        [ (src, tgt) => isControlFlowNode(src) && isControlFlowNode(tgt), "control_flow" ],
 
         // PM data flow
-        [ isDataFlowNode, isDataFlowNode, "data_flow" ],
+        [ (src, tgt) => isDataFlowNode(src) && isDataFlowNode(tgt), "data_flow" ],
 
         // FTG data flow
-        [ isTransformation, isFormalism, "data_flow" ],
-        [ isFormalism, isTransformation, "data_flow" ],
+        [ (src, tgt) => isTransformation(src) && isFormalism(tgt), "data_flow" ],
+        [ (src, tgt) => isFormalism(src) && isTransformation(tgt), "data_flow" ],
 
       ].concat(typedByLinks);
 
-      checkEdge(ui, eventObj.properties.edge, fromTo);
+      // Update style
+      checkEdge(ui, edge, fromTo);
+
+      // Reverse direction, if necessary
+      const sourceCell = edge.source;
+      const targetCell = edge.getTerminal();
+
+      if (!sourceCell || !targetCell) {
+        return;
+      }
+
+      const sourceType = sourceCell.getAttribute("pmRole");
+      const targetType = targetCell.getAttribute("pmRole");
+      if (isInport(sourceType) && isOutport(targetType)) {
+        console.log("REVERSE");
+
+        ui.editor.graph.model.setTerminals(edge, targetCell, sourceCell); // swap
+      }
     });
 
     const portClasses = [ "data_in", "data_out", "ctrl_in", "ctrl_out", ];
@@ -261,10 +286,10 @@ Draw.loadPlugin(function(ui) {
       reversePortMapping.set(cell, cell.parent);
     }
 
-    function findPortsAndAttach(cells) {
+    function findPortsAndAttach(cells, moveCells) {
       for (const cell of cells) {
         if (cell.parent && cell.parent.geometry && isPort(cell.getAttribute("pmRole"))) {
-          attachPortToParent(cell, true);
+          attachPortToParent(cell, moveCells);
         }
       }      
     }
@@ -273,13 +298,17 @@ Draw.loadPlugin(function(ui) {
       // console.log("MOVE_CELLS:", eventObj);
 
       // High-level event: Happens when the user releases a dragged shape
-      findPortsAndAttach(eventObj.properties.cells);
+      findPortsAndAttach(eventObj.properties.cells, true);
     })
 
     ui.editor.graph.addListener(mxEvent.RESIZE_CELLS, (_, eventObj) => {
       console.log("RESIZE");
       console.log("EVENT:", eventObj);
 
+      // Resized shapes might contain ports:
+      findPortsAndAttach(eventObj.properties.cells, true);
+
+      // Move contained ports
       for (const parent of eventObj.properties.cells) {
         if (!parent.geometry) continue;
         const portList = portMapping.get(parent);
@@ -309,7 +338,10 @@ Draw.loadPlugin(function(ui) {
       console.log("GRAPH EVENT:", eventObj);
 
       // Root has changed (new model loaded)
-      findPortsAndAttach(Object.values(ui.editor.graph.model.cells));
+      findPortsAndAttach(
+        Object.values(ui.editor.graph.model.cells),
+        false, // only initialize portMapping and reversePortMapping - do not move cells when loading.
+      );
     });
 
     window.ui = ui;
@@ -326,21 +358,23 @@ Draw.loadPlugin(function(ui) {
         return type === "initial" || type === "final" || type === "fork_join" || type === "decision" || isActivityNode(type);
       }
 
+      const edge = eventObj.properties.edge;
+
       const fromTo = [
         // PM control flow
-        [ isControlFlowNode, isControlFlowNode, "control_flow" ],
+        [ (src, tgt) => isControlFlowNode(src) && isControlFlowNode(tgt), "control_flow" ],
 
         // PM data flow
-        [ isActivityNode, isArtifact, "data_flow" ],
-        [ isArtifact, isActivityNode, "data_flow" ],
+        [ (src, tgt) => isActivityNode(src) && isArtifact(tgt), "data_flow" ],
+        [ (src, tgt) => isArtifact(src) && isActivityNode(tgt), "data_flow" ],
 
         // FTG data flow
-        [ isTransformation, isFormalism, "data_flow" ],
-        [ isFormalism, isTransformation, "data_flow" ],
+        [ (src, tgt) => isTransformation(src) && isFormalism(tgt), "data_flow" ],
+        [ (src, tgt) => isFormalism(src) && isTransformation(tgt), "data_flow" ],
 
       ].concat(typedByLinks);
 
-      checkEdge(ui, eventObj.properties.edge, fromTo);
+      checkEdge(ui, edge, fromTo);
     });
 
     ui.loadLibrary(new LocalLibrary(ui, noportsExamplesLib, "FTG+PM: Examples"));