static void SetConnectorSrcDestConnectionPoints(Connector connector, ConnectionPoint srcConnectionPoint, ConnectionPoint destConnectionPoint) { FreeFormPanel.SetSourceConnectionPoint(connector, srcConnectionPoint); FreeFormPanel.SetDestinationConnectionPoint(connector, destConnectionPoint); srcConnectionPoint.AttachedConnectors.Add(connector); destConnectionPoint.AttachedConnectors.Add(connector); }
protected void DrawConnectionPoint(ConnectionPoint connPoint, Point actualLocation, DrawingContext drawingContext) { if (connPoint.IsEnabled) { // actualLocation is the point on the Edge with respect to the coordinate system defined by the top left corner of the adorned element // We will need this transparent rectangle to make sure OnMouseOver event can be triggered, for hit test. drawingContext.DrawRectangle(Brushes.Transparent, new Pen(Brushes.Transparent, 0), new Rect(actualLocation + connPoint.HitTestOffset, connPoint.HitTestSize)); drawingContext.DrawRectangle(this.renderBrush, this.renderPen, new Rect(actualLocation + connPoint.DrawingOffset, connPoint.DrawingSize)); } }
internal static ConnectionPoint ConnectionPointHitTest(Point hitPoint, List <ConnectionPoint> connectionPoints, FreeFormPanel panel) { ConnectionPoint hitConnectionPoint = null; FreeFormPanel outmost = panel.GetOutmostPanel(); foreach (ConnectionPoint connPoint in connectionPoints) { if (connPoint != null && connPoint.IsEnabled) { if (new Rect(panel.TranslatePoint(connPoint.Location, outmost) + connPoint.HitTestOffset, connPoint.HitTestSize).Contains(hitPoint)) { hitConnectionPoint = connPoint; break; } } } return(hitConnectionPoint); }
public static ConnectionPoint GetClosestConnectionPoint(List <ConnectionPoint> connectionPoints, Point refPoint, out double minDist) { minDist = double.PositiveInfinity; if (connectionPoints == null || connectionPoints.Count == 0) { return(null); } double dist = 0; ConnectionPoint closestPoint = null; foreach (ConnectionPoint point in connectionPoints) { dist = DesignerGeometryHelper.DistanceBetweenPoints(refPoint, point.Location); if (dist < minDist) { minDist = dist; closestPoint = point; } } return(closestPoint); }
void ConnectionPoint_MouseDown(object sender, MouseButtonEventArgs e) { UIElement srcElement = ((Adorner)sender).AdornedElement as UIElement; this.srcConnectionPoint = ConnectionPointHitTest(srcElement, e.GetPosition(this.panel)); e.Handled = true; }
private void OnFlowchartGridMouseUp(object sender, MouseButtonEventArgs e) { if (this.srcConnectionPoint != null) { RemoveAdorner(this.panel, typeof(ConnectorCreationAdorner)); this.srcConnectionPoint = null; } }
private ConnectionPoint GetSourceConnectionPointForAutoSplit(ConnectionPoint destConnPoint, UIElement srcDesigner) { this.MeasureView(srcDesigner); ConnectionPoint point = this.GetEmptyEdgeMidConnectionPointNotOfType(srcDesigner, this.exitEdgeForAutoSplit, ConnectionPointKind.Incoming); if (point == null) { point = this.FindClosestConnectionPointNotOfType(destConnPoint, new List<ConnectionPoint>(FlowchartDesigner.GetConnectionPoints(srcDesigner).Where<ConnectionPoint>(p => { return p.AttachedConnectors.Count == 0; })), ConnectionPointKind.Incoming); } return point; }
public void DoAutoConnect(DragEventArgs e, UIElement targetElement, AutoConnectDirections direction) { UIElement sourceElement = targetElement; bool immediatelyCommit = ModelItemHelper.CanCreateImmediateEditingScope(this.ModelItem); using (EditingScope scope = (EditingScope)this.ModelItem.BeginEdit(SR.AutoConnect, immediatelyCommit)) { ModelItem droppedModelItem = this.DoFlowchartGridDrop(e, direction, null); bool autoConnected = false; if (droppedModelItem != null) { ModelItem sourceModelItem = this.GetSourceModelItemForAutoConnect(sourceElement); if (sourceModelItem != null) { if (sourceModelItem.ItemType == typeof(FlowStep)) { sourceModelItem.Properties["Next"].SetValue(droppedModelItem); autoConnected = true; } else if (sourceModelItem.ItemType == typeof(FlowDecision)) { if (direction == AutoConnectDirections.Left) { sourceModelItem.Properties["True"].SetValue(droppedModelItem); autoConnected = true; } else if (direction == AutoConnectDirections.Right) { sourceModelItem.Properties["False"].SetValue(droppedModelItem); autoConnected = true; } } else if (GenericFlowSwitchHelper.IsGenericFlowSwitch(sourceModelItem.ItemType)) { string message = string.Empty; autoConnected = this.CreateFlowSwitchLink(this.srcConnectionPointForAutoConnect, sourceModelItem, droppedModelItem, null, null, ref message); } else if (sourceModelItem.ItemType == typeof(StartNode)) { this.ModelItem.Properties["StartNode"].SetValue(droppedModelItem); autoConnected = true; } } } if (autoConnected) { this.srcConnectionPointForAutoConnect = this.GetSourceConnectionPointForAutoConnect(sourceElement, AutoConnectHelper.AutoConnectDirection2EdgeLocation(direction)); scope.Complete(); } else { scope.Revert(); } } }
private void OnFlowchartGridPreviewMouseUp(object sender, MouseButtonEventArgs e) { if (this.srcConnectionPoint != null) { UIElement destElement = VisualTreeUtils.FindVisualAncestor<VirtualizedContainerService.VirtualizingContainer>(e.OriginalSource as DependencyObject); if (destElement != null && this.panel.Children.Contains(destElement)) { string errorMessage = string.Empty; Point mouseUpLocation = e.GetPosition(sender as IInputElement); if (!CreateLinkGesture(this.srcConnectionPoint, destElement, mouseUpLocation, out errorMessage, false, null) && !errorMessage.Equals(string.Empty)) { ErrorReporting.ShowErrorMessage(errorMessage); } this.srcConnectionPoint = null; RemoveAdorner(this.panel, typeof(ConnectorCreationAdorner)); RemoveAdorner(destElement, typeof(FlowchartConnectionPointsAdorner)); // Simulate a MouseEnter to show connection points ChildElement_MouseEnter(destElement, null); } } }
void StoreConnectorViewState(ModelItem linkModelItem, PointCollection viewState, ConnectionPoint srcConnPoint) { StoreConnectorViewState(linkModelItem, viewState, srcConnPoint, true); }
static internal ConnectionPoint GetClosestConnectionPoint(ConnectionPoint srcConnPoint, List<ConnectionPoint> destConnPoints, out double minDist) { minDist = double.PositiveInfinity; double dist = 0; ConnectionPoint closestPoint = null; Point srcPoint = FreeFormPanel.GetLocationRelativeToOutmostPanel(srcConnPoint); foreach (ConnectionPoint destConnPoint in destConnPoints) { if (srcConnPoint != destConnPoint) { dist = DesignerGeometryHelper.ManhattanDistanceBetweenPoints(srcPoint, FreeFormPanel.GetLocationRelativeToOutmostPanel(destConnPoint)); if (dist < minDist) { minDist = dist; closestPoint = destConnPoint; } } } return closestPoint; }
// Create a connector by view state of the connector model item, and if failed, just create a connector using the connection points // of the source and destination designers. Then add the connector created to the free form panel. void AddConnector( UIElement sourceDesigner, UIElement destinationDesigner, ModelItem connectorModelItem, ConnectionPoint sourceConnectionPoint = null, ConnectionPoint destinationConnectionPoint = null) { // Check whether connector already exists. // If users programmatically add state with transition to the stateMachine, AddConnector will be called twice for one connectorModelItem. if (GetConnectorInStateMachine(connectorModelItem) != null) { return; } Connector connector = CreateConnectorByConnectorModelItemViewState(sourceDesigner, destinationDesigner, connectorModelItem); if (connector == null) { PointCollection connectorPoints = this.CreatePointCollectionForAutoConnectOrAutoSplit(sourceDesigner, destinationDesigner, connectorModelItem, ref sourceConnectionPoint, ref destinationConnectionPoint); if (connectorPoints != null) { connector = CreateConnector(sourceConnectionPoint, destinationConnectionPoint, connectorPoints, connectorModelItem); this.ViewStateService.StoreViewState(connectorModelItem, ConnectorLocationViewStateKey, connectorPoints); } } if (connector != null) { this.panel.Children.Add(connector); } }
static public Point GetLocationRelativeToOutmostPanel(ConnectionPoint connectionPoint) { return(connectionPoint.Location); }
static public List <Point> GetEdgeRelativeToOutmostPanel(ConnectionPoint connectionPoint) { return(connectionPoint.Edge); }
public static void SetSourceConnectionPoint(DependencyObject obj, ConnectionPoint connectionPoint) { obj.SetValue(FreeFormPanel.SourceConnectionPointProperty, connectionPoint); }
void UpdateFlowchartOnLinkVisualMoved(ConnectionPoint knownConnectionPoint, Point newPoint, Connector movedConnector, bool isSourceKnown) { Fx.Assert(this.panel != null, "This code should not be hit if panel is null"); HitTestResult hitTestResult = VisualTreeHelper.HitTest(this.panel, newPoint); if (hitTestResult == null) { return; } //Test if the last connectionPoint hit, is the new location for the connector. UIElement newViewElement = null; ConnectionPoint newConnectionPoint = null; //The case where the link is dropped on a connectionpoint. if (this.lastConnectionPointMouseUpElement != null) { newConnectionPoint = this.ConnectionPointHitTest(this.lastConnectionPointMouseUpElement, newPoint); if (newConnectionPoint != null) { newViewElement = this.lastConnectionPointMouseUpElement; } } //The case where the link is dropped on a shape. if (newViewElement == null) { newViewElement = VisualTreeUtils.FindVisualAncestor<StartSymbol>(hitTestResult.VisualHit); if (newViewElement == null) { newViewElement = VisualTreeUtils.FindVisualAncestor<VirtualizedContainerService.VirtualizingContainer>(hitTestResult.VisualHit); } } if (newViewElement != null) { if (this.panel.Children.Contains(newViewElement)) { using (EditingScope es = (EditingScope)this.ModelItem.BeginEdit(SR.FCLinkMove)) { //Delete the existing link and keep the caseKey IFlowSwitchLink oldCaseKey = this.DeleteLink(movedConnector, true); //Create new link bool linkCreated = false; string errorMessage = string.Empty; if (isSourceKnown) { if (newConnectionPoint == null) { linkCreated = CreateLinkGesture(knownConnectionPoint, newViewElement, newPoint, out errorMessage, true, oldCaseKey); } else { linkCreated = CreateLinkGesture(knownConnectionPoint, newConnectionPoint, out errorMessage, true, oldCaseKey); } } else { //If the Link source is dropped onto itself, we need to set the isLinkValidDueToLinkMove flag. bool isLinkValidDueToLinkMove = FreeFormPanel.GetSourceConnectionPoint(movedConnector).ParentDesigner.Equals(newViewElement); if (newConnectionPoint == null) { linkCreated = CreateLinkGesture(newViewElement, knownConnectionPoint, newPoint, out errorMessage, isLinkValidDueToLinkMove, oldCaseKey); } else { linkCreated = CreateLinkGesture(newConnectionPoint, knownConnectionPoint, out errorMessage, isLinkValidDueToLinkMove, oldCaseKey); } } if (!linkCreated) { if (!errorMessage.Equals(string.Empty)) { ErrorReporting.ShowErrorMessage(errorMessage); } es.Revert(); } else { es.Complete(); } } } } }
void SetConnectorLabel(Connector connector, ConnectionPoint srcConnPoint, ModelItem linkModelItem) { BindingBase labelBinding = null; if (typeof(FlowDecision).IsAssignableFrom(linkModelItem.ItemType)) { if (FlowchartDesigner.GetTrueConnectionPoint(srcConnPoint.ParentDesigner).Equals(srcConnPoint)) { labelBinding = new Binding { Source = linkModelItem, Path = new PropertyPath("TrueLabel") }; } else { labelBinding = new Binding { Source = linkModelItem, Path = new PropertyPath("FalseLabel") }; } SetConnectorLabelToolTip(connector, labelBinding); } else if (typeof(IFlowSwitchLink).IsAssignableFrom(linkModelItem.ItemType)) { IFlowSwitchLink flowSwitchLink = (IFlowSwitchLink)linkModelItem.GetCurrentValue(); labelBinding = flowSwitchLink.CreateConnectorLabelTextBinding(); SetConnectorLabelToolTip(connector, labelBinding); } }
static ConnectionPoint GetClosestConnectionPointNotOfType(ConnectionPoint srcConnectionPoint, List<ConnectionPoint> targetConnectionPoints, ConnectionPointKind illegalConnectionPointKind) { double minDist; List<ConnectionPoint> filteredConnectionPoints = new List<ConnectionPoint>(); foreach (ConnectionPoint connPoint in targetConnectionPoints) { if (connPoint.PointType != illegalConnectionPointKind && !connPoint.Equals(srcConnectionPoint) && connPoint.AttachedConnectors.Count == 0) { filteredConnectionPoints.Add(connPoint); } } return GetClosestConnectionPoint(srcConnectionPoint, filteredConnectionPoints, out minDist); }
//Save the connector.Points property on the CFx object for serialization and viewstate maintenance. void StoreConnectorViewState(ModelItem linkModelItem, PointCollection viewState, ConnectionPoint srcConnPoint, bool isUndoableViewState) { ModelItem storageModelItem = GetConnectorViewStateStorageModelItem(linkModelItem); string viewStateKey = GetConnectorViewStateKey(linkModelItem, srcConnPoint); StoreConnectorViewState(storageModelItem, viewStateKey, viewState, isUndoableViewState); }
static void GetClosestConnectionPointPair(List<ConnectionPoint> srcConnPoints, List<ConnectionPoint> destConnPoints, out ConnectionPoint srcConnPoint, out ConnectionPoint destConnPoint) { double minDist = double.PositiveInfinity; double dist; ConnectionPoint tempConnPoint; srcConnPoint = null; destConnPoint = null; foreach (ConnectionPoint connPoint in srcConnPoints) { tempConnPoint = GetClosestConnectionPoint(connPoint, destConnPoints, out dist); if (dist < minDist) { minDist = dist; srcConnPoint = connPoint; destConnPoint = tempConnPoint; } } Fx.Assert(srcConnPoint != null, "No ConnectionPoint found"); Fx.Assert(destConnPoint != null, "No ConnectionPoint found"); }
string GetConnectorViewStateKey(ModelItem linkModelItem, ConnectionPoint srcConnPoint) { string viewStateKey = ConnectorViewStateKey; if ((typeof(FlowDecision).IsAssignableFrom(linkModelItem.ItemType))) { if (srcConnPoint.Equals(FlowchartDesigner.GetTrueConnectionPoint(this.modelElement[linkModelItem]))) { viewStateKey = TrueConnectorViewStateKey; } else { viewStateKey = FalseConnectorViewStateKey; } } else if (typeof(IFlowSwitchLink).IsAssignableFrom(linkModelItem.ItemType)) { IFlowSwitchLink link = (IFlowSwitchLink)linkModelItem.GetCurrentValue(); if (link.IsDefaultCase) { viewStateKey = FlowSwitchDefaultViewStateKey; } else { viewStateKey = link.CaseName + CaseViewStateKeyAppendString; } } return viewStateKey; }
static void GetEmptySrcDestConnectionPoints(UIElement source, UIElement dest, out ConnectionPoint srcConnPoint, out ConnectionPoint destConnPoint) { srcConnPoint = null; destConnPoint = null; List<ConnectionPoint> srcConnectionPoints = GetEmptyConnectionPoints(source); List<ConnectionPoint> destConnectionPoints = GetEmptyConnectionPoints(dest); if (srcConnectionPoints.Count > 0 && destConnectionPoints.Count > 0) { GetClosestConnectionPointPair(srcConnectionPoints, destConnectionPoints, out srcConnPoint, out destConnPoint); } }
internal static ConnectionPoint GetDestinationConnectionPointForAutoConnect(UIElement dest, ConnectionPoint srcConnPoint) { EdgeLocation destEdgeLocation = EdgeLocation.Top; if (!((dest is VirtualizedContainerService.VirtualizingContainer) && ((VirtualizedContainerService.VirtualizingContainer)dest).ModelItem.ItemType == typeof(FlowDecision))) { switch (srcConnPoint.EdgeLocation) { case EdgeLocation.Top: destEdgeLocation = EdgeLocation.Bottom; break; case EdgeLocation.Bottom: destEdgeLocation = EdgeLocation.Top; break; case EdgeLocation.Left: destEdgeLocation = EdgeLocation.Right; break; case EdgeLocation.Right: destEdgeLocation = EdgeLocation.Left; break; } } List<ConnectionPoint> destConnectionPoints = new List<ConnectionPoint>(FlowchartDesigner.GetConnectionPoints(dest).Where<ConnectionPoint>((p) => { return p.PointType != ConnectionPointKind.Outgoing && p.EdgeLocation == destEdgeLocation; })); Fx.Assert(destConnectionPoints.Count > 0, "There should be at least one dest connection point available"); return FlowchartDesigner.GetConnectionPointForAutoConnect(destConnectionPoints); }
//This returns the closest non-incoming connectionPoint on source. Return value will be different than destConnectionPoint. static ConnectionPoint GetClosestSrcConnectionPoint(UIElement src, ConnectionPoint destConnectionPoint) { ConnectionPoint srcConnectionPoint = null; if (destConnectionPoint.PointType != ConnectionPointKind.Outgoing) { srcConnectionPoint = GetClosestConnectionPointNotOfType(destConnectionPoint, StateContainerEditor.GetConnectionPoints(src), ConnectionPointKind.Incoming); } return srcConnectionPoint; }
internal static int GetConnectionPointIndex(UIElement element, ConnectionPoint pnt) { List<ConnectionPoint> list = FlowchartDesigner.GetAllConnectionPoints(element); return list.IndexOf(pnt); }
//This returns the closest non-outgoing connectionPoint on dest. Return value will be different than sourceConnectionPoint. static ConnectionPoint GetClosestDestConnectionPoint(ConnectionPoint sourceConnectionPoint, UIElement dest) { ConnectionPoint destConnectionPoint = null; if (sourceConnectionPoint.PointType != ConnectionPointKind.Incoming) { destConnectionPoint = GetClosestConnectionPointNotOfType(sourceConnectionPoint, StateContainerEditor.GetConnectionPoints(dest), ConnectionPointKind.Outgoing); } return destConnectionPoint; }
private void OnFlowchartGridMouseLeave(object sender, MouseEventArgs e) { bool endLinkCreation = !IsVisualHit(sender as UIElement, sender as UIElement, e.GetPosition(sender as IInputElement)); if (endLinkCreation) { RemoveAdorner(this.panel, typeof(ConnectorCreationAdorner)); this.srcConnectionPoint = null; } }
//widthFraction, heightFraction determine location of connectionpoint on the shape. ConnectionPoint CreateConnectionPoint(UIElement element, double widthFraction, double heightFraction, EdgeLocation location) { ConnectionPoint connectionPoint = new ConnectionPoint(); connectionPoint.EdgeLocation = location; connectionPoint.PointType = ConnectionPointKind.Default; connectionPoint.ParentDesigner = element; BindingOperations.SetBinding(connectionPoint, ConnectionPoint.LocationProperty, GetConnectionPointBinding(element as FrameworkElement, widthFraction, heightFraction)); return connectionPoint; }
static void SetTrueConnectionPoint(DependencyObject obj, ConnectionPoint connectionPoint) { obj.SetValue(FlowchartDesigner.TrueConnectionPointProperty, connectionPoint); }
void GetSrcDestConnectionPoints(UIElement source, UIElement dest, out ConnectionPoint srcConnPoint, out ConnectionPoint destConnPoint, out string errorMessage) { srcConnPoint = null; destConnPoint = null; errorMessage = string.Empty; VirtualizedContainerService.VirtualizingContainer sourceContainer = source as VirtualizedContainerService.VirtualizingContainer; if (sourceContainer != null && typeof(FlowDecision).IsAssignableFrom(sourceContainer.ModelItem.ItemType)) { srcConnPoint = FindFlowDecisionSrcConnectionPoint(source, out errorMessage); if (srcConnPoint != null) { destConnPoint = FindBestMatchDestConnectionPoint(srcConnPoint, dest, out errorMessage); } } else { List<ConnectionPoint> srcConnectionPoints = FlowchartDesigner.GetConnectionPoints(source); List<ConnectionPoint> destConnectionPoints = FlowchartDesigner.GetConnectionPoints(dest); if (sourceContainer != null && GenericFlowSwitchHelper.IsGenericFlowSwitch(sourceContainer.ModelItem.ItemType)) { FindBestMatchConnectionPointPair(srcConnectionPoints, destConnectionPoints, out srcConnPoint, out destConnPoint); } else { // Flowstep FindBestMatchConnectionPointPair(srcConnectionPoints, destConnectionPoints, out srcConnPoint, out destConnPoint); } } }
void ConnectionPoint_MouseUp(object sender, MouseButtonEventArgs e) { Fx.Assert(this.panel != null, "This code should not be hit if panel is null"); UIElement dest = ((Adorner)sender).AdornedElement as UIElement; Fx.Assert(dest != null, "Adorned element is not a UIElement"); if (this.srcConnectionPoint != null) { ConnectionPoint destConnectionPoint = ConnectionPointHitTest(dest, e.GetPosition(this.panel)); if (destConnectionPoint != null && !this.srcConnectionPoint.Equals(destConnectionPoint)) { string errorMessage = string.Empty; if (!CreateLinkGesture(this.srcConnectionPoint, destConnectionPoint, out errorMessage, null) && !errorMessage.Equals(string.Empty)) { ErrorReporting.ShowErrorMessage(errorMessage); } } this.srcConnectionPoint = null; RemoveAdorner(this.panel, typeof(ConnectorCreationAdorner)); RemoveAdorner(dest, typeof(FlowchartConnectionPointsAdorner)); } else { //This will cause the FreeFormPanel to handle the event and is useful while moving connection end points of a connector. lastConnectionPointMouseUpElement = dest; dest.RaiseEvent(e); } }
//This returns the closest non-outgoing connectionPoint on dest. Return value will be different than sourceConnectionPoint. ConnectionPoint ClosestDestConnectionPoint(ConnectionPoint sourceConnectionPoint, UIElement dest, out string errorMessage) { ConnectionPoint destConnectionPoint = null; errorMessage = string.Empty; if (sourceConnectionPoint.PointType != ConnectionPointKind.Incoming) { destConnectionPoint = FindClosestConnectionPointNotOfType(sourceConnectionPoint, FlowchartDesigner.GetConnectionPoints(dest), ConnectionPointKind.Outgoing); } else { errorMessage = SR.FCInvalidLink; } return destConnectionPoint; }
Connector GetConnector(ModelItem linkModelItem, ConnectionPoint srcConnPoint, ConnectionPoint destConnPoint) { Fx.Assert(this.panel != null, "This code should not be hit if panel is null"); ConnectorWithoutStartDot connector = new ConnectorWithoutStartDot(); connector.FocusVisualStyle = null; connector.Focusable = true; DesignerView.SetCommandMenuMode(connector, CommandMenuMode.NoCommandMenu); SetConnectorLabel(connector, srcConnPoint, linkModelItem); connector.GotKeyboardFocus += new KeyboardFocusChangedEventHandler(OnConnectorGotKeyboardFocus); connector.RequestBringIntoView += new RequestBringIntoViewEventHandler(OnConnectorRequestBringIntoView); connector.MouseDown += new MouseButtonEventHandler(OnConnectorMouseDown); connector.GotFocus += new RoutedEventHandler(OnConnectorGotFocus); SetConnectorSrcDestConnectionPoints(connector, srcConnPoint, destConnPoint); FlowchartDesigner.SetLinkModelItem(connector, linkModelItem); connector.Unloaded += new RoutedEventHandler(OnConnectorUnloaded); connector.AutoSplitContainer = this; return connector; }
//This returns the closest non-Incoming connectionPoint on source. Return value will be different than destConnectionPoint. ConnectionPoint ClosestSrcConnectionPoint(UIElement src, ConnectionPoint destConnectionPoint, out string errorMessage) { ConnectionPoint sourceConnectionPoint = null; errorMessage = string.Empty; if (destConnectionPoint.PointType != ConnectionPointKind.Outgoing) { VirtualizedContainerService.VirtualizingContainer srcContainer = src as VirtualizedContainerService.VirtualizingContainer; if (srcContainer != null && typeof(FlowDecision).IsAssignableFrom(srcContainer.ModelItem.ItemType)) { sourceConnectionPoint = FindFlowDecisionSrcConnectionPoint(src, out errorMessage); } else { sourceConnectionPoint = FindClosestConnectionPointNotOfType(destConnectionPoint, FlowchartDesigner.GetConnectionPoints(src), ConnectionPointKind.Incoming); } } else { errorMessage = SR.FCInvalidLink; } return sourceConnectionPoint; }
//Returns a new connector if viewstate exists, null otherwise. Connector GetConnectorViewState(UIElement source, UIElement dest, ModelItem linkModelItem, ConnectionPoint sourceConnectionPoint) { Fx.Assert(this.panel != null, "This code should not be hit if panel is null"); Connector connector = null; object connectorLocation = null; if (typeof(FlowDecision).IsAssignableFrom(linkModelItem.ItemType)) { Fx.Assert(sourceConnectionPoint != null, "Source connection point is null."); if (sourceConnectionPoint.Equals(FlowchartDesigner.GetTrueConnectionPoint(this.modelElement[linkModelItem]))) { connectorLocation = this.ViewStateService.RetrieveViewState(linkModelItem, TrueConnectorViewStateKey); } else { connectorLocation = this.ViewStateService.RetrieveViewState(linkModelItem, FalseConnectorViewStateKey); } } else if (typeof(IFlowSwitchLink).IsAssignableFrom(linkModelItem.ItemType)) { string key = null; IFlowSwitchLink link = (IFlowSwitchLink)linkModelItem.GetCurrentValue(); if (link.IsDefaultCase) { key = FlowSwitchDefaultViewStateKey; } else { key = link.CaseName + CaseViewStateKeyAppendString; } //Transitioning from fake ModelItem world to real ModelItem world. ModelItem realFSModelItem = (this.ModelItem as IModelTreeItem).ModelTreeManager.WrapAsModelItem(link.ParentFlowSwitch); connectorLocation = this.ViewStateService.RetrieveViewState(realFSModelItem, key); } else { connectorLocation = this.ViewStateService.RetrieveViewState(linkModelItem, ConnectorViewStateKey); } PointCollection locationPts = connectorLocation as PointCollection; if (locationPts != null) { ConnectionPoint srcConnPoint, destConnPoint; System.Diagnostics.Debug.WriteLine(this.isLoaded ? "About to call ConnectionPointHitTest - Loaded" : "About to call ConnectionPointHitTest - Not Loaded"); srcConnPoint = ConnectionPointHitTest(source, locationPts[0]); destConnPoint = ConnectionPointHitTest(dest, locationPts[locationPts.Count - 1]); //In Debug mode, the size of the designer changes due to the debug adorner(border). Because of this connection points will move and //won't coincide with the viewstate. //The following code path is added for the scenario where we reload the flowchart designer by navigating back and forth on breadcrumb //when one of the flowchart activities has the debug border. //In this scenario we try to find the closest connection point from the end point stored in viewstate. If the distance between the two //is within the acceptable range, we will reuse the viewstate and avoid re-drawing the connector. if (this.IsReadOnly) { ConnectionPoint pt; double dist; if (srcConnPoint == null) { pt = FindClosestConnectionPoint(locationPts[0], FlowchartDesigner.GetConnectionPoints(source), out dist); if (pt != null && pt.PointType != ConnectionPointKind.Incoming && dist <= DebugTimeMaxConnectorShapeDist) { srcConnPoint = pt; } } if (destConnPoint == null) { pt = FindClosestConnectionPoint(locationPts[locationPts.Count - 1], FlowchartDesigner.GetConnectionPoints(dest), out dist); if (pt != null && pt.PointType != ConnectionPointKind.Outgoing && dist <= DebugTimeMaxConnectorShapeDist) { destConnPoint = pt; } } } if (srcConnPoint != null && destConnPoint != null) { connector = GetConnector(linkModelItem, srcConnPoint, destConnPoint); connector.Points = locationPts; } } return connector; }
void UpdateEditPoints(Point newPoint) { if (this.editPoints.Count < 2 || this.editPoints[0].Type != EditPoint.EditPointTypes.ConnectionEditPoint || this.editPoints[this.editPoints.Count - 1].Type != EditPoint.EditPointTypes.ConnectionEditPoint) { Fx.Assert(false, "EditPoints are invalid"); return; } if (this.activeEditPoint != null) { int activeEditPointIndex = this.editPoints.IndexOf(this.activeEditPoint); EditPoint previous = (activeEditPointIndex > 0) ? this.editPoints[activeEditPointIndex - 1] : null; EditPoint next = (activeEditPointIndex < this.editPoints.Count - 1) ? this.editPoints[activeEditPointIndex + 1] : null; //Note that extra edit points are only added if we are connected to connection point if (previous != null && previous.Type == EditPoint.EditPointTypes.ConnectionEditPoint) { double slopeOfLine = DesignerGeometryHelper.SlopeOfLineSegment(previous.Location, this.activeEditPoint.Location); Orientation orientation = (Math.Abs(slopeOfLine) < 1) ? Orientation.Horizontal : Orientation.Vertical; int editPointOffset = Convert.ToInt32(DesignerGeometryHelper.DistanceBetweenPoints(previous.Location, (next != null) ? next.Location : this.activeEditPoint.Location)) / 4; if (orientation == Orientation.Horizontal) { editPointOffset *= (previous.Location.X < this.activeEditPoint.Location.X) ? 1 : -1; } else { editPointOffset *= (previous.Location.Y < this.activeEditPoint.Location.Y) ? 1 : -1; } activeEditPointIndex = this.editPoints.IndexOf(this.activeEditPoint); Point editPointLocation = (orientation == Orientation.Horizontal) ? new Point(previous.Location.X + editPointOffset, previous.Location.Y) : new Point(previous.Location.X, previous.Location.Y + editPointOffset); previous = new EditPoint(EditPoint.EditPointTypes.MultiSegmentEditPoint, editPointLocation); this.editPoints.InsertRange(activeEditPointIndex, new EditPoint[] { new EditPoint(EditPoint.EditPointTypes.MultiSegmentEditPoint, editPointLocation), previous }); } if (next != null && next.Type == EditPoint.EditPointTypes.ConnectionEditPoint) { double slopeOfLine = DesignerGeometryHelper.SlopeOfLineSegment(this.activeEditPoint.Location, next.Location); Orientation orientation = (Math.Abs(slopeOfLine) < 1) ? Orientation.Horizontal : Orientation.Vertical; int editPointOffset = Convert.ToInt32(DesignerGeometryHelper.DistanceBetweenPoints((previous != null) ? previous.Location : this.activeEditPoint.Location, next.Location)) / 4; if (orientation == Orientation.Horizontal) { editPointOffset *= (this.activeEditPoint.Location.X < next.Location.X) ? -1 : 1; } else { editPointOffset *= (this.activeEditPoint.Location.Y < next.Location.Y) ? -1 : 1; } activeEditPointIndex = this.editPoints.IndexOf(this.activeEditPoint); Point editPointLocation = (orientation == Orientation.Horizontal) ? new Point(next.Location.X + editPointOffset, next.Location.Y) : new Point(next.Location.X, next.Location.Y + editPointOffset); next = new EditPoint(EditPoint.EditPointTypes.MultiSegmentEditPoint, editPointLocation); this.editPoints.InsertRange(activeEditPointIndex + 1, new EditPoint[] { next, new EditPoint(EditPoint.EditPointTypes.MultiSegmentEditPoint, editPointLocation) }); } if (this.activeEditPoint.Type == EditPoint.EditPointTypes.ConnectionEditPoint) { Fx.Assert(this.editPoints[0].Type == EditPoint.EditPointTypes.ConnectionEditPoint, "EditPoint type is wrong."); Fx.Assert(this.editPoints[editPoints.Count - 1].Type == EditPoint.EditPointTypes.ConnectionEditPoint, "EditPoint type is wrong."); this.activeEditPoint.Location = newPoint; Fx.Assert(this.editPoints.Count > 0, "Some edit point should exist"); ConnectionPoint targetConnPt = null; Point[] points = null; Point begin = this.editPoints[0].Location; Point end = this.editPoints[this.editPoints.Count - 1].Location; if (typeof(ConnectionPointsAdorner).IsAssignableFrom(Mouse.DirectlyOver.GetType())) { ConnectionPointsAdorner connPtsAdorner = Mouse.DirectlyOver as ConnectionPointsAdorner; targetConnPt = FreeFormPanel.ConnectionPointHitTest(newPoint, connPtsAdorner); } if (activeEditPointIndex == 0) { // We are dragging the source point of a connector. ConnectionPoint destConnPt = FreeFormPanel.GetDestinationConnectionPoint(this.editedConnector); if (targetConnPt != null) { points = ConnectorRouter.Route(parentPanel, targetConnPt, destConnPt); this.activeEditPoint.Location = targetConnPt.Location; } else { points = ConnectorRouter.Route(parentPanel, begin, destConnPt); } } else { // We are dragging the destination point of a connector. ConnectionPoint srcConnPt = FreeFormPanel.GetSourceConnectionPoint(this.editedConnector); if (targetConnPt != null) { points = ConnectorRouter.Route(parentPanel, srcConnPt, targetConnPt); this.activeEditPoint.Location = targetConnPt.Location; } else { points = ConnectorRouter.Route(parentPanel, srcConnPt, end); } } //When we start editing the end point we need to clear the slate and start over List <EditPoint> newEditPoints = new List <EditPoint>(); if (points != null && points.Length > 1) { RemoveEditPoints(EditPoint.EditPointTypes.MultiSegmentEditPoint); for (int i = 1; i < points.Length - 1; ++i) { newEditPoints.Add(new EditPoint(EditPoint.EditPointTypes.MultiSegmentEditPoint, points[i])); } this.editPoints.InsertRange(1, newEditPoints.ToArray()); } } else if (this.activeEditPoint.Type == EditPoint.EditPointTypes.MultiSegmentEditPoint) { if (previous != null && previous.Type != EditPoint.EditPointTypes.ConnectionEditPoint && next != null && next.Type != EditPoint.EditPointTypes.ConnectionEditPoint) { //Update the previous point double slopeOfLine = DesignerGeometryHelper.SlopeOfLineSegment(previous.Location, this.activeEditPoint.Location); Orientation orientation = (Math.Abs(slopeOfLine) < 1) ? Orientation.Horizontal : Orientation.Vertical; previous.Location = (orientation == Orientation.Horizontal) ? new Point(previous.Location.X, newPoint.Y) : new Point(newPoint.X, previous.Location.Y); //Update the next point slopeOfLine = DesignerGeometryHelper.SlopeOfLineSegment(this.activeEditPoint.Location, next.Location); orientation = (Math.Abs(slopeOfLine) < 1) ? Orientation.Horizontal : Orientation.Vertical; next.Location = (orientation == Orientation.Horizontal) ? new Point(next.Location.X, newPoint.Y) : new Point(newPoint.X, next.Location.Y); //Update the current point this.activeEditPoint.Location = newPoint; } else { Fx.Assert(false, "Should not be here. UpdateEditPoints failed."); } } } // Remove all the redundant edit points RemoveCoincidingEditPoints(); bool validEditPoints = ValidateEditPoints(); Fx.Assert(validEditPoints, "Validating EditPoints failed."); }