Bug 534642 - Visual feedback for straight links crossing each other.

Also-By: Anna Haas <haas@fortiss.org>
Signed-off-by: Florian Hoelzl <hoelzl@fortiss.org>
diff --git a/org.eclipse.systemfocus.kernel.base.ui/src/org/eclipse/systemfocus/kernel/base/ui/graphical/editor/controller/.ratings b/org.eclipse.systemfocus.kernel.base.ui/src/org/eclipse/systemfocus/kernel/base/ui/graphical/editor/controller/.ratings
index 27e065c..8a704ea 100644
--- a/org.eclipse.systemfocus.kernel.base.ui/src/org/eclipse/systemfocus/kernel/base/ui/graphical/editor/controller/.ratings
+++ b/org.eclipse.systemfocus.kernel.base.ui/src/org/eclipse/systemfocus/kernel/base/ui/graphical/editor/controller/.ratings
@@ -1,4 +1,4 @@
-EObjectBasedDiagramControllerBase.java 8db601875f7f8bec42f126db8dac017f7b0372a6 RED
+EObjectBasedDiagramControllerBase.java 716bad8e6a6b052164e3d094da8f3fd5b6251d69 RED
 EObjectBasedRectangularResizableContentControllerBase.java 3d75a2c5e5a4578d027ecc98c9ca6dce59dd0775 YELLOW
 LayoutedModelElementBasedContentAnchorageController.java 21d885a9c68e3497ab5237853fe7384300e09c59 RED
 LayoutedModelElementBasedDiagramAnchorageController.java 7528b3f92480bb01299223b236afe9470a41f172 RED
diff --git a/org.eclipse.systemfocus.kernel.base.ui/src/org/eclipse/systemfocus/kernel/base/ui/graphical/editor/controller/EObjectBasedDiagramControllerBase.java b/org.eclipse.systemfocus.kernel.base.ui/src/org/eclipse/systemfocus/kernel/base/ui/graphical/editor/controller/EObjectBasedDiagramControllerBase.java
index 8db6018..716bad8 100644
--- a/org.eclipse.systemfocus.kernel.base.ui/src/org/eclipse/systemfocus/kernel/base/ui/graphical/editor/controller/EObjectBasedDiagramControllerBase.java
+++ b/org.eclipse.systemfocus.kernel.base.ui/src/org/eclipse/systemfocus/kernel/base/ui/graphical/editor/controller/EObjectBasedDiagramControllerBase.java
@@ -14,7 +14,6 @@
 package org.eclipse.systemfocus.kernel.base.ui.graphical.editor.controller;
 
 import static java.lang.Math.max;
-import static java.util.Collections.singletonList;
 import static java.util.Objects.requireNonNull;
 import static org.eclipse.systemfocus.kernel.base.ui.graphical.editor.controller.Utils.createLinkByCommand;
 import static org.eclipse.systemfocus.kernel.core.ui.utils.CompositionUtils.createSubContextWithCompositionLocation;
@@ -86,6 +85,7 @@
 	/** {@inheritDoc} */
 	@Override
 	public List<MenuItem> contextMenuContributions(double x, double y) {
+		List<MenuItem> menuList = super.contextMenuContributions(x, y);
 		// outer-most grid areas of the diagram are inaccessible
 		GridConfiguration gridConf = getViewer().getGridConfig();
 		x = max(gridConf.getHorizontalSpacing(), x);
@@ -98,9 +98,9 @@
 		if(items != null && !items.isEmpty()) {
 			Menu newMenu = new Menu("New ...");
 			newMenu.getItems().addAll(items);
-			return singletonList(newMenu);
+			menuList.add(0, newMenu);
 		}
-		return null;
+		return menuList;
 	}
 
 	/** The model change listener list. */
diff --git a/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/.ratings b/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/.ratings
index 27fd714..f0e8381 100644
--- a/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/.ratings
+++ b/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/.ratings
@@ -1,5 +1,5 @@
 DiagramLayers.java 14cd8766eec2aa4da4f698b134a6f2c22a0b5c2e YELLOW
-DiagramViewer.java ddbb88398fd1230862ca91b527d1b15cd44138bd YELLOW
+DiagramViewer.java 6a1b84bab3e11fd21b18aa7dd3255db8559de7f8 YELLOW
 DiagramViewerDefaultTags.java dd93a45a79cf386696762b12460080d8310001b4 YELLOW
 EDragGesture.java 222f421d3dc99dbed1dc28c6428a60ce8e6df615 YELLOW
 FeedbackChange.java 529ff9430cdac3a906bee9dd72de53bc04a2d071 YELLOW
diff --git a/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/DiagramViewer.java b/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/DiagramViewer.java
index ddbb883..6a1b84b 100644
--- a/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/DiagramViewer.java
+++ b/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/DiagramViewer.java
@@ -57,6 +57,7 @@
 import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.visual.ILinkVisual;
 import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.visual.IVisual;
 import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.visual.IVisualFactory;
