void BringToFront() { FreeFormPanel panel = StateContainerEditor.GetVisualAncestor <FreeFormPanel>(this); // It is possible when BringToFront is executed, the state has already been deleted if (panel != null) { panel.Children.Remove(this); panel.Children.Add(this); // Bring to front all attached connectors including those attached to child states StateContainerEditor parent = StateContainerEditor.GetVisualAncestor <StateContainerEditor>(this); if (parent != null) { FreeFormPanel outmostPanel = parent.GetOutmostStateContainerEditor().Panel; HashSet <Connector> connectors = new HashSet <Connector>(); List <ModelItem> allStateModelItems = new List <ModelItem>(); allStateModelItems.Add(this.ModelItem); allStateModelItems.AddRange(StateContainerEditor.GetAllChildStateModelItems(this.ModelItem)); foreach (ModelItem stateModelItem in allStateModelItems) { List <Connector> attachedConnectors = StateContainerEditor.GetAttachedConnectors((UIElement)stateModelItem.View); foreach (Connector connector in attachedConnectors) { connectors.Add(connector); } } foreach (Connector connector in connectors) { outmostPanel.Children.Remove(connector); outmostPanel.Children.Add(connector); } } } }
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); }
static ConnectionPoint ConnectionPointHitTest(UIElement element, Point hitPoint) { FreeFormPanel panel = VisualTreeUtils.FindVisualAncestor <FreeFormPanel>(element); List <ConnectionPoint> connectionPoints = StateContainerEditor.GetConnectionPoints(element); return(FreeFormPanel.ConnectionPointHitTest(hitPoint, connectionPoints, panel)); }
ConnectionPoint ConnectionPointHitTest(UIElement element, Point hitPoint) { List <ConnectionPoint> connectionPoints = new List <ConnectionPoint>(); List <ConnectionPoint> defaultConnectionPoints = FlowchartDesigner.GetConnectionPoints(element); connectionPoints.InsertRange(0, defaultConnectionPoints); connectionPoints.Add(FlowchartDesigner.GetTrueConnectionPoint(element)); connectionPoints.Add(FlowchartDesigner.GetFalseConnectionPoint(element)); return(FreeFormPanel.ConnectionPointHitTest(hitPoint, connectionPoints, this.panel)); }
void DeleteLinkVisual(Connector link) { ConnectionPoint srcConnectionPoint = FreeFormPanel.GetSourceConnectionPoint(link); ConnectionPoint destConnectionPoint = FreeFormPanel.GetDestinationConnectionPoint(link); //Update ConnectionPoints. srcConnectionPoint.AttachedConnectors.Remove(link); destConnectionPoint.AttachedConnectors.Remove(link); this.panel.Children.Remove(link); }
protected override void OnRender(DrawingContext drawingContext) { Point actualPoint; Point origin = FreeFormPanel.GetLocation(AdornedElement); Thickness margin = ((FrameworkElement)AdornedElement).Margin; origin.X += margin.Left; origin.Y += margin.Top; foreach (ConnectionPoint connPoint in connectionPoints) { actualPoint = new Point(connPoint.Location.X - origin.X, connPoint.Location.Y - origin.Y); this.DrawConnectionPoint(connPoint, actualPoint, drawingContext); } base.OnRender(drawingContext); }
protected override void OnMouseMove(MouseEventArgs args) { base.OnMouseMove(args); if (args != null && !this.Disabled) { if (args.LeftButton == MouseButtonState.Pressed && this.IsMouseCaptured) { StateContainerEditor stateContainerEditor = this.ParentStateContainerEditor; FreeFormPanel panel = stateContainerEditor.Panel; Grid stateContainerGrid = stateContainerEditor.stateContainerGrid; Point currentPosition = Mouse.GetPosition(stateContainerGrid); currentPosition.Offset(this.offset.X, this.offset.Y); stateContainerEditor.StateContainerWidth = Math.Min(Math.Max(panel.RequiredWidth, currentPosition.X), stateContainerGrid.MaxWidth); stateContainerEditor.StateContainerHeight = Math.Min(Math.Max(panel.RequiredHeight, currentPosition.Y), stateContainerGrid.MaxHeight); } } }
static ConnectionPoint GetSrcConnectionPointForSharedTrigger(UIElement sourceDesigner, ModelItem connectorModelItem) { ConnectionPoint sourceConnectionPoint = null; List <Connector> connectors = StateContainerEditor.GetOutgoingConnectors(sourceDesigner); foreach (Connector connector in connectors) { ModelItem modelItem = StateContainerEditor.GetConnectorModelItem(connector); if (modelItem != null && modelItem.ItemType == typeof(Transition)) { if (modelItem.Properties[TransitionDesigner.TriggerPropertyName].Value == connectorModelItem.Properties[TransitionDesigner.TriggerPropertyName].Value) { sourceConnectionPoint = FreeFormPanel.GetSourceConnectionPoint(connector); } } } return(sourceConnectionPoint); }
void CreateStartSymbol() { //Instantiate the start symbol StartSymbol start = System.Activities.Core.Presentation.StartSymbol.CreateStartSymbol(this.Context); start.Text = "Start"; this.flowStart = start.ModelItem; DragDropHelper.SetCompositeView(start, this); modelElement.Add(flowStart, start); start.SizeChanged += new SizeChangedEventHandler(ChildSizeChanged); this.StartSymbol = start; PopulateConnectionPoints(this.StartSymbol, null); this.StartSymbol.MouseEnter += new MouseEventHandler(ChildElement_MouseEnter); this.StartSymbol.MouseLeave += new MouseEventHandler(ChildElement_MouseLeave); //Getting the View state information. object locationOfShape = this.ViewStateService.RetrieveViewState(this.ModelItem, shapeLocation); object sizeOfShape = this.ViewStateService.RetrieveViewState(this.ModelItem, shapeSize); if (locationOfShape != null) { Point locationPt = (Point)locationOfShape; FreeFormPanel.SetLocation(this.StartSymbol, locationPt); } else { //Set the location of the start symbol. this.StartSymbol.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity)); double startHeight = this.StartSymbol.DesiredSize.Height; double startWidth = this.StartSymbol.DesiredSize.Width; Point startPoint = new Point(panel.MinWidth / 2, startSymbolTopMargin + startHeight / 2); Point startLocation = SnapVisualToGrid(this.StartSymbol, startPoint, new Point(-1, -1), false); FreeFormPanel.SetLocation(this.StartSymbol, startLocation); this.internalViewStateChange = true; this.StoreShapeViewState(this.ModelItem, startLocation); this.internalViewStateChange = false; } if (sizeOfShape != null) { FreeFormPanel.SetChildSize(this.StartSymbol, (Size)sizeOfShape); } }
static ConnectionPoint ConnectionPointHitTest(UIElement element, Point hitPoint) { ConnectionPoint hitConnectionPoint = null; List <ConnectionPoint> connectionPoints = StateContainerEditor.GetConnectionPoints(element); foreach (ConnectionPoint connPoint in connectionPoints) { if (connPoint != null) { // We need to transform the connection point location to be relative to the outmost panel FreeFormPanel panel = GetVisualAncestor <FreeFormPanel>(element); if (new Rect(panel.GetLocationRelativeToOutmostPanel(connPoint.Location) + connPoint.HitTestOffset, connPoint.HitTestSize).Contains(hitPoint)) { hitConnectionPoint = connPoint; break; } } } return(hitConnectionPoint); }
protected override void OnMouseMove(MouseEventArgs args) { base.OnMouseMove(args); if (!this.Disabled) { if (args.LeftButton == MouseButtonState.Pressed && this.IsMouseCaptured) { FlowchartDesigner flowchartDesigner = this.ParentFlowchartDesigner; FreeFormPanel panel = flowchartDesigner.panel; Grid flowchartGrid = this.ParentGrid; Point currentPosition = Mouse.GetPosition(flowchartGrid); currentPosition.Offset(this.offset.X, this.offset.Y); flowchartDesigner.FlowchartWidth = Math.Min(Math.Max(panel.RequiredWidth, currentPosition.X), flowchartGrid.MaxWidth); flowchartDesigner.FlowchartHeight = Math.Min(Math.Max(panel.RequiredHeight, currentPosition.Y), flowchartGrid.MaxHeight); args.Handled = 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); }
private static List <ConnectionPoint> FindCandidatePointsForLink(List <ConnectionPoint> destConnPoints, ConnectionPointKind excludePointType) { List <ConnectionPoint> candidateDestConnPoints; IEnumerable <ConnectionPoint> freeDestConnPoints = destConnPoints.Where(p => p.PointType != excludePointType && !p.AttachedConnectors.Any()); if (freeDestConnPoints.Any()) { candidateDestConnPoints = freeDestConnPoints.ToList(); } else { IEnumerable <ConnectionPoint> availablePoints = destConnPoints.Where( p => p.PointType != excludePointType && p.AttachedConnectors.Any(connector => FreeFormPanel.GetDestinationConnectionPoint(connector).Equals(p))); candidateDestConnPoints = availablePoints.Any() ? availablePoints.ToList() : destConnPoints; } return(candidateDestConnPoints); }
void OnViewStateChanged(object sender, ViewStateChangedEventArgs e) { Debug.Assert(e.ParentModelItem != null, "ViewState should be associated with some modelItem"); if (!this.internalViewStateChange) { if (e.ParentModelItem == this.ModelItem) { if (string.Equals(e.Key, StateContainerWidthViewStateKey, StringComparison.Ordinal)) { double defaultWidth = ((this.ModelItem.ItemType == typeof(State)) ? DefaultStateWidth : DefaultStateMachineWidth); object widthViewState = this.ViewStateService.RetrieveViewState(this.ModelItem, StateContainerWidthViewStateKey); this.StateContainerWidth = (widthViewState != null) ? (double)widthViewState : defaultWidth; } else if (string.Equals(e.Key, StateContainerHeightViewStateKey, StringComparison.Ordinal)) { double defaultHeight = ((this.ModelItem.ItemType == typeof(State)) ? DefaultStateHeight : DefaultStateMachineHeight); object heightViewState = this.ViewStateService.RetrieveViewState(this.ModelItem, StateContainerHeightViewStateKey); this.StateContainerHeight = (heightViewState != null) ? (double)heightViewState : defaultHeight; } } if (e.ParentModelItem.ItemType == typeof(State) && e.Key.Equals(ShapeLocationViewStateKey)) { if (this.modelItemToUIElement.ContainsKey(e.ParentModelItem)) { if (e.NewValue != null) { FreeFormPanel.SetLocation(this.modelItemToUIElement[e.ParentModelItem], (Point)e.NewValue); this.panel.InvalidateMeasure(); if (e.OldValue != null) { this.shapeLocations.Remove((Point)e.OldValue); } this.shapeLocations.Add((Point)e.NewValue); // To reroute the links this.InvalidateMeasureForOutmostPanel(); } } } else if (e.ParentModelItem.ItemType == typeof(State) && e.Key.Equals(ShapeSizeViewStateKey)) { // To reroute the links this.InvalidateMeasureForOutmostPanel(); } // Only the outmost editor should respond to connector changes because all connectors are // only added to the outmost editor else if (e.Key.Equals(ConnectorLocationViewStateKey) && this.IsOutmostStateContainerEditor()) { Connector changedConnector = this.GetConnectorOnOutmostEditor(e.ParentModelItem); if (changedConnector != null) { if (e.NewValue != null) { Debug.Assert(e.NewValue is PointCollection, "e.NewValue is not PointCollection"); changedConnector.Points = e.NewValue as PointCollection; this.panel.RemoveConnectorEditor(); this.InvalidateMeasureForOutmostPanel(); if (IsConnectorFromInitialNode(changedConnector)) { this.initialStateChanged = true; } } } } } }
internal Connector GetLinkOnCanvas(ModelItem srcFlowElementModelItem, ModelItem destflowElementModelItem, string propertyName) { Connector linkOnCanvas = null; ModelItem shapeModelItem = null; List <Connector> outGoingConnectors = null; if (!srcFlowElementModelItem.Equals(this.ModelItem)) { shapeModelItem = this.GetCorrespondingElementOnCanvas(srcFlowElementModelItem); outGoingConnectors = GetOutGoingConnectors(this.modelElement[shapeModelItem]); } else // Must be startNode { outGoingConnectors = GetOutGoingConnectors(this.StartSymbol); } foreach (Connector connector in outGoingConnectors) { ModelItem connectorDestModelItem = ((VirtualizedContainerService.VirtualizingContainer)FreeFormPanel.GetDestinationConnectionPoint(connector).ParentDesigner).ModelItem; ModelItem connectorDestFlowElementMI = this.GetFlowElementMI(connectorDestModelItem); //Following condition checks if the destination for current connector is equal to the destination passed in. if (destflowElementModelItem != null && destflowElementModelItem.Equals(connectorDestFlowElementMI)) { if (GenericFlowSwitchHelper.IsGenericFlowSwitch(srcFlowElementModelItem.ItemType)) { ModelItem linkModelItem = FlowchartDesigner.GetLinkModelItem(connector); if (linkModelItem.Properties["IsDefaultCase"].Value.GetCurrentValue().Equals(true) && propertyName.Equals("Default")) { linkOnCanvas = connector; break; } else { ModelItem connectorCaseMI = linkModelItem.Properties["Case"].Value; if (linkModelItem.Properties["IsDefaultCase"].Value.GetCurrentValue().Equals(false)) { string caseName = connectorCaseMI == null ? null : GenericFlowSwitchHelper.GetString(connectorCaseMI.GetCurrentValue(), connectorCaseMI.ItemType); if (connectorCaseMI != null && caseName.Equals(propertyName.Substring(GenericFlowSwitchHelper.FlowSwitchCasesKeyIdentifier.Length))) { linkOnCanvas = connector; break; } else if (connectorCaseMI == null) { if (GenericFlowSwitchHelper.FlowSwitchNullCaseKeyIdentifier.Equals(propertyName.Substring(GenericFlowSwitchHelper.FlowSwitchCasesKeyIdentifier.Length))) { linkOnCanvas = connector; break; } } } } } else if (typeof(FlowDecision).IsAssignableFrom(srcFlowElementModelItem.ItemType)) { ConnectionPoint trueConnPoint = FlowchartDesigner.GetTrueConnectionPoint(this.modelElement[shapeModelItem]); ConnectionPoint falseConnPoint = FlowchartDesigner.GetFalseConnectionPoint(this.modelElement[shapeModelItem]); ConnectionPoint connectorSrcConnPoint = FreeFormPanel.GetSourceConnectionPoint(connector); if ((propertyName.Equals("True") && connectorSrcConnPoint.Equals(trueConnPoint)) || (propertyName.Equals("False") && connectorSrcConnPoint.Equals(falseConnPoint))) { linkOnCanvas = connector; break; } } else //FlowStep case. { linkOnCanvas = connector; break; } } } return(linkOnCanvas); }
void OnViewStateChanged(object sender, ViewStateChangedEventArgs e) { Fx.Assert(this.panel != null, "This code should not be hit if panel is null"); Fx.Assert(e.ParentModelItem != null, "ViewState should be associated with some modelItem"); Connector changedConnector = null; if (e.ParentModelItem == this.ModelItem) { if (string.Equals(e.Key, FlowchartSizeFeature.WidthPropertyName, StringComparison.Ordinal)) { this.FlowchartWidth = (double)TypeDescriptor.GetProperties(this.ModelItem)[FlowchartSizeFeature.WidthPropertyName].GetValue(this.ModelItem); } else if (string.Equals(e.Key, FlowchartSizeFeature.HeightPropertyName, StringComparison.Ordinal)) { this.FlowchartHeight = (double)TypeDescriptor.GetProperties(this.ModelItem)[FlowchartSizeFeature.HeightPropertyName].GetValue(this.ModelItem); } } if ((IsFlowNode(e.ParentModelItem) || this.ModelItem.Equals(e.ParentModelItem)) && !this.internalViewStateChange) { ModelItem itemOnCanvas = this.GetCorrespondingElementOnCanvas(e.ParentModelItem); if (this.modelElement.ContainsKey(itemOnCanvas)) { if (e.Key.Equals(shapeLocation)) { if (e.NewValue != null) { FreeFormPanel.SetLocation(this.modelElement[itemOnCanvas], (Point)e.NewValue); this.panel.InvalidateMeasure(); if (e.OldValue != null) { this.shapeLocations.Remove((Point)e.OldValue); } this.shapeLocations.Add((Point)e.NewValue); } } else { if (this.ModelItem.Equals(e.ParentModelItem) && e.Key.Equals(ConnectorViewStateKey)) { changedConnector = this.GetLinkOnCanvas(e.ParentModelItem, e.ParentModelItem.Properties["StartNode"].Value, "StartNode"); } else if (typeof(FlowStep).IsAssignableFrom(e.ParentModelItem.ItemType) && e.Key.Equals(ConnectorViewStateKey)) { changedConnector = this.GetLinkOnCanvas(e.ParentModelItem, e.ParentModelItem.Properties["Next"].Value, "Next"); } else if (typeof(FlowDecision).IsAssignableFrom(e.ParentModelItem.ItemType)) { if (e.Key.Equals(TrueConnectorViewStateKey)) { changedConnector = this.GetLinkOnCanvas(e.ParentModelItem, e.ParentModelItem.Properties["True"].Value, "True"); } else if (e.Key.Equals(FalseConnectorViewStateKey)) { changedConnector = this.GetLinkOnCanvas(e.ParentModelItem, e.ParentModelItem.Properties["False"].Value, "False"); } } else if (GenericFlowSwitchHelper.IsGenericFlowSwitch(e.ParentModelItem.ItemType)) { if (e.Key.Equals(FlowchartDesigner.FlowSwitchDefaultViewStateKey, StringComparison.CurrentCulture)) { changedConnector = this.GetLinkOnCanvas(e.ParentModelItem, e.ParentModelItem.Properties["Default"].Value, e.Key); } else if (e.Key.EndsWith(CaseViewStateKeyAppendString, StringComparison.CurrentCulture)) { string switchCaseName = e.Key.Substring(0, e.Key.Length - CaseViewStateKeyAppendString.Length); object switchCase = switchCaseName; Type genericType = e.ParentModelItem.ItemType.GetGenericArguments()[0]; switchCase = GenericFlowSwitchHelper.GetObject(switchCaseName, genericType); if (GenericFlowSwitchHelper.ContainsCaseKey(e.ParentModelItem.Properties["Cases"], switchCase)) { //Prepending with GenericFlowSwitchHelper.FlowSwitchCasesKeyIdentifier to differentiate between the property Default and the key Default. changedConnector = this.GetLinkOnCanvas(e.ParentModelItem, GenericFlowSwitchHelper.GetCaseModelItem(e.ParentModelItem.Properties["Cases"], switchCase), GenericFlowSwitchHelper.FlowSwitchCasesKeyIdentifier + switchCase); } } } } } } if (changedConnector != null) { if (e.NewValue != null) { Fx.Assert(e.NewValue is PointCollection, "e.NewValue is not PointCollection"); changedConnector.Points = e.NewValue as PointCollection; this.panel.RemoveConnectorEditor(); this.panel.InvalidateMeasure(); } } }
private IFlowSwitchLink DeleteLinkImpl(Connector link, bool isMoveOrAutoSplit = false, HashSet <ModelItem> referenceUpdatedModelItems = null) { IFlowSwitchLink caseKey = null; ModelItem linkModelItem = FlowchartDesigner.GetLinkModelItem(link); if (referenceUpdatedModelItems != null && referenceUpdatedModelItems.Contains(linkModelItem)) { return(caseKey); } ConnectionPoint srcConnectionPoint = FreeFormPanel.GetSourceConnectionPoint(link); ConnectionPoint destConnectionPoint = FreeFormPanel.GetDestinationConnectionPoint(link); if (typeof(FlowStep).IsAssignableFrom(linkModelItem.ItemType)) { linkModelItem.Properties["Next"].SetValue(null); } else if (typeof(FlowDecision).IsAssignableFrom(linkModelItem.ItemType)) { //Determine if it is True or False branch. if (srcConnectionPoint.Equals(FlowchartDesigner.GetTrueConnectionPoint(srcConnectionPoint.ParentDesigner))) { //True branch linkModelItem.Properties["True"].SetValue(null); } else { linkModelItem.Properties["False"].SetValue(null); } } else if (typeof(IFlowSwitchLink).IsAssignableFrom(linkModelItem.ItemType)) { IFlowSwitchLink flowSwitchLink = (IFlowSwitchLink)linkModelItem.GetCurrentValue(); caseKey = flowSwitchLink; //Transitioning from the fakeModelItem world to the real ModelItem world. FlowNode fs = flowSwitchLink.ParentFlowSwitch; ModelItem realFlowSwitchMI = (this.ModelItem as IModelTreeItem).ModelTreeManager.WrapAsModelItem(fs); if (referenceUpdatedModelItems != null && referenceUpdatedModelItems.Contains(realFlowSwitchMI)) { return(caseKey); } if (flowSwitchLink.IsDefaultCase) { realFlowSwitchMI.Properties["Default"].SetValue(null); if (!isMoveOrAutoSplit) { realFlowSwitchMI.Properties[FlowSwitchLabelFeature.DefaultCaseDisplayNamePropertyName].SetValue(FlowSwitchLabelFeature.DefaultCaseDisplayNameDefaultValue); } } else { GenericFlowSwitchHelper.RemoveCase(realFlowSwitchMI.Properties["Cases"], flowSwitchLink.CaseObject); } } else // StartNode { this.ModelItem.Properties["StartNode"].SetValue(null); } this.StoreConnectorViewState(linkModelItem, null, srcConnectionPoint, true); return(caseKey); }
List <Connector> GetOutGoingConnectors(UIElement shape) { List <Connector> outGoingConnectors = new List <Connector>(); List <ConnectionPoint> allConnectionPoints = GetAllConnectionPoints(shape); foreach (ConnectionPoint connPoint in allConnectionPoints) { if (connPoint != null) { outGoingConnectors.AddRange(connPoint.AttachedConnectors.Where(p => FreeFormPanel.GetSourceConnectionPoint(p).Equals(connPoint))); } } return(outGoingConnectors); }
static List <Connector> GetIncomingConnectors(UIElement shape) { List <Connector> incomingConnectors = new List <Connector>(); List <ConnectionPoint> allConnectionPoints = GetConnectionPoints(shape); foreach (ConnectionPoint connPoint in allConnectionPoints) { if (connPoint != null) { incomingConnectors.AddRange(connPoint.AttachedConnectors.Where(p => FreeFormPanel.GetDestinationConnectionPoint(p).Equals(connPoint))); } } return(incomingConnectors); }
protected override void OnRender(DrawingContext drawingContext) { const int textCulture = 9; ConnectionPoint trueConnectionPoint = null; ConnectionPoint falseConnectionPoint = null; if (this.connectionPoints.Contains(FlowchartDesigner.GetTrueConnectionPoint(this.AdornedElement))) { trueConnectionPoint = FlowchartDesigner.GetTrueConnectionPoint(this.AdornedElement); } if (this.connectionPoints.Contains(FlowchartDesigner.GetFalseConnectionPoint(this.AdornedElement))) { falseConnectionPoint = FlowchartDesigner.GetFalseConnectionPoint(this.AdornedElement); } Point actualPoint; Point origin = FreeFormPanel.GetLocation(AdornedElement); Thickness margin = ((FrameworkElement)AdornedElement).Margin; origin.X += margin.Left; origin.Y += margin.Top; foreach (ConnectionPoint connPoint in this.connectionPoints) { actualPoint = new Point(connPoint.Location.X - origin.X, connPoint.Location.Y - origin.Y); this.DrawConnectionPoint(connPoint, actualPoint, drawingContext); } if (trueConnectionPoint != null) { string trueLabelText = String.Empty; VirtualizedContainerService.VirtualizingContainer virtualizingContainer = (VirtualizedContainerService.VirtualizingContainer)trueConnectionPoint.ParentDesigner; if (virtualizingContainer != null && virtualizingContainer.ModelItem != null) { trueLabelText = (string)virtualizingContainer.ModelItem.Properties["TrueLabel"].ComputedValue; } actualPoint = new Point(trueConnectionPoint.Location.X - origin.X, trueConnectionPoint.Location.Y - origin.Y); FormattedText trueMarkerFormattedText = new FormattedText(trueLabelText, new System.Globalization.CultureInfo(textCulture), this.FlowDirection, FlowchartDesigner.FlowElementCaptionTypeface, FlowchartDesigner.FlowNodeCaptionFontSize, new SolidColorBrush(WorkflowDesignerColors.WorkflowViewElementCaptionColor)); actualPoint.Y += ConnectionPoint.DrawingLargeSide / 2; actualPoint.X -= trueMarkerFormattedText.WidthIncludingTrailingWhitespace; DrawtWithTransform( drawingContext, this.isTextRightToLeft, // Mirror the left side text to the right side by using this axis when RTL. actualPoint.X, () => { drawingContext.DrawText(trueMarkerFormattedText, actualPoint); }); } if (falseConnectionPoint != null) { string falseLabelText = String.Empty; VirtualizedContainerService.VirtualizingContainer virtualizingContainer = (VirtualizedContainerService.VirtualizingContainer)falseConnectionPoint.ParentDesigner; if (virtualizingContainer != null && virtualizingContainer.ModelItem != null) { falseLabelText = (string)virtualizingContainer.ModelItem.Properties["FalseLabel"].ComputedValue; } actualPoint = new Point(falseConnectionPoint.Location.X - origin.X, falseConnectionPoint.Location.Y - origin.Y); actualPoint.Y += ConnectionPoint.DrawingLargeSide / 2; FormattedText falseMarkerFormattedText = new FormattedText(falseLabelText, new System.Globalization.CultureInfo(textCulture), this.FlowDirection, FlowchartDesigner.FlowElementCaptionTypeface, FlowchartDesigner.FlowNodeCaptionFontSize, new SolidColorBrush(WorkflowDesignerColors.WorkflowViewElementCaptionColor)); DrawtWithTransform( drawingContext, this.isTextRightToLeft, // Mirror the left side text to the right side by using this axis when RTL. actualPoint.X, () => { drawingContext.DrawText(falseMarkerFormattedText, actualPoint); }); } base.OnRender(drawingContext); }
//For flowchart reacting to ModelItem changes we are concerned of the following scenarios: //1. FlowElements being deleted from the Flowchart.Nodes collection or Flowswitch cases being deleted from ItemsCollection //2. FlowElements being added to the Flowchart.Nodes collection or Flowswitch cases being added from ItemsCollection //3. Properties being changed in FlowStep(Next), FlowDecision(True, false), FlowSwitch(Default) (Any of the flowelemnet should be present in the elements collection). //4. Flowswitch cases being added/remove via Cases.Dicitionary void ModelTreeManager_EditingScopeCompleted(object sender, EditingScopeEventArgs e) { Fx.Assert(this.panel != null, "This code should not be hit if panel is null"); foreach (Change change in e.EditingScope.Changes) { //Case 1, 2. if (change is CollectionChange) { CollectionChange collectionChange = change as CollectionChange; if (collectionChange.Collection.Equals(this.ModelItem.Properties["Nodes"].Collection)) { if (collectionChange.Operation == CollectionChange.OperationType.Delete) { this.DeleteShapeVisual(this.flowNodeToUIElement[collectionChange.Item]); } else { this.AddFlowElementsToDesigner(new List <ModelItem> { collectionChange.Item }); //An editing scope change references the ModelItem. //Hence in case of multiple changes to the same modelItem within the same EditingScope, we will see all the changes on the ModelItem for each change. //Eg. Suppose following two changes are in the same editing scope: 1. Add ModelItem item1 to Collection, 2. Change a property on this MI, item1.Prop1 //In this case, EditingScope.Changes.Count will be 2. //Since an EditingScope change keeps a reference to the ModelItem changed, when we process the first change, the second change would already be reflected on the ModelItem. //Hence, while processing CollectionChange for item1, item1.Prop1 will already reflect the new value. //Also there will be another change notifying the change in item1.Prop1. //AddFlowElementsToDesigner() method, walks through the properties of a newly added item and creates any links if required. //This is necessary for Paste scenario where we want to create links between Items added to the Nodes Collection. //Because of this behavior of AddFlowElementsToDesigner(), before reacting to a property change for adding a link, we will always verify that the link does not already exists. } } if (collectionChange.Collection.Parent != null && collectionChange.Collection.Parent.Parent != null && this.ModelItem.Properties["Nodes"].Collection.Contains(collectionChange.Collection.Parent.Parent) && collectionChange.Collection.Parent.Parent.ItemType.IsGenericType && collectionChange.Collection.Parent.Parent.ItemType.GetGenericTypeDefinition() == typeof(FlowSwitch <>)) { ModelItem item = collectionChange.Item; string caseName = GenericFlowSwitchHelper.GetString(item.Properties["Key"].ComputedValue, item.Properties["Key"].PropertyType); Connector connector = this.GetLinkOnCanvas(collectionChange.Collection.Parent.Parent, item.Properties["Value"].Value, GenericFlowSwitchHelper.FlowSwitchCasesKeyIdentifier + caseName); if (collectionChange.Operation == CollectionChange.OperationType.Delete) { if (connector != null) { this.DeleteLinkVisual(connector); } } else if (collectionChange.Operation == CollectionChange.OperationType.Insert) { if (connector == null) { //Prepending GenericFlowSwitchHelper.FlowSwitchCasesKeyIdentifier to differentiate between the FlowSwitch's Property Default and key Default. connector = this.CreatePropertyLink(collectionChange.Collection.Parent.Parent, item.Properties["Value"].Value, GenericFlowSwitchHelper.FlowSwitchCasesKeyIdentifier + caseName); Fx.Assert(connector != null, "Link not created"); this.panel.Children.Add(connector); } else { RefreshFlowSwitchLinkModelItem(/* flowSwitchModelItem = */ collectionChange.Collection.Parent.Parent, connector, false); } } } } else if (change is DictionaryChange) { // case 4 DictionaryChange dictionaryChange = change as DictionaryChange; if (dictionaryChange.Dictionary.Parent != null && this.ModelItem.Properties["Nodes"].Collection.Contains(dictionaryChange.Dictionary.Parent) && dictionaryChange.Dictionary.Parent.ItemType.IsGenericType && dictionaryChange.Dictionary.Parent.ItemType.GetGenericTypeDefinition() == typeof(FlowSwitch <>)) { ModelItem flowSwitchModelItem = dictionaryChange.Dictionary.Parent; ModelItem caseTargetModelItem = dictionaryChange.Value; string caseName = GenericFlowSwitchHelper.GetString(dictionaryChange.Key == null ? null : dictionaryChange.Key.GetCurrentValue(), dictionaryChange.Key == null ? null : dictionaryChange.Key.ItemType); string caseNameInModelItem = GenericFlowSwitchHelper.FlowSwitchCasesKeyIdentifier + caseName; Connector connector = this.GetLinkOnCanvas( flowSwitchModelItem, caseTargetModelItem, caseNameInModelItem); if (dictionaryChange.Operation == DictionaryChange.OperationType.Delete) { if (connector != null) { this.DeleteLinkVisual(connector); } } else if (dictionaryChange.Operation == DictionaryChange.OperationType.Insert) { if (connector == null) { connector = this.CreatePropertyLink( flowSwitchModelItem, caseTargetModelItem, caseNameInModelItem); this.panel.Children.Add(connector); } } } } //Case 3. else if (change is PropertyChange) { PropertyChange propertyChange = change as PropertyChange; if (this.ModelItem.Properties["Nodes"].Collection.Contains(propertyChange.Owner) || (propertyChange.PropertyName == "StartNode" && propertyChange.Owner == this.ModelItem)) { if (propertyChange.OldValue != null && IsFlowNode(propertyChange.OldValue)) { Connector link = GetLinkOnCanvas(propertyChange.Owner, propertyChange.OldValue, propertyChange.PropertyName); //Debug.Assert(link != null, "Link not found on designer"); if (link != null) { this.DeleteLinkVisual(link); } } if (propertyChange.NewValue != null && IsFlowNode(propertyChange.NewValue)) { Connector oldLink = GetLinkOnCanvas(propertyChange.Owner, propertyChange.NewValue, propertyChange.PropertyName); //If this connector has already been added don't add again. if (oldLink == null) { Connector link = CreatePropertyLink(propertyChange.Owner, propertyChange.NewValue, propertyChange.PropertyName); Fx.Assert(link != null, "Link not created"); this.panel.Children.Add(link); } else { if (GenericFlowSwitchHelper.IsGenericFlowSwitch(propertyChange.Owner.ItemType)) { this.RefreshFlowSwitchLinkModelItem(/* flowSwitchModelItem = */ propertyChange.Owner, oldLink, true); } } } //handling for the case where the FlowStep.Action changes: //Explicitly adding a check for FlowStep, because other FlowNodes have properties of type Activity, which we don't want to react to. //AddFlowElementsToDesigner() will add the links originating out of the shape that is changing. //We have to take care of refreshing the links coming into the shape that is changing. if (typeof(FlowStep).IsAssignableFrom(propertyChange.Owner.ItemType)) { List <Connector> oldIncomingConnectors = new List <Connector>(); if (propertyChange.OldValue != null && IsFlowStepAction(propertyChange.OldValue)) { UIElement oldShape = this.flowNodeToUIElement[propertyChange.Owner]; oldIncomingConnectors = this.GetInComingConnectors(oldShape); this.DeleteShapeVisual(oldShape); } if (propertyChange.NewValue != null && IsFlowStepAction(propertyChange.NewValue)) { this.AddFlowElementsToDesigner(new List <ModelItem> { propertyChange.Owner }); foreach (Connector oldConnector in oldIncomingConnectors) { Connector newConnector = CreateLink(FreeFormPanel.GetSourceConnectionPoint(oldConnector), this.flowNodeToUIElement[propertyChange.Owner], FlowchartDesigner.GetLinkModelItem(oldConnector)); this.panel.Children.Add(newConnector); } } } } } } }