浏览代码

Bugfix: in some cases transitions were clipped away if scale factor != 100%

terfloth@itemis.de 13 年之前
父节点
当前提交
9dffb91a08

+ 114 - 2
plugins/org.yakindu.sct.ui.editor/src/org/yakindu/sct/ui/editor/editor/StatechartDiagramEditor.java

@@ -14,8 +14,16 @@ import org.eclipse.core.resources.IMarker;
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IProjectDescription;
 import org.eclipse.core.runtime.CoreException;
+import org.eclipse.draw2d.Connection;
+import org.eclipse.draw2d.ConnectionAnchor;
 import org.eclipse.draw2d.ConnectionLayer;
+import org.eclipse.draw2d.IFigure;
+import org.eclipse.draw2d.Viewport;
 import org.eclipse.draw2d.ViewportAwareConnectionLayerClippingStrategy;
+import org.eclipse.draw2d.ViewportUtilities;
+import org.eclipse.draw2d.geometry.Insets;
+import org.eclipse.draw2d.geometry.PointList;
+import org.eclipse.draw2d.geometry.Rectangle;
 import org.eclipse.emf.transaction.ResourceSetChangeEvent;
 import org.eclipse.emf.transaction.ResourceSetListener;
 import org.eclipse.emf.transaction.ResourceSetListenerImpl;
@@ -148,9 +156,113 @@ public class StatechartDiagramEditor extends DiagramDocumentEditor implements
 		if (rootEditPart instanceof LayerManager) {
 			ConnectionLayer connectionLayer = (ConnectionLayer) ((LayerManager) rootEditPart)
 					.getLayer(LayerConstants.CONNECTION_LAYER);
+//			connectionLayer
+//					.setClippingStrategy(new ViewportAwareConnectionLayerClippingStrategy(
+//							connectionLayer));
+
 			connectionLayer
-					.setClippingStrategy(new ViewportAwareConnectionLayerClippingStrategy(
-							connectionLayer));
+				.setClippingStrategy(new ViewportAwareConnectionLayerClippingStrategy(
+						connectionLayer){
+				
+				private final Insets PRIVATE_INSETS = new Insets(0, 0, 1, 1);
+				
+				/**
+				 * Computes clipping rectangle(s) for a given connection. Will consider all
+				 * enclosing viewports, excluding the root viewport.
+				 */
+				protected Rectangle[] getEdgeClippingRectangle(Connection connection) {
+					// start with clipping the connection at its original bounds
+					Rectangle clipRect = getAbsoluteBoundsAsCopy(connection);
+
+					// in case we cannot infer source and target of the connection (e.g.
+					// if XYAnchors are used), returning the bounds is all we can do
+					ConnectionAnchor sourceAnchor = connection.getSourceAnchor();
+					ConnectionAnchor targetAnchor = connection.getTargetAnchor();
+					if (sourceAnchor == null || sourceAnchor.getOwner() == null
+							|| targetAnchor == null || targetAnchor.getOwner() == null) {
+						return new Rectangle[] { clipRect };
+					}
+
+					// source and target figure are known, see if there is common
+					// viewport
+					// the connection has to be clipped at.
+					IFigure sourceFigure = sourceAnchor.getOwner();
+					IFigure targetFigure = targetAnchor.getOwner();
+					Viewport nearestEnclosingCommonViewport = ViewportUtilities
+							.getNearestCommonViewport(sourceFigure, targetFigure);
+					if (nearestEnclosingCommonViewport == null) {
+						return new Rectangle[] { clipRect };
+					}
+
+					// if the nearest common viewport is not the root viewport, we may
+					// start with clipping the connection at this viewport.
+					if (nearestEnclosingCommonViewport != getRootViewport()) {
+						clipRect.intersect(getNodeClippingRectangle(nearestEnclosingCommonViewport));
+					}
+
+					// if the nearest common viewport of source and target is not
+					// simultaneously
+					// the nearest enclosing viewport of source and target respectively, the
+					// connection has to be further clipped (the connection may even not be
+					// visible at all)
+					Viewport nearestEnclosingSourceViewport = ViewportUtilities
+							.getNearestEnclosingViewport(sourceFigure);
+					Viewport nearestEnclosingTargetViewport = ViewportUtilities
+							.getNearestEnclosingViewport(targetFigure);
+					if (nearestEnclosingSourceViewport != nearestEnclosingTargetViewport) {
+						// compute if source and target anchor are visible
+						// within the nearest common enclosing viewport (which may
+						// itself be nested in other viewports).
+						Rectangle sourceClipRect = getAbsoluteBoundsAsCopy(connection);
+						if (nearestEnclosingSourceViewport != nearestEnclosingCommonViewport) {
+							clipAtViewports(sourceClipRect,
+									ViewportUtilities.getViewportsPath(
+											nearestEnclosingSourceViewport,
+											nearestEnclosingCommonViewport, false));
+						}
+						Rectangle targetClipRect = getAbsoluteBoundsAsCopy(connection);
+						if (nearestEnclosingTargetViewport != nearestEnclosingCommonViewport) {
+							clipAtViewports(targetClipRect,
+									ViewportUtilities.getViewportsPath(
+											nearestEnclosingTargetViewport,
+											nearestEnclosingCommonViewport, false));
+						}
+						PointList absolutePointsAsCopy = getAbsolutePointsAsCopy(connection);
+						boolean sourceAnchorVisible = sourceClipRect.getExpanded(
+								PRIVATE_INSETS).contains(
+								absolutePointsAsCopy.getFirstPoint());
+						boolean targetAnchorVisible = targetClipRect.getExpanded(
+								PRIVATE_INSETS).contains(
+								absolutePointsAsCopy.getLastPoint());
+
+						if (!sourceAnchorVisible || !targetAnchorVisible) {
+							// one (or both) of source or target anchor is invisible
+							// within the nearest common viewport, so up to now
+							// we regard the edge as invisible.
+							return new Rectangle[] {};
+							// TODO: We could come up with a more decent strategy here,
+							// which also computes clipping fragments in those cases
+							// where source/target are not visible but the edge
+							// intersects with the enclosing source/target viewport's
+							// parents bounds.
+
+						} else {
+							// both ends are visible, so just return what we have
+							// computed before
+							// (clipping at nearest enclosing viewport)
+							return new Rectangle[] { clipRect };
+						}
+					} else {
+						// source and target share the same enclosing viewport, so just
+						// return what we have computed before (clipping at nearest
+						// enclosing viewport)
+						return new Rectangle[] { clipRect };
+					}
+				}
+				
+										
+			});
+
 		}
 	}