Ejemplo n.º 1
0
        private void DoUpdateNodesAndLinks()
        {
            VerifyAccess();
            this.UpdateNodesAndLinksNeeded = false;

            Diagram observed = this.Observed;

            if (observed == null)
            {
                return;
            }
            PartManager obmgr = observed.PartManager;

            if (obmgr == null)
            {
                return;
            }

            // make sure each Node and Link have the same locations and routes and visibility as those in the Observed diagram
            bool usevis = this.UsesObservedPartVisible;

            if (this.UsesObservedNodeLocation)
            {
                foreach (Node overviewnode in this.Nodes)
                {
                    Node observednode = obmgr.FindNodeForData(overviewnode.Data, this.Model);
                    if (observednode != null)
                    {
                        Point ovloc = overviewnode.Location;
                        Point obloc = observednode.Location;
                        if (!Geo.IsApprox(ovloc, obloc))
                        {
                            overviewnode.Location = obloc;
                        }
                        if (usevis)
                        {
                            overviewnode.Visible = observednode.Visible;
                        }
                    }
                }
            }
            if (this.UsesObservedLinkRoute)
            {
                foreach (Link overviewlink in this.Links)
                {
                    Link observedlink = obmgr.FindLinkForData(overviewlink.Data, this.Model);
                    if (observedlink != null)
                    {
                        overviewlink.Route.Points = observedlink.Route.Points;
                        if (usevis)
                        {
                            overviewlink.Visible = observedlink.Visible;
                        }
                    }
                }
            }
            // afterwards, Node.Location is updated dynamically in Overview.ObservedPanel_PartBoundsChanged
            // and Part.Visible is updated dynamically in Overview.ObservedPanel_PartVisibleChanged
        }
Ejemplo n.º 2
0
 private void Panel_ViewportBoundsChanged(Object sender, RoutedPropertyChangedEventArgs <Rect> e)
 {
     // only call LayoutDiagram when the size of the viewport has changed (in model coordinates),
     // because the panel changed size or because the panel.Scale changed
     if (!Geo.IsApprox(e.OldValue.Width, e.NewValue.Width) || !Geo.IsApprox(e.OldValue.Height, e.NewValue.Height))
     {
         LayoutDiagram();
     }
 }
