public StateContainerEditor()
        {
            InitializeComponent();
            this.modelItemToUIElement = new Dictionary<ModelItem, UIElement>();
            this.shapeLocations = new HashSet<Point>();
            this.listenedTransitionCollections = new HashSet<ModelItem>();
            this.transitionModelItemsAdded = new List<ModelItem>();
            this.transitionModelItemsRemoved = new List<ModelItem>();

            Binding readOnlyBinding = new Binding();
            readOnlyBinding.RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(DesignerView), 1);
            readOnlyBinding.Path = new PropertyPath(DesignerView.IsReadOnlyProperty);
            readOnlyBinding.Mode = BindingMode.OneWay;
            this.SetBinding(IsReadOnlyProperty, readOnlyBinding);

            this.Loaded += (s, e) =>
            {
                if (this.ShouldInitialize())
                {
                    WorkflowViewElement parent = VisualTreeUtils.FindVisualAncestor<WorkflowViewElement>(this);
                    this.ModelItem = parent.ModelItem;
                    this.StateMachineModelItem = StateContainerEditor.GetStateMachineModelItem(this.ModelItem);
                    this.Context = parent.Context;
                    this.compositeViewEvents = parent;
                    if (this.compositeViewEvents != null)
                    {
                        this.compositeViewEvents.RegisterDefaultCompositeView(this);
                    }
                    if (!this.populated)
                    {
                        this.Populate();
                        Selection.Subscribe(this.Context, this.OnSelectionChangedCallback);
                        this.populated = true;
                    }
                }
            };

            this.Unloaded += (s, e) =>
            {
                if (this.compositeViewEvents != null)
                {
                    (compositeViewEvents).UnregisterDefaultCompositeView(this);
                    this.compositeViewEvents = null;
                }
                if (this.populated)
                {
                    this.Cleanup();
                    Selection.Unsubscribe(this.Context, this.OnSelectionChangedCallback);
                    this.populated = false;
                }

                this.StateMachineModelItem = null;

                this.activeSrcConnectionPoint = null;
                this.activeDestConnectionPointForAutoSplit = null;
                this.activeSrcConnectionPointForAutoSplit = null;

                // selectedConnector is a placeholder for the last connector selected.
                this.selectedConnector = null;

                // Used for connector creation
                this.lastConnectionPointMouseUpElement = null;
                this.activeConnectionPointsAdorner = null;
                this.activeConnectionPoint = null;
                this.initialNode = null;
                // The ModelItem for the initial node
                this.initialModelItem = null;

                BindingOperations.ClearBinding(this, IsReadOnlyProperty);
            };
        }
        void AddConnectionPointsAdorner(UIElement element)
        {
            bool isSelected = false;
            if (element is VirtualizedContainerService.VirtualizingContainer)
            {
                isSelected = (((Selection)this.Context.Items.GetValue<Selection>()).SelectedObjects as ICollection<ModelItem>).Contains(((VirtualizedContainerService.VirtualizingContainer)element).ModelItem);
            }
            ConnectionPointsAdorner connectionPointsAdorner = new StateMachineConnectionPointsAdorner(element, ConnectionPointsToShow(element), isSelected);
            if ((element is VirtualizedContainerService.VirtualizingContainer) && ((VirtualizedContainerService.VirtualizingContainer)element).ModelItem.ItemType == typeof(State))
            {
                connectionPointsAdorner.ToolTip = SR.TransitionConnectionPointTooltip;
            }
            else if (element is StartSymbol)
            {
                connectionPointsAdorner.ToolTip = SR.InitialStateConnectionPointTooltip;
            }

            AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(element);
            Fx.Assert(adornerLayer != null, "Cannot get AdornerLayer.");
            adornerLayer.Add(connectionPointsAdorner);
            // The outmostEditor should handle all the connection point related events for all its descendants
            StateContainerEditor stateMachineContainer = this.GetStateMachineContainerEditor();
            connectionPointsAdorner.MouseDown += new MouseButtonEventHandler(stateMachineContainer.OnConnectionPointMouseDown);
            connectionPointsAdorner.MouseUp += new MouseButtonEventHandler(stateMachineContainer.OnConnectionPointMouseUp);
            connectionPointsAdorner.MouseLeave += new MouseEventHandler(stateMachineContainer.OnConnectionPointMouseLeave);

            this.activeConnectionPointsAdorner = connectionPointsAdorner;
        }
 private void RemoveConnectionPointsAdorner(UIElement adornedElement)
 {
     IEnumerable<Adorner> adornersRemoved = RemoveAdorner(adornedElement, typeof(ConnectionPointsAdorner));
     Fx.Assert(adornersRemoved.Count() <= 1, "There should be at most one ConnectionPointsAdorner");
     if (adornersRemoved.Count() == 1)
     {
         ConnectionPointsAdorner adorner = (ConnectionPointsAdorner)adornersRemoved.First();
         Fx.Assert(object.Equals(this.activeConnectionPointsAdorner, adorner), "The adorner removed should be the same as the active adorner.");
         this.activeConnectionPointsAdorner = null;
         foreach (ConnectionPoint connectionPoint in adorner.ConnectionPoints)
         {
             connectionPoint.IsEnabled = false;
             if (object.Equals(this.activeConnectionPoint, connectionPoint))
             {
                 this.activeConnectionPoint = null;
             }
         }
     }
 }
 internal static ConnectionPoint ConnectionPointHitTest(Point hitPoint, ConnectionPointsAdorner adorner)
 {
     FreeFormPanel panel = VisualTreeUtils.FindVisualAncestor<FreeFormPanel>(adorner.AdornedElement);
     return ConnectionPointHitTest(hitPoint, adorner.ConnectionPoints, panel);
 }
        internal static ConnectionPoint ConnectionPointHitTest(Point hitPoint, ConnectionPointsAdorner adorner)
        {
            FreeFormPanel panel = VisualTreeUtils.FindVisualAncestor <FreeFormPanel>(adorner.AdornedElement);

            return(ConnectionPointHitTest(hitPoint, adorner.ConnectionPoints, panel));
        }
Example #6
0
        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.");
        }