/// <summary> /// Start reshaping. /// </summary> /// <remarks> /// This sets the <see cref="ReshapingBaseTool.Handle"/> to the result of <see cref="DiagramTool.FindToolHandleAt"/>; /// if it is null, this method does not actually activate this tool. /// If there is a reshape handle, /// this sets <see cref="ReshapingBaseTool.AdornedElement"/> and <see cref="HandleIndex"/>, /// remembers the <see cref="OriginalPoint"/>, /// starts a transaction (<see cref="DiagramTool.StartTransaction"/>), /// and sets <see cref="DiagramTool.Active"/> to true. /// </remarks> public override void DoActivate() { Diagram diagram = this.Diagram; if (diagram == null) { return; } this.Handle = FindToolHandleAt(diagram.FirstMousePointInModel, ToolCategory); if (this.Handle == null) { return; } this.AdornedElement = FindAdornedElement(this.Handle); this.HandleIndex = LinkPanel.GetIndex(this.Handle); Link link = this.AdornedLink; // this should be non-null, checked by FindReshapeHandle this.OriginalPoint = link.Route.GetPoint(this.HandleIndex); this.OriginalPoints = link.Route.Points.ToList(); StartTransaction(ToolCategory); // make sure a CurrentEdit exists; otherwise no model changes during the transaction // causes the transaction to be thrown away, which means any "UpdateDelayedRoutes" transaction // won't have a committed transaction to coalesce. var umgr = diagram.Model.UndoManager; if (umgr != null) { umgr.CurrentEdit = new Northwoods.GoXam.Model.UndoManager.CompoundEdit(); } this.Active = true; }
public override void DoCancel() { if (this.Label != null) { LinkPanel.SetOffset(this.Label, this.OriginalOffset); } base.DoCancel(); }
public override object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { if (value == null) { return(null); } return(LinkPanel.IsFilled((Arrowhead)value) ? new SolidColorBrush(Colors.LightGray) : null); }
public override void DoActivate() { StartTransaction("Shifted Label"); this.Label = FindLabel(); if (this.Label != null) { this.OriginalOffset = LinkPanel.GetOffset(this.Label); } base.DoActivate(); }
private FrameworkElement FindLabel() { #if SILVERLIGHT var elt = this.Diagram.Panel.FindElementAt <UIElement>(this.Diagram.LastMousePointInModel, e => e, null, SearchLayers.Links); if (elt == null) { return(null); } Link link = Part.FindAncestor <Link>(elt); if (link == null) { return(null); } var parent = System.Windows.Media.VisualTreeHelper.GetParent(elt) as UIElement; while (parent != null && parent != link && !(parent is LinkPanel)) { elt = parent; parent = System.Windows.Media.VisualTreeHelper.GetParent(elt) as UIElement; } #else var elt = this.Diagram.Panel.FindElementAt <System.Windows.Media.Visual>(this.Diagram.LastMousePointInModel, e => e, null, SearchLayers.Links); if (elt == null) { return(null); } Link link = Part.FindAncestor <Link>(elt); if (link == null) { return(null); } var parent = System.Windows.Media.VisualTreeHelper.GetParent(elt) as System.Windows.Media.Visual; while (parent != null && parent != link && !(parent is LinkPanel)) { elt = parent; parent = System.Windows.Media.VisualTreeHelper.GetParent(elt) as System.Windows.Media.Visual; } #endif if (parent is LinkPanel) { FrameworkElement lab = elt as FrameworkElement; if (lab == null) { return(null); } // needs to be positioned relative to the MidPoint if (LinkPanel.GetIndex(lab) != Int32.MinValue) { return(null); } // also check for movable-ness? return(lab); } return(null); }
private void UpdateLinkPanelProperties() { if (this.Label == null) { return; } Link link = Part.FindAncestor <Link>(this.Label); if (link == null) { return; } Point last = this.Diagram.LastMousePointInModel; Point mid = link.Route.MidPoint; // need to rotate this point to account for angle of middle segment Point p = new Point(last.X - mid.X, last.Y - mid.Y); LinkPanel.SetOffset(this.Label, RotatePoint(p, -link.Route.MidAngle)); }
/// <summary> /// Start reshaping. /// </summary> /// <remarks> /// This sets the <see cref="ReshapingBaseTool.Handle"/> to the result of <see cref="DiagramTool.FindToolHandleAt"/>; /// if it is null, this method does not actually activate this tool. /// If there is a reshape handle, /// this sets <see cref="ReshapingBaseTool.AdornedElement"/> and <see cref="HandleIndex"/>, /// remembers the <see cref="OriginalPoint"/>, /// starts a transaction (<see cref="DiagramTool.StartTransaction"/>), /// and sets <see cref="DiagramTool.Active"/> to true. /// </remarks> public override void DoActivate() { Diagram diagram = this.Diagram; if (diagram == null) { return; } this.Handle = FindToolHandleAt(diagram.FirstMousePointInModel, ToolCategory); if (this.Handle == null) { return; } this.AdornedElement = FindAdornedElement(this.Handle); this.HandleIndex = LinkPanel.GetIndex(this.Handle); Link link = this.AdornedLink; // this should be non-null, checked by FindReshapeHandle this.OriginalPoint = link.Route.GetPoint(this.HandleIndex); this.OriginalPoints = link.Route.Points.ToList(); StartTransaction("Reshape"); this.Active = true; }
/// <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); }
private void DoReshape(Point newPoint) { switch (GetReshapeBehavior(this.Handle)) { case ReshapeBehavior.Horizontal: newPoint.X = Math.Floor(newPoint.X / 4 + 0.5) * 4; break; case ReshapeBehavior.Vertical: newPoint.Y = Math.Floor(newPoint.Y / 4 + 0.5) * 4; break; default: break; } Link link = this.AdornedLink; int idx = LinkPanel.GetIndex(this.Handle); Rect portb; if (idx == 0) { portb = link.FromNode.GetElementBounds(link.FromPort); } else { portb = link.ToNode.GetElementBounds(link.ToPort); } if (portb.Width < 1 || portb.Height < 1) { return; } Point ctr = Spot.Center.PointInRect(portb); double x = (newPoint.X - portb.Left) / portb.Width; double y = (newPoint.Y - portb.Top) / portb.Height; x = Math.Max(0, Math.Min(x, 1)); y = Math.Max(0, Math.Min(y, 1)); switch (GetReshapeBehavior(this.Handle)) { case ReshapeBehavior.Horizontal: y = newPoint.Y < ctr.Y ? 0 : 1; break; case ReshapeBehavior.Vertical: x = newPoint.X < ctr.X ? 0 : 1; break; default: break; } Route route = link.Route; if (idx == 0) { route.FromSpot = new Spot(x, y); } else { route.ToSpot = new Spot(x, y); } }
/// <summary> /// Show an <see cref="Adornment"/> with <see cref="ToolHandle"/>s at each end of the link's route, /// if the link is selected and visible. /// </summary> /// <param name="part"></param> /// <remarks> /// </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 && Part.IsVisibleElement(selelt)) { adornment = link.GetAdornment(ToolCategory); if (adornment == null) { Route route = link.Route; if (route != null) { IList <Point> pts = route.Points; int numpts = route.PointsCount; if (pts != null && numpts > 2) { // This tool's Adornments consists of a LinkPanel containing two ToolHandles. LinkPanel panel = new LinkPanel(); #if SILVERLIGHT var h = new System.Windows.Shapes.Path(); #else var h = new ToolHandle(); #endif // of course you can customize the appearance of the shift handles here... NodePanel.SetFigure(h, NodeFigure.Rectangle); h.Width = 6; h.Height = 6; h.Fill = new SolidColorBrush(Colors.Orange); LinkPanel.SetIndex(h, 0); LinkPanel.SetFraction(h, 0.5); if (pts[0].X == pts[1].X && pts[0].Y != pts[1].Y) { SetReshapeBehavior(h, ReshapeBehavior.Horizontal); h.Cursor = System.Windows.Input.Cursors.SizeWE; } else if (pts[0].Y == pts[1].Y && pts[0].X != pts[1].X) { SetReshapeBehavior(h, ReshapeBehavior.Vertical); h.Cursor = System.Windows.Input.Cursors.SizeNS; } else { SetReshapeBehavior(h, ReshapeBehavior.All); #if !SILVERLIGHT h.Cursor = System.Windows.Input.Cursors.SizeAll; #endif } panel.Children.Add(h); #if SILVERLIGHT h = new System.Windows.Shapes.Path(); #else h = new ToolHandle(); #endif NodePanel.SetFigure(h, NodeFigure.Rectangle); h.Width = 6; h.Height = 6; h.Fill = new SolidColorBrush(Colors.Orange); LinkPanel.SetIndex(h, -1); LinkPanel.SetFraction(h, 0.5); SetReshapeBehavior(h, ReshapeBehavior.All); if (pts[numpts - 1].X == pts[numpts - 2].X && pts[numpts - 1].Y != pts[numpts - 2].Y) { SetReshapeBehavior(h, ReshapeBehavior.Horizontal); h.Cursor = System.Windows.Input.Cursors.SizeWE; } else if (pts[numpts - 1].Y == pts[numpts - 2].Y && pts[numpts - 1].X != pts[numpts - 2].X) { SetReshapeBehavior(h, ReshapeBehavior.Vertical); h.Cursor = System.Windows.Input.Cursors.SizeNS; } else { SetReshapeBehavior(h, ReshapeBehavior.All); #if !SILVERLIGHT h.Cursor = System.Windows.Input.Cursors.SizeAll; #endif } panel.Children.Add(h); adornment = new Adornment(); 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); }
/// <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); }
public override object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return(LinkPanel.IsFilled((Arrowhead)value) ? this.Fill : null); }