Ejemplo n.º 3
0
        private void ObservedPanel_PartBoundsChanged(object sender, EventArgs e)
        {
            Diagram observed = this.Observed;

            if (observed == null)
            {
                return;
            }
            // don't let animated movements mess up data via TwoWay data-bindings
            LayoutManager observedlayout = observed.LayoutManager;

            if (observedlayout != null && observedlayout.IsAnimating)
            {
                return;
            }
            PartManager partmgr = this.PartManager;

            if (partmgr == null)
            {
                return;
            }
            Node observednode = sender as Node;

            if (observednode != null && this.UsesObservedNodeLocation)
            {
                // find the corresponding node in this Overview
                Node overviewnode = partmgr.FindNodeForData(observednode.Data, observed.Model);
                if (overviewnode != null)
                {
                    // need to remove any Binding for Node.Location on this node,
                    // in case it is Mode=TwoWay, trying to update the data
                    FrameworkElement ve = overviewnode.EnsuredVisualElement;
                    if (ve != null)
                    {
                        //var be0 = ve.GetBindingExpression(Node.LocationProperty);
                        ve.ClearValue(Node.LocationProperty);
                        //var be1 = ve.GetBindingExpression(Node.LocationProperty);
                        //var locval = ve.ReadLocalValue(Node.LocationProperty);
                        //var val = ve.GetValue(Node.LocationProperty);
                    }
                    // the observed node has moved -- also move this overview's node
                    Point ovloc = overviewnode.Location;
                    Point obloc = observednode.Location;
                    if (!Geo.IsApprox(ovloc, obloc))
                    {
                        overviewnode.Location = obloc;
                    }
                }
            }
            else
            {
                Link observedlink = sender as Link;
                if (observedlink != null && this.UsesObservedLinkRoute)
                {
                    Link overviewlink = partmgr.FindLinkForData(observedlink.Data, observed.Model);
                    if (overviewlink != null)
                    {
                        // the observed link has moved or changed size -- replace this overview's link's route
                        // with that of the observed link's, so it doesn't need to be recomputed
                        //??? doesn't handle case where the points have changed, but the Bounds haven't
                        overviewlink.Route.Points = observedlink.Route.Points;
                    }
                }
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Modify the <see cref="Route"/> of the <see cref="AdornedLink"/> to a new point,
        /// considering also which reshape handle is being dragged and whether the route
        /// is <see cref="Route.Orthogonal"/>.
        /// </summary>
        /// <param name="newPoint"></param>
        /// <remarks>
        /// If the <see cref="Route"/> is <see cref="Route.Orthogonal"/> this
        /// modifies the adjacent points as well in order to keep adjacent segments orthogonal.
        /// For handles that are near either end of the route, the movement may be constrained
        /// to be only vertical or only horizontal, in order to maintain orthogonality.
        /// The decision is based on the value of <see cref="ReshapingBaseTool.GetReshapeBehavior"/>
        /// on the <see cref="ReshapingBaseTool.Handle"/>.
        /// This method is called during a "ReshapeLink" transaction.
        /// </remarks>
        protected virtual void DoReshape(Point newPoint)
        {
            Link            link     = this.AdornedLink;
            Route           route    = link.Route;
            ReshapeBehavior behavior = GetReshapeBehavior(this.Handle);

            if (route.Orthogonal) // need to adjust adjacent points as well
            {
                if (this.HandleIndex == route.FirstPickIndex + 1)
                {
                    int midfirst = route.FirstPickIndex + 1;
                    if (behavior == ReshapeBehavior.Vertical)
                    {
                        // move segment vertically
                        route.SetPoint(midfirst, new Point(route.GetPoint(midfirst - 1).X, newPoint.Y));
                        route.SetPoint(midfirst + 1, new Point(route.GetPoint(midfirst + 2).X, newPoint.Y));
                    }
                    else if (behavior == ReshapeBehavior.Horizontal)
                    {
                        // move segment horizontally
                        route.SetPoint(midfirst, new Point(newPoint.X, route.GetPoint(midfirst - 1).Y));
                        route.SetPoint(midfirst + 1, new Point(newPoint.X, route.GetPoint(midfirst + 2).Y));
                    }
                }
                else if (this.HandleIndex == route.LastPickIndex - 1)
                {
                    int midlast = route.LastPickIndex - 1;
                    if (behavior == ReshapeBehavior.Vertical)
                    {
                        // move segment vertically
                        route.SetPoint(midlast - 1, new Point(route.GetPoint(midlast - 2).X, newPoint.Y));
                        route.SetPoint(midlast, new Point(route.GetPoint(midlast + 1).X, newPoint.Y));
                    }
                    else if (behavior == ReshapeBehavior.Horizontal)
                    {
                        // move segment horizontally
                        route.SetPoint(midlast - 1, new Point(newPoint.X, route.GetPoint(midlast - 2).Y));
                        route.SetPoint(midlast, new Point(newPoint.X, route.GetPoint(midlast + 1).Y));
                    }
                }
                else
                {
                    // can move anywhere, but need to keep adjacent segments orthogonal
                    int   i      = this.HandleIndex;
                    Point oldpt  = route.GetPoint(i);
                    Point before = route.GetPoint(i - 1);
                    Point after  = route.GetPoint(i + 1);
                    if (Geo.IsApprox(before.X, oldpt.X) && Geo.IsApprox(oldpt.Y, after.Y))
                    {
                        route.SetPoint(i - 1, new Point(newPoint.X, before.Y));
                        route.SetPoint(i + 1, new Point(after.X, newPoint.Y));
                    }
                    else if (Geo.IsApprox(before.Y, oldpt.Y) && Geo.IsApprox(oldpt.X, after.X))
                    {
                        route.SetPoint(i - 1, new Point(before.X, newPoint.Y));
                        route.SetPoint(i + 1, new Point(newPoint.X, after.Y));
                    }
                    else if (Geo.IsApprox(before.X, oldpt.X) && Geo.IsApprox(oldpt.X, after.X))
                    {
                        route.SetPoint(i - 1, new Point(newPoint.X, before.Y));
                        route.SetPoint(i + 1, new Point(newPoint.X, after.Y));
                    }
                    else if (Geo.IsApprox(before.Y, oldpt.Y) && Geo.IsApprox(oldpt.Y, after.Y))
                    {
                        route.SetPoint(i - 1, new Point(before.X, newPoint.Y));
                        route.SetPoint(i + 1, new Point(after.X, newPoint.Y));
                    }
                    route.SetPoint(this.HandleIndex, newPoint);
                }
            }
            else // no Orthogonal constraints, just set the new point
            {
                route.SetPoint(this.HandleIndex, newPoint);
            }
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Show an <see cref="Adornment"/> with reshape handles at each of the interesting points of the link's <see cref="Route"/>,
        /// if the link is selected and visible and if <see cref="Northwoods.GoXam.Part.CanReshape"/> is true.
        /// </summary>
        /// <param name="part"></param>
        /// <remarks>
        /// <para>
        /// This produces reshape handles at each point of the route, starting with
        /// <see cref="Northwoods.GoXam.Route.FirstPickIndex"/> and ending with
        /// <see cref="Northwoods.GoXam.Route.LastPickIndex"/>.
        /// Depending on whether <see cref="Northwoods.GoXam.Route.Orthogonal"/> is true,
        /// this will call <see cref="ReshapingBaseTool.SetReshapeBehavior"/> and the <c>Cursor</c> to
        /// limit the directions in which the user may drag the handle.
        /// </para>
        /// <para>
        /// You can change the template used to create each reshape handle by setting <see cref="Link.LinkReshapeHandleTemplate"/>.
        /// If that property is null, this uses a default template produces a small square.
        /// </para>
        /// </remarks>
        public override void UpdateAdornments(Part part)
        {
            Link link = part as Link;

            if (link == null)
            {
                return;          // no Nodes
            }
            Adornment adornment = null;

            if (link.IsSelected)
            {
                FrameworkElement selelt = link.Path;
                if (selelt != null && link.CanReshape() && Part.IsVisibleElement(selelt))
                {
                    adornment = link.GetAdornment(ToolCategory);
                    if (adornment == null)
                    {
                        Route route = link.Route;
                        if (route != null)
                        {
                            IEnumerable <Point> pts = route.Points;
                            int  numpts             = route.PointsCount;
                            bool ortho = route.Orthogonal;
                            if (pts != null && numpts > 2)
                            {
                                // LinkReshapeHandleTemplate: for each reshape handle, not for whole adornment
                                DataTemplate template = link.LinkReshapeHandleTemplate;
                                if (template == null)
                                {
                                    template = Diagram.FindDefault <DataTemplate>("DefaultLinkReshapeHandleTemplate");
                                }

                                LinkPanel panel      = new LinkPanel();
                                int       firstindex = route.FirstPickIndex;
                                int       lastindex  = route.LastPickIndex;
                                // don't bother creating handles for firstindex or lastindex
                                for (int i = firstindex + 1; i <= lastindex - 1; i++)
                                {
                                    // expand the DataTemplate to make a copy of a reshape handle
                                    FrameworkElement h = template.LoadContent() as FrameworkElement;
                                    // needs to be a FrameworkElement so we can set its Cursor
                                    if (h == null)
                                    {
                                        continue;
                                    }
                                    // identify this particular handle within the LinkPanel
                                    LinkPanel.SetIndex(h, i);
                                    // now determines its reshape behavior and cursor, depending on whether Orthogonal et al.
                                    if (i == firstindex)
                                    {
                                        // default ReshapeBehavior.None
                                    }
                                    else if (i == firstindex + 1 && ortho)
                                    {
                                        Point a = route.GetPoint(firstindex);
                                        Point b = route.GetPoint(firstindex + 1);
                                        if (Geo.IsApprox(a.X, b.X))
                                        {
                                            SetReshapeBehavior(h, ReshapeBehavior.Vertical);
                                            h.Cursor = Part.SizeNSCursor;
                                        }
                                        else if (Geo.IsApprox(a.Y, b.Y))
                                        {
                                            SetReshapeBehavior(h, ReshapeBehavior.Horizontal);
                                            h.Cursor = Part.SizeWECursor;
                                        }
                                    }
                                    else if (i == lastindex - 1 && ortho)
                                    {
                                        Point a = route.GetPoint(lastindex - 1);
                                        Point b = route.GetPoint(lastindex);
                                        if (Geo.IsApprox(a.X, b.X))
                                        {
                                            SetReshapeBehavior(h, ReshapeBehavior.Vertical);
                                            h.Cursor = Part.SizeNSCursor;
                                        }
                                        else if (Geo.IsApprox(a.Y, b.Y))
                                        {
                                            SetReshapeBehavior(h, ReshapeBehavior.Horizontal);
                                            h.Cursor = Part.SizeWECursor;
                                        }
                                    }
                                    else if (i == lastindex)
                                    {
                                        // default ReshapeBehavior.None
                                    }
                                    else
                                    {
                                        SetReshapeBehavior(h, ReshapeBehavior.All);
                                        h.Cursor = Part.SizeAllCursor;
                                    }
                                    panel.Children.Add(h);
                                }
                                adornment = new Adornment(); // for LinkReshapingTool.UpdateAdornments
                                adornment.AdornedElement = selelt;
                                adornment.Category       = ToolCategory;
                                adornment.Content        = panel; // just provide the FrameworkElement as the Content and as the Visual Child
                                adornment.LocationSpot   = Spot.TopLeft;
                            }
                        }
                    }
                    if (adornment != null)
                    {
                        Point loc = link.GetElementPoint(selelt, Spot.TopLeft);
                        adornment.Location      = loc;
                        adornment.RotationAngle = link.GetAngle(selelt);
                        adornment.Remeasure();
                    }
                }
            }
            link.SetAdornment(ToolCategory, adornment);
        }