Point CalculateDropLocationForAutoConnect(AutoConnectDirections autoConnectDirection, Size droppedSize) { return AutoConnectHelper.CalculateDropLocation(droppedSize, this.panel.CurrentAutoConnectTarget, autoConnectDirection, this.shapeLocations); }
void PerformInternalMove(UIElement movedElement, Point newPoint, Point? shapeAnchorPoint, AutoConnectDirections autoConnectDirection, Connector connectorToSplit) { using (EditingScope es = (EditingScope)this.ModelItem.BeginEdit(SR.FCLinkMove)) { RemoveAdorner(movedElement, typeof(ConnectionPointsAdorner)); Point shapeLocation; Size size = FreeFormPanel.GetChildSize(movedElement); if (autoConnectDirection != AutoConnectDirections.None) { shapeLocation = this.CalculateDropLocationForAutoConnect(autoConnectDirection, size); } else if (shapeAnchorPoint.HasValue) { shapeLocation = SnapVisualToGrid(movedElement, newPoint, shapeAnchorPoint.Value, true); } else { Fx.Assert(newPoint.X.IsNoLessThan(0) && newPoint.Y.IsNoLessThan(0), "newPoint is negative"); shapeLocation = newPoint; } if (connectorToSplit != null) { shapeLocation = this.CalculateDropLocationForAutoSplit(newPoint, shapeLocation, connectorToSplit, size); } StoreShapeViewState(movedElement, shapeLocation); RerouteAttachedConnectors(movedElement); es.Complete(); } }
// Returns the last dropped item - used for auto-connect and auto-split where only one item is allowed ModelItem DoFlowchartGridDrop(DragEventArgs e, AutoConnectDirections autoConnectDirection, Connector connectorToSplit) { ModelItem droppedModelItem = null; ModelItem newFlowStepMI = null; e.Effects = DragDropEffects.None; IEnumerable<object> droppedObjects = DragDropHelper.GetDroppedObjects(this, e, Context); //Marking the event as being handled. In whichever case we want to route the event, it will be unmarked explicitly. e.Handled = true; List<WorkflowViewElement> movedViewElements = new List<WorkflowViewElement>(); ShapeOffsetter shapeOffsetter = new ShapeOffsetter(); Dictionary<WorkflowViewElement, Point> relativeLocations = DragDropHelper.GetDraggedViewElementRelativeLocations(e); ModelItem modelItemDroppedFromToolBox = null; Dictionary<object, FlowNode> objToNewFlowNodeMap = null; Dictionary<FlowNode, ModelItem> flowNodeModelItemMap = null; Dictionary<FlowNode, FlowNode> oldNewFlowNodeMap = null; this.PrepareForDrop(droppedObjects, out objToNewFlowNodeMap, out flowNodeModelItemMap, out oldNewFlowNodeMap); bool shouldStoreCurrentSizeViewState = true; foreach (object droppedObject in droppedObjects) { if (droppedObject == null) { continue; } droppedModelItem = droppedObject as ModelItem; // archor point Point anchorPoint = DragDropHelper.GetDragDropAnchorPoint(e); ICompositeView srcContainer = droppedModelItem != null ? DragDropHelper.GetCompositeView(droppedModelItem.View as WorkflowViewElement) as ICompositeView : null; bool keepRelativePosition = srcContainer is FlowchartDesigner; // This is the case of dragging from toolbox if (anchorPoint.X < 0 && anchorPoint.Y < 0) { keepRelativePosition = false; } // This is the case of dragging from the designer surface else if (droppedModelItem != null) { WorkflowViewElement view = (WorkflowViewElement)droppedModelItem.View; anchorPoint.Offset(-relativeLocations[view].X, -relativeLocations[view].Y); } if (droppedModelItem != null && srcContainer != null && srcContainer.Equals(this)) { if (shouldStoreCurrentSizeViewState) { // Moving may change the size of flowchart; need this to undo the size change. this.StoreCurrentSizeViewStateWithUndo(); shouldStoreCurrentSizeViewState = false; } //InternalMove PerformInternalMove(modelElement[droppedModelItem], e.GetPosition(this.panel), anchorPoint, autoConnectDirection, connectorToSplit); } else { //External model Item drop. if (droppedModelItem != null) { if ((IsFlowStepAction(droppedModelItem) || IsFlowNode(droppedModelItem)) && !IsParentOf(droppedModelItem, this.ModelItem)) { if (shouldStoreCurrentSizeViewState) { // Drop may change the size of flowchart; need this to undo the size change. this.StoreCurrentSizeViewStateWithUndo(); shouldStoreCurrentSizeViewState = false; } FlowNode flowElement = objToNewFlowNodeMap[droppedObject]; ModelItem flowElementMI; if (flowNodeModelItemMap.TryGetValue(flowElement, out flowElementMI)) { // FlowNode comes from some other flowchart. this.ModelItem.Properties["Nodes"].Collection.Add(flowElementMI); } else { // FlowNode is a new created one, which means this is an Activity dragged // from somewhere else, outside of Flowchart. flowElementMI = this.ModelItem.Properties["Nodes"].Collection.Add(flowElement); flowNodeModelItemMap[flowElement] = flowElementMI; } newFlowStepMI = flowElementMI; } else { //We want to route the event in the case that the flowchart is dropped upon itself. if (droppedModelItem.Equals(this.ModelItem)) { e.Handled = false; } //Don't add anything for what is neither a Activity nor a flowlink. continue; } if (droppedModelItem != null && droppedModelItem.View != null) { movedViewElements.Add((WorkflowViewElement)droppedModelItem.View); } // the external item may come from other panel (sequence) which is already given // a size by its previous layout panel. That might give an inaccurate size to the // dropped object (i.e. Bug 198290). Therefore, when the object is dropped externally // the FC should erases its previous hint size, forcing the FC to recompute an appropriate // size based on the workflowelementview size. VirtualizedContainerService.SetHintSize(droppedModelItem.GetCurrentValue(), null); } //Tool box drop. else { if (typeof(Activity).IsAssignableFrom(droppedObject.GetType())) { FlowStep flowStep = new FlowStep(); flowStep.Action = (Activity)droppedObject; if (shouldStoreCurrentSizeViewState) { // Drop may change the size of flowchart; need this to undo the size change. this.StoreCurrentSizeViewStateWithUndo(); shouldStoreCurrentSizeViewState = false; } newFlowStepMI = this.ModelItem.Properties["Nodes"].Collection.Add(flowStep); droppedModelItem = newFlowStepMI.Properties["Action"].Value; } else if (typeof(FlowNode).IsAssignableFrom(droppedObject.GetType())) { if (shouldStoreCurrentSizeViewState) { // Drop may change the size of flowchart; need this to undo the size change. this.StoreCurrentSizeViewStateWithUndo(); shouldStoreCurrentSizeViewState = false; } droppedModelItem = this.ModelItem.Properties["Nodes"].Collection.Add(droppedObject); newFlowStepMI = droppedModelItem; } // Now, toolbox drop doesn't support multiple drop // If multi-drop from tool box, use an array here. modelItemDroppedFromToolBox = droppedModelItem; keepRelativePosition = false; } // tool box WorkflowViewElement view = droppedModelItem.View as WorkflowViewElement; if (view == null || view.ExpandState) { //Creating a new view to get the size of collapsed view. view = this.ViewService.GetView(droppedModelItem) as WorkflowViewElement; ViewUtilities.MeasureView(view, true); } if (view != null) { PostDropUpdateViewState(view, newFlowStepMI, autoConnectDirection, connectorToSplit, e.GetPosition(this.panel), anchorPoint, keepRelativePosition, shapeOffsetter); } } // external move } // foreach // Remap references. // The re-map here is different from the remaping in copy/paste. // In copy paste, all the values are copied. but here, some value are // set by Properties["key"].SetValue(). // Don't move this into PrepareMove. Some value setting is added to // Change. So the operation here will decide the order of Change.Apply(). // PropertyChange in some case, must happen after ModelItem is moved to // new places. foreach (FlowNode flowNode in oldNewFlowNodeMap.Keys) { UpdateCloneReferenceByModelItem(flowNode, flowNodeModelItemMap, oldNewFlowNodeMap); } DragDropHelper.SetDragDropMovedViewElements(e, movedViewElements); //Backward compatibility for 4.0 if (droppedObjects.Count() == 1 && movedViewElements.Count == 1) { #pragma warning disable 618 DragDropHelper.SetDragDropCompletedEffects(e, DragDropEffects.Move); #pragma warning restore 618 } if (modelItemDroppedFromToolBox != null) { // if it is dropped from toolbox, select this.Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, (Action)(() => { UIElement view = (UIElement)(modelItemDroppedFromToolBox.View); if (view != null) { Keyboard.Focus(view); Selection.SelectOnly(this.Context, modelItemDroppedFromToolBox); } })); } if (droppedModelItem != null) { if (IsFlowNode(droppedModelItem)) { return droppedModelItem; } else if (IsFlowStepAction(droppedModelItem)) { if (newFlowStepMI != null) { return newFlowStepMI; } else { return this.GetParentFlowStepModelItem(droppedModelItem); } } return null; } return null; }
private AutoConnectDirections GetAutoConnectDirections(AutoConnectDirections directions, List<DependencyObject> childShapes, DependencyObject target) { directions = AutoConnectDirections.Top | AutoConnectDirections.Bottom | AutoConnectDirections.Left | AutoConnectDirections.Right; List<Rect> hitTestRects = CreateHitTestRects(FreeFormPanel.GetLocation(target), FreeFormPanel.GetChildSize(target)); this.RemoveDirectionsOutsideOfPanel(hitTestRects, ref directions); RemoveDirectionsInCollision(childShapes, target, hitTestRects, ref directions); return directions; }
private void AddDropTargets(DragEventArgs e, UIElement adornedElement, AutoConnectDirections directions) { AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(adornedElement); Fx.Assert(adornerLayer != null, "AdornerLayer should not be null."); adornerLayer.Add(new AutoConnectAdorner(adornedElement, this.panel, (directions & this.panel.AutoConnectContainer.GetDirectionsAllowed(e, adornedElement)))); this.CurrentTarget = adornedElement; }
protected override void OnDragLeave(DragEventArgs e) { base.OnDragLeave(e); this.highlightedDirection = AutoConnectDirections.None; this.InvalidateVisual(); }
// Check if hit test rects are completely within the FreeFormPanel rect, and remove that direction in case it's not. private void RemoveDirectionsOutsideOfPanel(List<Rect> hitTestRects, ref AutoConnectDirections directions) { Rect panelRect = new Rect(0, 0, this.panel.Width, this.panel.Height); for (int i = 0; i < hitTestRects.Count; i++) { if (!panelRect.Contains(hitTestRects[i])) { directions &= ~AutoConnectHelper.GetAutoConnectDirection(i); } } }
internal static EdgeLocation AutoConnectDirection2EdgeLocation(AutoConnectDirections direction) { EdgeLocation edgeLocation = EdgeLocation.Right; switch (direction) { case AutoConnectDirections.Left: edgeLocation = EdgeLocation.Left; break; case AutoConnectDirections.Right: edgeLocation = EdgeLocation.Right; break; case AutoConnectDirections.Top: edgeLocation = EdgeLocation.Top; break; case AutoConnectDirections.Bottom: edgeLocation = EdgeLocation.Bottom; break; } return edgeLocation; }
internal DependencyObject FindTarget(Point point, DependencyObject dragged, out AutoConnectDirections directions) { directions = AutoConnectDirections.None; List<DependencyObject> childShapes = this.panel.GetChildShapes(dragged); DependencyObject target = GetShapeContainingPoint(point, childShapes); if (target != null) { directions = this.GetAutoConnectDirections(directions, childShapes, target); } return target; }
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 connectorModelItem = null; Point location = e.GetPosition(sourceElement); ModelItem droppedModelItem = this.DoStateContainerGridDrop(e, direction, null); if (droppedModelItem != null) { connectorModelItem = this.DoAutoConnect(sourceElement, droppedModelItem, null); } if (connectorModelItem != null) { EdgeLocation edgeLocation = AutoConnectHelper.AutoConnectDirection2EdgeLocation(direction); this.GetStateMachineContainerEditor().activeSrcConnectionPoint = this.GetSourceConnectionPointForAutoConnect(sourceElement, edgeLocation); ModelItem sourceModelItem = TryGetModelItemFromView(sourceElement); Fx.Assert(sourceModelItem != null, "sourceModelItem"); // add a custom change inside a new editing scope since current editing scope an immediate editing scope using (EditingScope es = (EditingScope)this.ModelItem.BeginEdit(SR.AutoConnect, false)) { es.Changes.Add(new StoreAutoConnectorViewStateChange( this.ModelItem, sourceModelItem, droppedModelItem, connectorModelItem, edgeLocation)); es.Complete(); } scope.Complete(); } else { scope.Revert(); } } }
internal static Point CalculateDropLocation(Size droppedSize, DependencyObject autoConnectTarget, AutoConnectDirections direction, HashSet<Point> shapeLocations) { Point dropPoint = new Point(-1, -1); if (autoConnectTarget != null) { Point location = FreeFormPanel.GetLocation(autoConnectTarget); Size size = FreeFormPanel.GetChildSize(autoConnectTarget); switch (direction) { case AutoConnectDirections.Left: dropPoint = new Point(location.X - DropPointOffset - droppedSize.Width, location.Y + ((size.Height - droppedSize.Height) / 2)); break; case AutoConnectDirections.Right: dropPoint = new Point(location.X + size.Width + DropPointOffset, location.Y + ((size.Height - droppedSize.Height) / 2)); break; case AutoConnectDirections.Top: dropPoint = new Point(location.X + ((size.Width - droppedSize.Width) / 2), location.Y - DropPointOffset - droppedSize.Height); break; case AutoConnectDirections.Bottom: dropPoint = new Point(location.X + ((size.Width - droppedSize.Width) / 2), location.Y + DropPointOffset + size.Height); break; default: Fx.Assert(false, "Should not be here"); break; } dropPoint = new Point(dropPoint.X < 0 ? 0 : dropPoint.X, dropPoint.Y < 0 ? 0 : dropPoint.Y); if (shapeLocations != null) { while (shapeLocations.Contains(dropPoint)) { dropPoint.Offset(FreeFormPanel.GridSize, FreeFormPanel.GridSize); } } } return dropPoint; }
void PerformInternalMove(UIElement movedElement, Point newPoint, Point? shapeAnchorPoint, AutoConnectDirections autoConnectDirection, Connector connectorToSplit) { using (EditingScope es = (EditingScope)this.ModelItem.BeginEdit(SR.ItemMove)) { StoreShapeSizeWithUndoRecursively(this.ModelItem); this.RemoveConnectionPointsAdorner(movedElement); Point newLocation; Size size = FreeFormPanel.GetChildSize(movedElement); if (autoConnectDirection != AutoConnectDirections.None) { newLocation = this.CalculateDropLocationForAutoConnect(autoConnectDirection, size); } else if (shapeAnchorPoint.HasValue) { newLocation = SnapVisualToGrid(movedElement, newPoint, shapeAnchorPoint.Value, true); } else { Fx.Assert(newPoint.X.IsNoLessThan(0) && newPoint.Y.IsNoLessThan(0), "newPoint is negative"); newLocation = newPoint; } if (connectorToSplit != null) { newLocation = this.CalculateDropLocationForAutoSplit(newPoint, newLocation, connectorToSplit, size); } ModelItem modelItem = GetModelItemFromView(movedElement); object viewState = this.ViewStateService.RetrieveViewState(modelItem, ShapeLocationViewStateKey); if (viewState != null) { Point oldLocation = (Point)viewState; // To make sure the connectors are still connected to the connection points. // We don't need to offset non-contained connectors because internal move // won't cause the connectors to be recreated and we have code in FreeFormPanel // to guarantee that connectors will still be connected to the connection points this.OffsetConnectorViewState(movedElement, oldLocation, newLocation, false); } else { this.StoreAttachedConnectorViewStates(movedElement); } this.StoreShapeLocationViewState(movedElement, newLocation); // To make sure the connector changes are undoable this.panel.RemoveConnectorEditor(); es.Complete(); } }
// Returns the last dropped item - used for auto-connect and auto-split where only one item is allowed ModelItem DoStateContainerGridDrop(DragEventArgs e, AutoConnectDirections autoConnectDirection, Connector connectorToSplit) { ModelItem droppedModelItem = null; e.Effects = DragDropEffects.None; IEnumerable<object> droppedObjects = DragDropHelper.GetDroppedObjects(this, e, Context); // Marking the event as being handled. In whichever case we want to route the event, it will be unmarked explicitly. e.Handled = true; List<ModelItem> modelItemsToSelect = new List<ModelItem>(); Dictionary<WorkflowViewElement, Point> relativeLocations = DragDropHelper.GetDraggedViewElementRelativeLocations(e); foreach (object droppedObject in droppedObjects) { if (droppedObject != null) { droppedModelItem = droppedObject as ModelItem; bool isAnchorPointValid = true; Point anchorPoint = DragDropHelper.GetDragDropAnchorPoint(e); // This is the case of dragging from toolbox if (anchorPoint.X < 0 && anchorPoint.Y < 0) { isAnchorPointValid = false; } // This is the case of dragging from the designer surface else if (droppedModelItem != null) { WorkflowViewElement view = droppedModelItem.View as WorkflowViewElement; anchorPoint.Offset(-relativeLocations[view].X, -relativeLocations[view].Y); } StateContainerEditor srcContainer = droppedModelItem != null ? DragDropHelper.GetCompositeView(droppedModelItem.View as WorkflowViewElement) as StateContainerEditor : null; bool externalDrop = false; if (droppedModelItem != null && srcContainer != null && srcContainer.Equals(this)) { // Internal move PerformInternalMove(this.modelItemToUIElement[droppedModelItem], e.GetPosition(this.panel), anchorPoint, autoConnectDirection, connectorToSplit); } else { // External model Item drop if (droppedModelItem != null) { if (droppedModelItem.ItemType == typeof(State) && this.ModelItem.ItemType == typeof(StateMachine)) { this.InsertState(droppedModelItem); externalDrop = true; } } // Toolbox drop. else { if (droppedObject.GetType() == typeof(State)) { if (((State)droppedObject).DisplayName == null) { ((State)droppedObject).DisplayName = GenerateStateName(); } droppedModelItem = InsertState(droppedObject); } else if (droppedObject.GetType() == typeof(FinalState)) { droppedModelItem = InsertState(new State() { DisplayName = DefaultFinalStateDisplayName, IsFinal = true }); } } if (droppedModelItem != null) { modelItemsToSelect.Add(droppedModelItem); UIElement view = null; if (this.modelItemToUIElement.ContainsKey(droppedModelItem)) { view = this.modelItemToUIElement[droppedModelItem]; } else { view = droppedModelItem.View as WorkflowViewElement; if (view == null) { view = this.Context.Services.GetService<ViewService>().GetView(droppedModelItem) as WorkflowViewElement; ViewUtilities.MeasureView(view as WorkflowViewElement, true); } } // If drag anchor point is beyond the size of the shape being dropped, if (anchorPoint.X > view.DesiredSize.Width || anchorPoint.Y > view.DesiredSize.Height) { isAnchorPointValid = false; } Point shapeLocation; if (autoConnectDirection != AutoConnectDirections.None) { shapeLocation = this.CalculateDropLocationForAutoConnect(autoConnectDirection, new Size(DefaultStateDesignerWidth, DefaultStateDesignerHeight)); } else { shapeLocation = StateContainerEditor.SnapVisualToGrid(view, e.GetPosition(this.panel), anchorPoint, isAnchorPointValid); } if (connectorToSplit != null) { shapeLocation = this.CalculateDropLocationForAutoSplit(e.GetPosition(this.panel), shapeLocation, connectorToSplit, new Size(DefaultStateDesignerWidth, DefaultStateDesignerHeight)); } object viewState = this.ViewStateService.RetrieveViewState(droppedModelItem, ShapeLocationViewStateKey); if (externalDrop) { Fx.Assert(viewState != null, "item dropped from external should already have view states"); Fx.Assert(droppedModelItem.View != null, "item dropped from extenal should already have view"); VirtualizedContainerService.VirtualizingContainer container = VisualTreeUtils.FindVisualAncestor<VirtualizedContainerService.VirtualizingContainer>(droppedModelItem.View); Fx.Assert(container != null, "container should not be null"); Point oldLocation = (Point)viewState; oldLocation = srcContainer.panel.GetLocationRelativeToOutmostPanel(oldLocation); Point newLocation = this.panel.GetLocationRelativeToOutmostPanel(shapeLocation); // To make sure the connectors are still connected to the connection points OffsetConnectorViewState(container, oldLocation, newLocation, true); } this.StoreShapeLocationViewState(droppedModelItem, shapeLocation); } } } } DragDropHelper.SetDragDropMovedViewElements(e, new WorkflowViewElement[] { }); this.Dispatcher.BeginInvoke(() => { bool first = true; foreach (ModelItem modelItem in modelItemsToSelect) { if (first) { Keyboard.Focus((IInputElement)modelItem.View); Selection.SelectOnly(this.Context, modelItem); first = false; } else { Selection.Union(this.Context, modelItem); } } }, DispatcherPriority.ApplicationIdle); return droppedModelItem; }
public AutoConnectAdorner(UIElement adornedElement, FreeFormPanel panel, AutoConnectDirections directions) : base(adornedElement) { this.panel = panel; this.directions = directions; Size size = FreeFormPanel.GetChildSize(this.AdornedElement); this.adornedElementRect = new Rect(new Point(0, 0), size); this.hitTestRects = new Rect[] { new Rect(-HitTestHeight, (size.Height / 2) - (HitTestWidth / 2), HitTestHeight, HitTestWidth), new Rect(size.Width, (size.Height / 2) - (HitTestWidth / 2), HitTestHeight, HitTestWidth), new Rect((size.Width / 2) - (HitTestWidth / 2), -HitTestHeight, HitTestWidth, HitTestHeight), new Rect((size.Width / 2) - (HitTestWidth / 2), size.Height, HitTestWidth, HitTestHeight) }; this.renderGeometries = new PathGeometry[] { new PathGeometry() { Figures = { new PathFigure() { StartPoint = new Point(-DropTargetOffset - TriangleHeight, size.Height / 2), Segments = { new LineSegment() { Point = new Point(-DropTargetOffset, (size.Height / 2) - (TriangleBaseLength / 2)) }, new LineSegment() { Point = new Point(-DropTargetOffset, (size.Height / 2) + (TriangleBaseLength / 2)) }, new LineSegment() { Point = new Point(-DropTargetOffset - TriangleHeight, size.Height / 2) } } } } }, new PathGeometry() { Figures = { new PathFigure() { StartPoint = new Point(size.Width + DropTargetOffset, (size.Height / 2) - (TriangleBaseLength / 2)), Segments = { new LineSegment() { Point = new Point(size.Width + DropTargetOffset + TriangleHeight, size.Height / 2) }, new LineSegment() { Point = new Point(size.Width + DropTargetOffset, (size.Height / 2) + (TriangleBaseLength / 2)) }, new LineSegment() { Point = new Point(size.Width + DropTargetOffset, (size.Height / 2) - (TriangleBaseLength / 2)) } } } } }, new PathGeometry() { Figures = { new PathFigure() { StartPoint = new Point((size.Width / 2) - (TriangleBaseLength / 2), -DropTargetOffset), Segments = { new LineSegment() { Point = new Point((size.Width / 2), -DropTargetOffset - TriangleHeight) }, new LineSegment() { Point = new Point((size.Width / 2) + (TriangleBaseLength / 2), -DropTargetOffset) }, new LineSegment() { Point = new Point((size.Width / 2) - (TriangleBaseLength / 2), -DropTargetOffset) } } } } }, new PathGeometry() { Figures = { new PathFigure() { StartPoint = new Point((size.Width / 2) - (TriangleBaseLength / 2), size.Height + DropTargetOffset), Segments = { new LineSegment() { Point = new Point((size.Width / 2) + (TriangleBaseLength / 2), size.Height + DropTargetOffset) }, new LineSegment() { Point = new Point((size.Width / 2), size.Height + TriangleHeight + DropTargetOffset) }, new LineSegment() { Point = new Point((size.Width / 2) - (TriangleBaseLength / 2), size.Height + DropTargetOffset) } } } } } }; }
// Move the object to correct position after drop private void PostDropUpdateViewState(WorkflowViewElement view, ModelItem flownodeMI, AutoConnectDirections autoConnectDirection, Connector connectorToSplit, Point newPoint, Point anchorPoint, bool keepRelativePosition, ShapeOffsetter shapeOffsetter) { Fx.Assert((view != null && flownodeMI != null), "movedItem != null && flownodeMI != null"); Point shapeLocationPtr; if (autoConnectDirection != AutoConnectDirections.None) { shapeLocationPtr = this.CalculateDropLocationForAutoConnect(autoConnectDirection, view.DesiredSize); } else { shapeLocationPtr = SnapVisualToGrid(view, newPoint, anchorPoint, keepRelativePosition); if (!keepRelativePosition) { // To avoid overlaps shapeLocationPtr = shapeOffsetter.OffsetShapeLocation(shapeLocationPtr); } } if (connectorToSplit != null) { shapeLocationPtr = this.CalculateDropLocationForAutoSplit(newPoint, shapeLocationPtr, connectorToSplit, view.DesiredSize); } // if (keepRelativePosition) { this.OffsetDroppedItemToNewPosition(flownodeMI, shapeLocationPtr); } else { this.StoreShapeViewState(flownodeMI, shapeLocationPtr); } }
// Check if hit test rects collide with any children of the FreeFormPanel, and remove that direction in case a collision is found. private static void RemoveDirectionsInCollision(List<DependencyObject> childShapes, DependencyObject target, List<Rect> hitTestRects, ref AutoConnectDirections directions) { foreach (DependencyObject shape in childShapes) { if (directions == AutoConnectDirections.None) { break; } if (object.Equals(shape, target)) { continue; } Point shapeLocation = FreeFormPanel.GetLocation(shape); Size shapeSize = FreeFormPanel.GetChildSize(shape); Rect shapeRect = new Rect(shapeLocation, shapeSize); for (int i = 0; i < hitTestRects.Count; i++) { if (hitTestRects[i].IntersectsWith(shapeRect)) { directions &= ~AutoConnectHelper.GetAutoConnectDirection(i); } } } }
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(); } } }
internal void UpdateHighlightedDirection(Point position) { Size size = FreeFormPanel.GetChildSize(this.AdornedElement); if (position.X < 0 && this.highlightedDirection != AutoConnectDirections.Left) { this.highlightedDirection = AutoConnectDirections.Left; this.InvalidateVisual(); } else if (position.X > size.Width && this.highlightedDirection != AutoConnectDirections.Right) { this.highlightedDirection = AutoConnectDirections.Right; this.InvalidateVisual(); } else if (position.Y < 0 && this.highlightedDirection != AutoConnectDirections.Top) { this.highlightedDirection = AutoConnectDirections.Top; this.InvalidateVisual(); } else if (position.Y > size.Height && this.highlightedDirection != AutoConnectDirections.Bottom) { this.highlightedDirection = AutoConnectDirections.Bottom; this.InvalidateVisual(); } }