+import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.visual.rectangular.LineLinkGraph;
 
 import javafx.event.EventHandler;
 import javafx.geometry.Bounds;
@@ -122,6 +123,8 @@
 	private boolean linkHighlightingEnabled = false;
 	/** The current context menu. */
 	private ContextMenu contextMenu = null;
+	/** The graph for straight links. */
+	private LineLinkGraph lineLinkGraph = new LineLinkGraph();
 
 	/** The selection changed runnable used to notify about selection changes. */
 	private final Runnable selectionChangedRunnable;
@@ -237,6 +240,8 @@
 
 		// update the viewer content
 		updateContentObjects();
+
+		linkHighlightingEnabled = true;
 	}
 
 	/** Returns the {@link IDiagramMVCBundle}. */
@@ -592,6 +597,11 @@
 		}
 		// single selection clears old selection
 		IMVCBundle oldSelection = primarySelectedBundle;
+		if(oldSelection != null) {
+			oldSelection.removeTag(FOCUS_TAG);
+			oldSelection.removeTag(PRIMARY_SELECTION_TAG);
+			oldSelection.getVisual().updateNodes(layers);
+		}
 		primarySelectedBundle = sel;
 		if(primarySelectedBundle != null) {
 			primarySelectedBundle.getVisual().requestFocus();
@@ -599,11 +609,6 @@
 			primarySelectedBundle.addTag(PRIMARY_SELECTION_TAG);
 			primarySelectedBundle.getVisual().updateNodes(layers);
 		}
-		if(oldSelection != null) {
-			oldSelection.removeTag(FOCUS_TAG);
-			oldSelection.removeTag(PRIMARY_SELECTION_TAG);
-			oldSelection.getVisual().updateNodes(layers);
-		}
 		fireSelectionChanged();
 	}
 
@@ -981,6 +986,16 @@
 		}
 	}
 
+	/** Returns the lineLinkGraph. */
+	public LineLinkGraph getLineLinkGraph() {
+		return lineLinkGraph;
+	}
+
+	/** Returns linkBundles. */
+	public List<ILinkMVCBundle> getLinkBundles() {
+		return linkBundles;
+	}
+
 	/** Returns whether link highlighting is enabled. */
 	public boolean isLinkHighlightingEnabled() {
 		return linkHighlightingEnabled;
diff --git a/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/controller/base/.ratings b/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/controller/base/.ratings
index 4fd8f1c..608c2cf 100644
--- a/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/controller/base/.ratings
+++ b/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/controller/base/.ratings
@@ -2,6 +2,7 @@
 ControllerBase.java ed0ab2278b44fba802ce094ee10c35fb9a74a9a1 YELLOW
 DefaultContentAnchorageControllerBase.java 2e3189972cf34f5cc868bd458c84cb3d2f0eddf1 YELLOW
 DefaultDiagramAnchorageControllerBase.java 0df0e7868a61043611eb3db15ad8108c5cbb7f76 YELLOW
+DefaultDiagramController.java 2e41d84e472816615bcefa9dd9683500d17021e0 YELLOW
 DragControllerBase.java 217c6fd1a212d82581478a350c5746def868639f YELLOW
 LinkBendPointControllerBase.java 3be7d0474d026c362e81f404e8d1899b478880b0 YELLOW
 ResizableContentControllerBase.java 57a19ddd32a6c42c299b8cf30e609c2b33584d45 YELLOW
diff --git a/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/controller/base/DefaultDiagramController.java b/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/controller/base/DefaultDiagramController.java
new file mode 100644
index 0000000..2e41d84
--- /dev/null
+++ b/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/controller/base/DefaultDiagramController.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2017, 2018 fortiss GmbH. 
+ * 
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v2.0 which is available at
+ * http://www.eclipse.org/legal/epl-v20.html
+ * 
+ * SPDX-License-Identifier: EPL-2.0
+ * 
+ * Contributors:
+ *     Florian Hoelzl (fortiss GmbH) - initial implementation
+ *
+ *******************************************************************************/
+package org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.controller.base;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.mvc.IMVCBundle;
+
+import javafx.scene.control.Menu;
+import javafx.scene.control.MenuItem;
+
+/**
+ * Default implementation for diagram controller, which proves an empty list of context menu items.
+ */
+public class DefaultDiagramController extends ControllerBase {
+	/** Constructor. */
+	public DefaultDiagramController(IMVCBundle mvcb) {
+		super(mvcb);
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public List<MenuItem> contextMenuContributions(double x, double y) {
+		List<MenuItem> superList = super.contextMenuContributions(x, y);
+
+		MenuItem enableLinkHighlighting = new MenuItem("Enable Link Highlighting");
+		enableLinkHighlighting.setOnAction(evt -> {
+			getViewer().setLinkHighlightingEnabled(true);
+			getViewer().updateAllVisuals();
+		});
+		MenuItem disableLinkHighlighting = new MenuItem("Disable Link Highlighting");
+		disableLinkHighlighting.setOnAction(evt -> {
+			getViewer().setLinkHighlightingEnabled(false);
+			getViewer().updateAllVisuals();
+		});
+
+		Menu menu = new Menu("Display ...");
+		menu.getItems().add(enableLinkHighlighting);
+		menu.getItems().add(disableLinkHighlighting);
+
+		List<MenuItem> menuList = new LinkedList<>();
+		menuList.add(menu);
+		menuList.addAll(superList);
+		return menuList;
+	}
+}
diff --git a/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/mvc/impl/.ratings b/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/mvc/impl/.ratings
index da00b88..316aa6b 100644
--- a/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/mvc/impl/.ratings
+++ b/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/mvc/impl/.ratings
@@ -1,8 +1,10 @@
 AnchorageMVCBundleBase.java f7d1e309601809e60f501635dd7a5aeafb4d5944 YELLOW
 ContentAnchorageMVCBundle.java c1ad94481520f0c872074084e4a84dde531e60f6 YELLOW
 ContentMVCBundle.java d75ad6f02206958e13b1899f7fa30adf8ff4debf YELLOW
+DefaultMVCBTags.java 6b39227bd505179fd75568785ce328ad05e23174 YELLOW
 DiagramAnchorageMVCBundle.java f38b0e5e427ac646d026b1b7dbfa05466409093d YELLOW
 DiagramMVCBundle.java 1ae946b7839deda10727b75ea679fdfdcea20fbe YELLOW
 LinkMVCBundle.java d406a6bf96c58c395ee53c0c74130248bbf1c76b YELLOW
-MVCBundleBase.java 73287cf259365e8c4ae95fbf0c3fd82807d2efb9 YELLOW
+MVCBundleBase.java d1781f0397efc18db17a8671bc0355285a39f843 YELLOW
 MVCBundlePartBase.java c4c453c86ae7933a4c154dc46e31159c03482931 YELLOW
+MVCBundleTag.java 8d977977a8de160afcb606f0eae85283d2068d91 YELLOW
diff --git a/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/mvc/impl/MVCBundleBase.java b/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/mvc/impl/MVCBundleBase.java
index 73287cf..d1781f0 100644
--- a/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/mvc/impl/MVCBundleBase.java
+++ b/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/mvc/impl/MVCBundleBase.java
@@ -46,7 +46,7 @@
 	private IController controller;
 	/** The current feedback change applied to this bundle's visual. */
 	private FeedbackChange feedbackChange = new FeedbackChange();
-	/** The tag identifier to tag map. */
+	/** The set of {@link MVCBundleTag}s. */
 	private final Map<String, MVCBundleTag> tagMap = new HashMap<>();
 
 	/** Constructor. */
diff --git a/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/visual/base/.ratings b/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/visual/base/.ratings
index 729c1a4..57cf3aa 100644
--- a/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/visual/base/.ratings
+++ b/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/visual/base/.ratings
@@ -3,5 +3,5 @@
 DiagramAnchorageVisualBase.java 7026a5ae501b975061f47ebda9a9f871f947c42e YELLOW
 LinkVisualBase.java 8459ace47660234116acbdcf7038bede96828c46 YELLOW
 MVCBundlePartWithEffectsBase.java 971c7cdb403598aa0e8f9f871401caa884b7bf60 YELLOW
-ResizableContentVisualBase.java cc3cef70d35a7672e8b5fb6f8f8c62cf9b881117 YELLOW
+ResizableContentVisualBase.java d2d7e54951a90d1fea56dbf87d903013343791d2 YELLOW
 VisualBase.java 2bea191ca6736c2e89c222473803c0e4890820eb YELLOW
diff --git a/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/visual/base/ResizableContentVisualBase.java b/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/visual/base/ResizableContentVisualBase.java
index cc3cef7..d2d7e54 100644
--- a/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/visual/base/ResizableContentVisualBase.java
+++ b/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/visual/base/ResizableContentVisualBase.java
@@ -121,7 +121,6 @@
 				layers.getContentInteractionLayer().add(hvHandle, bundle);
 			}
 		}
-
 		if(getViewer().isLinkHighlightingEnabled()) {
 			List<IContentAnchorageMVCBundle> anchoragesBundles = bundle.getAnchorages();
 			for(IContentAnchorageMVCBundle aBundle : anchoragesBundles) {
diff --git a/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/visual/rectangular/.ratings b/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/visual/rectangular/.ratings
index fc83f9e..83404ec 100644
--- a/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/visual/rectangular/.ratings
+++ b/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/visual/rectangular/.ratings
@@ -1,4 +1,5 @@
-LineLinkVisualBase.java ea315aa54996a80672affd45699bf4881add80c2 YELLOW
+LineLinkGraph.java dfa63d3c13547d142c27085c9b74d33c9226db38 YELLOW
+LineLinkVisualBase.java fc42a33af7b56e776beadd49d5683886cc36293e RED
 LineSegment.java ec1cde0fc9bb58326144149a1360a61d27dc4135 YELLOW
 RectangularBorderLocation.java c6c8641012c31e0bb939e6bdf0dfa1f020cc3c51 YELLOW
 RectangularContentAnchorageVisualBase.java cf2040293cc468cf8e97cd3656bc66580a08eea6 YELLOW
diff --git a/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/visual/rectangular/LineLinkGraph.java b/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/visual/rectangular/LineLinkGraph.java
new file mode 100644
index 0000000..dfa63d3
--- /dev/null
+++ b/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/visual/rectangular/LineLinkGraph.java
@@ -0,0 +1,71 @@
+/*******************************************************************************
+ * Copyright (c) 2018 fortiss GmbH. 
+ * 
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v2.0 which is available at
+ * http://www.eclipse.org/legal/epl-v20.html
+ * 
+ * SPDX-License-Identifier: EPL-2.0
+ * 
+ * Contributors:
+ *     Anna Haas (fortiss GmbH) - initial implementation
+ *
+ *******************************************************************************/
+package org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.visual.rectangular;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javafx.scene.shape.Line;
+import javafx.util.Pair;
+
+/** This class represents all rectangular lines. */
+public class LineLinkGraph {
+	/** Maps the LineSegment to its Lines. */
+	private Map<LineSegment, List<Line>> segment2lines = new HashMap<>();
+	/** Maps the Line to its LineSegment. */
+	private Map<Line, LineSegment> line2segment = new HashMap<>();
+	/** Maps the Line to every Line Pair that is interrupted by it. */
+	private Map<Line, Set<Pair<Line, Line>>> line2interruptedLine = new HashMap<>();
+
+	/** Adds a new LineSegment to the graph. */
+	public void addSegment(LineSegment seg, List<Line> lines) {
+		segment2lines.put(seg, lines);
+		for(Line l : lines) {
+			line2segment.put(l, seg);
+		}
+	}
+
+	/** Removes the LineSegment from the graph. */
+	public void removeSegment(LineSegment seg, List<Line> lines) {
+		segment2lines.remove(seg);
+		for(Line l : lines) {
+			line2segment.remove(l);
+		}
+	}
+
+	/** Adds a new interrupted line. */
+	public void addInterruptedLine(Line line, Line interruptedLine1, Line interruptedLine2) {
+		Set<Pair<Line, Line>> set = line2interruptedLine.get(line);
+		if(set == null)
+			set = new HashSet<>();
+		set.add(new Pair<>(interruptedLine1, interruptedLine2));
+		line2interruptedLine.put(line, set);
+	}
+
+	/** Adds new interrupted lines. */
+	public void addInterruptedLines(Map<Line, Pair<Line, Line>> lines) {
+		for(Line line : lines.keySet()) {
+			Pair<Line, Line> pair = lines.get(line);
+			addInterruptedLine(line, pair.getKey(), pair.getValue());
+		}
+	}
+
+	/** Returns line2segment. */
+	public Map<Line, LineSegment> getLine2segment() {
+		return line2segment;
+	}
+}
diff --git a/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/visual/rectangular/LineLinkVisualBase.java b/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/visual/rectangular/LineLinkVisualBase.java
index ea315aa..fc42a33 100644
--- a/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/visual/rectangular/LineLinkVisualBase.java
+++ b/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/visual/rectangular/LineLinkVisualBase.java
@@ -13,20 +13,15 @@
  *******************************************************************************/
 package org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.visual.rectangular;
 
-import static org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.DiagramViewerDefaultTags.FOCUS_TAG;
-import static org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.DiagramViewerDefaultTags.HIGHLIGHT_INCOMING_LINK_TAG;
-import static org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.DiagramViewerDefaultTags.HIGHLIGHT_OUTGOING_LINK_TAG;
-import static org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.DiagramViewerDefaultTags.PRIMARY_SELECTION_TAG;
-
 import java.util.LinkedList;
 import java.util.List;
 
 import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.DiagramLayers;
+import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.DiagramViewerDefaultTags;
 import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.EDragGesture;
 import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.FeedbackChange;
 import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.mvc.IAnchorageMVCBundle;
 import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.mvc.ILinkMVCBundle;
-import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.mvc.IMVCBundle;
 import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.mvc.impl.LinkMVCBundle;
 import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.visual.base.LinkVisualBase;
 
@@ -58,16 +53,20 @@
 		int pts = getNumberOfBendPoints();
 		for(int i = 0; i < pts; i++) {
 			Point2D bp = getBendPointLocation(i);
-			segments.add(new LineSegment(bpModel, sx, sy, bp.getX(), bp.getY(), this,
-					getBendPointMarkerSize(), false, false, 0));
-			sx = bp.getX();
-			sy = bp.getY();
+			FeedbackChange chg = getFeedbackChangeForBendPoint(i);
+			double nx = bp.getX() + chg.getDeltaX();
+			double ny = bp.getY() + chg.getDeltaY();
+			segments.add(new LineSegment(bpModel, sx, sy, nx, ny, this, getBendPointMarkerSize(),
+					false, false, 0, getViewer().getLineLinkGraph()));
+			sx = nx;
+			sy = ny;
 			bpModel = getBendPointModel(i);
 		}
 		// end point
 		Point2D endPoint = getEndAnchorPoint();
 		segments.add(new LineSegment(bpModel, sx, sy, endPoint.getX(), endPoint.getY(), this, 0,
-				showArrowOnLastSegment(), useLineArrow(), getArrowLength()));
+				showArrowOnLastSegment(), useLineArrow(), getArrowLength(),
+				getViewer().getLineLinkGraph()));
 
 		ILinkMVCBundle bundle = getLinkBundle();
 		for(LineSegment ls : segments) {
@@ -89,58 +88,79 @@
 	@Override
 	public void updateNodes(DiagramLayers layers) {
 		super.updateNodes(layers);
-		int pts = getNumberOfBendPoints();
-		if(segments.size() != pts + 1) {
-			removeNodes(layers);
-			addNodes(layers);
-			if(getViewer().getSelectedMVCBundle() == getLinkBundle()) {
-				if(getViewer().hasFocus()) {
-					applySelectedFocusedEffect(layers);
-				} else {
-					applySelectedNotFocusedEffect(layers);
-				}
+		// update every lineLinkVisualBase
+		List<ILinkMVCBundle> linkBundle = getViewer().getLinkBundles();
+		for(ILinkMVCBundle l : linkBundle) {
+			if(l.getVisual() instanceof LineLinkVisualBase) {
+				LineLinkVisualBase visual = (LineLinkVisualBase)l.getVisual();
+				visual.updateThisNodes(layers);
 			}
-			return;
 		}
+		// FIXME: merged from master
+		// int pts = getNumberOfBendPoints();
+		// if(segments.size() != pts + 1) {
+		// removeNodes(layers);
+		// addNodes(layers);
+		// if(getViewer().getSelectedMVCBundle() == getLinkBundle()) {
+		// if(getViewer().hasFocus()) {
+		// applySelectedFocusedEffect(layers);
+		// } else {
+		// applySelectedNotFocusedEffect(layers);
+		// }
+		// }
+		// }
+	}
 
-		int segIndex = 0;
-		// start point
-		Point2D start = getStartAnchorPoint();
-		double sx = start.getX();
-		double sy = start.getY();
-		// handle bend points
-		for(int i = 0; i < pts; i++) {
-			Point2D bp = getBendPointLocation(i);
-			FeedbackChange chg = getFeedbackChangeForBendPoint(i);
-			double nx = bp.getX() + chg.getDeltaX();
-			double ny = bp.getY() + chg.getDeltaY();
-			segments.get(segIndex).update(sx, sy, nx, ny, getBendPointMarkerSize(), 0);
+	/** Updates this visual's nodes. */
+	public void updateThisNodes(DiagramLayers layers) {
+		super.updateNodes(layers);
 
-			sx = nx;
-			sy = ny;
-			segIndex++;
-		}
-		// end point
-		Point2D endPoint = getEndAnchorPoint();
-		segments.get(segIndex).update(sx, sy, endPoint.getX(), endPoint.getY(), 0,
-				getArrowLength());
+		removeNodes(layers);
+		addNodes(layers);
 
-		Paint color = getLineColor();
-		IMVCBundle mvcBundle = getMVCBundle();
-		if(mvcBundle.hasTag(HIGHLIGHT_INCOMING_LINK_TAG)) {
-			color = getHighlightIncomingLinkColor();
-		} else if(mvcBundle.hasTag(HIGHLIGHT_OUTGOING_LINK_TAG)) {
-			color = getHighlightOutgoingLinkColor();
-		} else if(mvcBundle.hasTag(PRIMARY_SELECTION_TAG)) {
-			if(mvcBundle.hasTag(FOCUS_TAG)) {
-				color = getSelectionFocusedColor();
+		if(getViewer().getSelectedMVCBundle() == getLinkBundle()) {
+			if(getViewer().hasFocus()) {
+				applySelectedFocusedEffect(layers);
 			} else {
-				color = getSelectionNotFocusedColor();
+				applySelectedNotFocusedEffect(layers);
 			}
 		}
-		for(LineSegment seg : segments) {
-			seg.getVisibleLine().setStroke(color);
+
+		if(getMVCBundle().hasTag(DiagramViewerDefaultTags.HIGHLIGHT_INCOMING_LINK_TAG)) {
+			for(LineSegment seg : segments) {
+				seg.setStrokeColor(getHighlightIncomingLinkColor());
+			}
+		} else if(getMVCBundle().hasTag(DiagramViewerDefaultTags.HIGHLIGHT_OUTGOING_LINK_TAG)) {
+			for(LineSegment seg : segments) {
+				seg.setStrokeColor(getHighlightOutgoingLinkColor());
+			}
+		} else {
+			for(LineSegment seg : segments) {
+				seg.setStrokeColor(getLineColor());
+			}
 		}
+		// FIXME: merged from master
+		// // end point
+		// Point2D endPoint = getEndAnchorPoint();
+		// segments.get(segIndex).update(sx, sy, endPoint.getX(), endPoint.getY(), 0,
+		// getArrowLength());
+		//
+		// Paint color = getLineColor();
+		// IMVCBundle mvcBundle = getMVCBundle();
+		// if(mvcBundle.hasTag(HIGHLIGHT_INCOMING_LINK_TAG)) {
+		// color = getHighlightIncomingLinkColor();
+		// } else if(mvcBundle.hasTag(HIGHLIGHT_OUTGOING_LINK_TAG)) {
+		// color = getHighlightOutgoingLinkColor();
+		// } else if(mvcBundle.hasTag(PRIMARY_SELECTION_TAG)) {
+		// if(mvcBundle.hasTag(FOCUS_TAG)) {
+		// color = getSelectionFocusedColor();
+		// } else {
+		// color = getSelectionNotFocusedColor();
+		// }
+		// }
+		// for(LineSegment seg : segments) {
+		// seg.getVisibleLine().setStroke(color);
+		// }
 	}
 
 	/** {@inheritDoc} */
@@ -186,7 +206,8 @@
 	public void applySelectedFocusedEffect(DiagramLayers layers) {
 		ILinkMVCBundle bundle = getLinkBundle();
 		for(LineSegment seg : segments) {
-			seg.getVisibleLine().setStroke(getSelectionFocusedColor());
+			// seg.getVisibleLine().setStroke(getSelectionFocusedColor());
+			seg.setStrokeColor(getSelectionFocusedColor());
 			seg.addFeedbackNodes(layers, bundle);
 		}
 	}
@@ -195,7 +216,8 @@
 	@Override
 	public void applySelectedNotFocusedEffect(DiagramLayers layers) {
 		for(LineSegment seg : segments) {
-			seg.getVisibleLine().setStroke(getSelectionNotFocusedColor());
+			// seg.getVisibleLine().setStroke(getSelectionNotFocusedColor());
+			seg.setStrokeColor(getSelectionNotFocusedColor());
 			seg.removeFeedbackNodes(layers);
 		}
 	}
@@ -205,7 +227,8 @@
 	public void removeAllEffects(DiagramLayers layers) {
 		super.removeAllEffects(layers);
 		for(LineSegment seg : segments) {
-			seg.getVisibleLine().setStroke(getLineColor());
+			// seg.getVisibleLine().setStroke(getLineColor());
+			seg.setStrokeColor(getLineColor());
 			seg.removeFeedbackNodes(layers);
 		}
 	}
@@ -332,6 +355,25 @@
 		}
 	}
 
+	/** Returns whether two segments are neighbors in this lineLinkVisualBase. */
+	public boolean neighbors(LineSegment seg1, LineSegment seg2) {
+		if(segments.size() == 1 || !segments.contains(seg1) || !segments.contains(seg2))
+			return false;
+		for(int i = 0; i < segments.size() - 1; i++) {
+			if(seg1.equals(segments.get(i))) {
+				if(seg2.equals(segments.get(i + 1)))
+					return true;
+				break;
+			}
+			if(seg2.equals(segments.get(i))) {
+				if(seg1.equals(segments.get(i + 1)))
+					return true;
+				break;
+			}
+		}
+		return false;
+	}
+
 	/** {@inheritDoc} */
 	@Override
 	public EDragGesture getDragGesture(Node node, Point2D locationOnNode) {
diff --git a/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/visual/rectangular/LineSegment.java b/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/visual/rectangular/LineSegment.java
index ec1cde0..c97df0a 100644
--- a/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/visual/rectangular/LineSegment.java
+++ b/org.eclipse.systemfocus.kernel.common.ui/src/org/eclipse/systemfocus/kernel/common/ui/javafx/lwfxef/visual/rectangular/LineSegment.java
@@ -15,12 +15,18 @@
 
 import static javafx.scene.paint.Color.TRANSPARENT;
 
+import java.util.LinkedList;
+import java.util.List;
+
 import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.DiagramLayers;
 import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.DiagramLayers.ILayer;
 import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.mvc.ILinkMVCBundle;
 import org.eclipse.systemfocus.kernel.common.ui.javafx.lwfxef.visual.handles.LinkArrowWidget;
 
+import javafx.geometry.Point2D;
 import javafx.scene.paint.Color;
+import javafx.scene.paint.Paint;
+import javafx.scene.shape.Arc;
 import javafx.scene.shape.Line;
 import javafx.scene.shape.Rectangle;
 
@@ -38,23 +44,33 @@
 	private final Object bendPointModel;
 	/** The visible line. */
 	private final Line visibleLine;
+	/** Set of visible lines */
+	private List<Line> visibleLines = new LinkedList<>();
 	/** The invisible line. */
 	private final Line clickableLine;
 	/** The selection feedback handle rectangle. */
 	private final Rectangle feedbackHandle;
 	/** The arrow head widget. */
 	private final LinkArrowWidget arrowWidget;
+	/** List of all bridges. */
+	private List<Arc> bridges = new LinkedList<>();
+	/** Graph representing all rectangular lines. */
+	private LineLinkGraph lineLinkGraph;
+	/** The visual for this segment. */
+	private LineLinkVisualBase visual;
 
 	/** Constructor. */
 	public LineSegment(double sx, double sy, double ex, double ey, LineLinkVisualBase visual,
-			double markerSize, boolean showArrow, boolean useLineArrow, double arrowLength) {
-		this(null, sx, sy, ex, ey, visual, markerSize, showArrow, useLineArrow, arrowLength);
+			double markerSize, boolean showArrow, boolean useLineArrow, double arrowLength,
+			LineLinkGraph lineLinkGraph) {
+		this(null, sx, sy, ex, ey, visual, markerSize, showArrow, useLineArrow, arrowLength,
+				lineLinkGraph);
 	}
 
 	/** Constructor. */
 	public LineSegment(Object bendPointModel, double sx, double sy, double ex, double ey,
 			LineLinkVisualBase visual, double feedbackSize, boolean showArrow, boolean useLineArrow,
-			double arrowLength) {
+			double arrowLength, LineLinkGraph lineLinkGraph) {
 		this.bendPointModel = bendPointModel;
 
 		this.visibleLine = new Line(sx, sy, ex, ey);
@@ -73,6 +89,9 @@
 		} else {
 			arrowWidget = null;
 		}
+
+		this.lineLinkGraph = lineLinkGraph;
+		this.visual = visual;
 	}
 
 	/** Returns the bend point model. */
@@ -85,6 +104,11 @@
 		return visibleLine;
 	}
 
+	/** Returns the visible lines. */
+	public List<Line> getVisibleLines() {
+		return visibleLines;
+	}
+
 	/** Returns the invisible, clickable line. */
 	public Line getClickableLine() {
 		return clickableLine;
@@ -95,44 +119,119 @@
 		return feedbackHandle;
 	}
 
-	/** Updates the segment coordinates. */
-	public void update(double sx, double sy, double ex, double ey, double feedbackSize,
-			double arrowLength) {
-		visibleLine.setStartX(sx);
-		visibleLine.setStartY(sy);
-		visibleLine.setEndX(ex);
-		visibleLine.setEndY(ey);
-
-		clickableLine.setStartX(sx);
-		clickableLine.setStartY(sy);
-		clickableLine.setEndX(ex);
-		clickableLine.setEndY(ey);
-
-		double fs2 = feedbackSize / 2;
-		feedbackHandle.setX(ex - fs2);
-		feedbackHandle.setY(ey - fs2);
-		feedbackHandle.setWidth(feedbackSize);
-		feedbackHandle.setHeight(feedbackSize);
-
-		if(arrowWidget != null) {
-			arrowWidget.update(ex, ey, sx, sy, arrowLength);
-		}
-	}
-
 	/** Adds the link nodes of this segment to the link layer node. */
 	public void addLinkNodes(DiagramLayers layers, ILinkMVCBundle bundle) {
 		ILayer linkLayer = layers.getLinkLayer();
-		linkLayer.add(visibleLine, bundle);
+
+		computeVisibleLines();
+
+		for(Line line : visibleLines) {
+			linkLayer.add(line, bundle);
+		}
+		for(Arc bridge : bridges) {
+			linkLayer.add(bridge, bundle);
+		}
+
 		linkLayer.add(clickableLine, bundle);
 		if(arrowWidget != null) {
 			linkLayer.add(arrowWidget, bundle);
 		}
 	}
 
+	/** Computes the visible lines. If this line intersects with another, it will be interrupted. */
+	private void computeVisibleLines() {
+		visibleLines.add(visibleLine);
+
+		for(Line otherLine : lineLinkGraph.getLine2segment().keySet()) {
+			List<Line> newLines = new LinkedList<>();
+			if(visual.neighbors(this, lineLinkGraph.getLine2segment().get(otherLine))) {
+				continue;
+			}
+			for(Line thisLine : visibleLines) {
+				Point2D iPoint = intersection(thisLine, otherLine);
+				if(iPoint == null) {
+					newLines.add(thisLine);
+					continue;
+				}
+				double bridgeRadius = 4.0;
+
+				Point2D thisLineStartPoint =
+						new Point2D(thisLine.getStartX(), thisLine.getStartY());
+				Point2D thisLineEndPoint = new Point2D(thisLine.getEndX(), thisLine.getEndY());
+				Point2D anchorPointStart = anchorPoint(iPoint, thisLineStartPoint, bridgeRadius);
+				Point2D anchorPointEnd = anchorPoint(iPoint, thisLineEndPoint, bridgeRadius);
+
+				Line newLineStart = new Line(), newLineEnd = new Line();
+				if(iPoint.distance(thisLineStartPoint) > bridgeRadius) {
+					newLineStart = new Line(thisLine.getStartX(), thisLine.getStartY(),
+							anchorPointStart.getX(), anchorPointStart.getY());
+					newLines.add(newLineStart);
+				}
+				if(iPoint.distance(thisLineEndPoint) > bridgeRadius) {
+					newLineEnd = new Line(anchorPointEnd.getX(), anchorPointEnd.getY(),
+							thisLine.getEndX(), thisLine.getEndY());
+					newLines.add(newLineEnd);
+				}
+				// add bridge over the interruption
+				double angle = Math.atan2(thisLine.getStartX() - iPoint.getX(),
+						thisLine.getStartY() - iPoint.getY()) / Math.PI * 180.0 + 90.0;
+				Arc bridge = new Arc(iPoint.getX(), iPoint.getY(), bridgeRadius, bridgeRadius,
+						angle, 180.0);
+				bridge.setFill(TRANSPARENT);
+				bridge.setStroke(Color.BLACK);
+				bridges.add(bridge);
+			}
+			visibleLines = newLines;
+		}
+
+		lineLinkGraph.addSegment(this, visibleLines);
+	}
+
+	/** Computes the anchorPoint for the interrupted line, given a radius to the intersection. */
+	private Point2D anchorPoint(Point2D iPoint, Point2D direction, double radius) {
+		double angle =
+				Math.atan2(direction.getX() - iPoint.getX(), direction.getY() - iPoint.getY());
+		double x = iPoint.getX() + Math.sin(angle) * radius;
+		double y = iPoint.getY() + Math.cos(angle) * radius;
+		return new Point2D(x, y);
+	}
+
+	/** Computes the intersection point of two lines. */
+	private Point2D intersection(Line line1, Line line2) {
+		double x1 = line1.getStartX();
+		double x2 = line1.getEndX();
+		double x3 = line2.getStartX();
+		double x4 = line2.getEndX();
+		double y1 = line1.getStartY();
+		double y2 = line1.getEndY();
+		double y3 = line2.getStartY();
+		double y4 = line2.getEndY();
+		double d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
+		// lines parallel?
+		if(d == 0)
+			return null;
+		double xi = ((x3 - x4) * (x1 * y2 - y1 * x2) - (x1 - x2) * (x3 * y4 - y3 * x4)) / d;
+		double yi = ((y3 - y4) * (x1 * y2 - y1 * x2) - (y1 - y2) * (x3 * y4 - y3 * x4)) / d;
+		// intersection point in bounds?
+		if(!line1.contains(xi, yi) || !line2.contains(xi, yi))
+			return null;
+		return new Point2D(xi, yi);
+	}
+
 	/** Removes the link nodes of this segment from the link layer node. */
 	public void removeLinkNodes(DiagramLayers layers) {
 		ILayer linkLayer = layers.getLinkLayer();
-		linkLayer.remove(visibleLine);
+
+		lineLinkGraph.removeSegment(this, visibleLines);
+
+		for(Line line : visibleLines) {
+			linkLayer.remove(line);
+		}
+
+		for(Arc bridge : bridges) {
+			linkLayer.remove(bridge);
+		}
+
 		linkLayer.remove(clickableLine);
 		if(arrowWidget != null) {
 			linkLayer.remove(arrowWidget);
@@ -148,4 +247,14 @@
 	public void removeFeedbackNodes(DiagramLayers layers) {
 		layers.getLinkInteractionLayer().remove(feedbackHandle);
 	}
+
+	/** Sets the color of the visibleLines. */
+	public void setStrokeColor(Paint color) {
+		for(Line line : visibleLines) {
+			line.setStroke(color);
+		}
+		for(Arc bridge : bridges) {
+			bridge.setStroke(color);
+		}
+	}
 }