private void Button_Click_1(object sender, RoutedEventArgs e) { var button = sender as Button; var border = button.Parent as Border; Adornment.SetVisibility(border, Adornment.GetVisibility(border) == Visibility.Visible ? Visibility.Collapsed : Visibility.Visible); }
// Used when a node is created by right clicking private void CreateChild(object sender, RoutedEventArgs e) { FrameworkElement elt = myDiagram.Panel.FindElementAt <FrameworkElement>(myDiagram.LastMousePointInModel, x => x as FrameworkElement, x => true, SearchLayers.Nodes); Node n = null; if (e.OriginalSource is Button) { Adornment ad = Part.FindAncestor <Adornment>(e.OriginalSource as UIElement); if (ad == null) { return; } n = ad.AdornedPart as Node; } else { n = Part.FindAncestor <Node>(elt); } if (n != null && ((MindMapData)n.Data).Key != "/") { // always make changes within a transaction myDiagram.StartTransaction("CreateNode"); MindMapData childdata = new MindMapData(); MindMapData parentdata = (MindMapData)n.Data; childdata.Location = new Point(parentdata.Location.X, parentdata.Location.Y); childdata.Key = parentdata.Key + "/"; SetUpChild(childdata, parentdata); myDiagram.Model.AddNode(childdata); myDiagram.CommitTransaction("CreateNode"); } }
public Style(Color foreColor, Color backColor, Color adornmentColor, Adornment adornment, FontStyle fontStyle) { ForeColor = foreColor; BackColor = backColor; AdornmentColor = adornmentColor; Adornment = adornment; FontStyle = fontStyle; }
/// <summary> /// Given a handle element in an adornment, return its adornment's <see cref="Adornment.AdornedPart"/>. /// </summary> /// <param name="handle">a <c>FrameworkElement</c></param> /// <returns>a <see cref="Part"/> that is not an adornment</returns> protected Part FindAdornedPart(FrameworkElement handle) { Adornment ad = FindAdornment(handle); if (ad != null) { return(ad.AdornedPart); } return(null); }
/// <summary> /// Show an <see cref="Adornment"/> with resize handles at points along the edge of bounds of the <see cref="AdornedElement"/>, /// if the node is selected and visible and if <see cref="Northwoods.GoXam.Part.CanResize"/> is true. /// </summary> /// <param name="part"></param> /// <remarks> /// <para> /// First this finds the element in the visual tree of the <paramref name="part"/> that should /// get the resize adornment and that the user will be able to resize interactively. /// It finds the element that has the <see cref="Part.ResizeElementName"/> property of the part. /// If the <see cref="Part.ResizeElementName"/> property is null, as it is by default, it uses /// the part's <see cref="Part.SelectionElement"/>. /// </para> /// <para> /// It then constructs the adornment template, associating it with the chosen resize element. /// </para> /// <para> /// You can change the template used to create the adornment by setting <see cref="Part.ResizeAdornmentTemplate"/>. /// If that property is null, this uses a default template with eight resize handles /// at the four corners and at the middles of the four sides. /// </para> /// <para> /// This only gives a resize adornment to <see cref="Node"/>s, not to <see cref="Link"/>s. /// </para> /// </remarks> public override void UpdateAdornments(Part part) { if (part == null || part is Link) { return; // can't resize links } Adornment adornment = null; if (part.IsSelected) { FrameworkElement selelt = null; String eltname = part.ResizeElementName; if (eltname != null) { selelt = part.FindNamedDescendant(eltname); } if (selelt == null) { selelt = part.SelectionElement; } if (selelt != null && part.CanResize() && Part.IsVisibleElement(selelt)) { adornment = part.GetAdornment(ToolCategory); if (adornment == null) { DataTemplate template = part.ResizeAdornmentTemplate; if (template == null) { template = Diagram.FindDefault <DataTemplate>("DefaultResizeAdornmentTemplate"); } adornment = part.MakeAdornment(selelt, template); if (adornment != null) { adornment.Category = ToolCategory; adornment.LocationSpot = Spot.TopLeft; } } if (adornment != null) { Node node = (Node)part; Point loc = part.GetElementPoint(selelt, Spot.TopLeft); // use the node's angle, not part.GetAngle(selelt) //?? this can be wrong if there are additional rotational transforms in the tree double angle = node.RotationAngle; UpdateResizeHandles(adornment.VisualElement, angle); adornment.Location = loc; adornment.RotationAngle = angle; adornment.Remeasure(); } } } part.SetAdornment(ToolCategory, adornment); }
public void Destroy() { Prefab = null; if (_visual != null) { Object.Destroy(_visual); _visual = null; } _adornment?.Destroy(); _adornment = null; }
public override int GetHashCode() { unchecked { int hash = 17; hash = hash * 23 + ForeColor.GetHashCode(); hash = hash * 23 + BackColor.GetHashCode(); hash = hash * 23 + AdornmentColor.GetHashCode(); hash = hash * 23 + Adornment.GetHashCode(); hash = hash * 23 + FontStyle.GetHashCode(); return(hash); } }
public void Instantiate(GameObject prefab, GameObject prefabAdornment, Vector3 position, Transform parent, TileAnimParams animParams) { Prefab = prefab; if (Prefab != null) { _visual = UnityEngine.Object.Instantiate(Prefab, Vector3.zero, Quaternion.identity); _visual.transform.SetParent(parent, false); _visual.transform.position = position; } if (prefabAdornment != null) { _adornment = new Adornment(); _adornment.Instantiate(prefabAdornment, parent, animParams.easeType, animParams.animTime); _adornment.UpdatePosition(position); } }
/// <summary> /// Show an <see cref="Adornment"/> with resize handles at points along the edge of bounds of the <see cref="AdornedElement"/>, /// if the node is selected and visible and if <see cref="Northwoods.GoXam.Part.CanResize"/> is true. /// </summary> /// <param name="part"></param> /// <remarks> /// You can change the template used to create the adornment by setting <see cref="Part.ResizeAdornmentTemplate"/>. /// If that property is null, this uses a default template with eight resize handles /// at the four corners and at the middles of the four sides. /// </remarks> public override void UpdateAdornments(Part part) { if (part == null || part is Link) { return; // can't resize links } Adornment adornment = null; if (part.IsSelected) { FrameworkElement selelt = part.SelectionElement; if (selelt != null && part.CanResize() && Part.IsVisibleElement(selelt)) { adornment = part.GetAdornment(ToolCategory); if (adornment == null) { DataTemplate template = part.ResizeAdornmentTemplate; if (template == null) { template = Diagram.FindDefault <DataTemplate>("DefaultResizeAdornmentTemplate"); } adornment = part.MakeAdornment(selelt, template); if (adornment != null) { adornment.Category = ToolCategory; adornment.LocationSpot = Spot.TopLeft; } } if (adornment != null) { Point loc = part.GetElementPoint(selelt, Spot.TopLeft); double angle = part.GetAngle(selelt); UpdateResizeHandles(adornment.VisualElement, angle); adornment.Location = loc; adornment.RotationAngle = angle; adornment.Remeasure(); } } } part.SetAdornment(ToolCategory, adornment); }
// This event handler is called from the Button that is in the Adornment // shown for a node when it is selected private void Button_Click(object sender, System.Windows.RoutedEventArgs e) { // find the Adornment "parent" for the Button Adornment ad = Part.FindAncestor <Adornment>(e.OriginalSource as UIElement); if (ad == null) { return; } // its AdornedPart should be a Node that is bound to a State object State from = ad.AdornedPart.Data as State; if (from == null) { return; } // make all changes to the model within a transaction myDiagram.StartTransaction("Add State"); // create a new State, add it to the model, and create a link from // the selected node data to the new node data State to = new State(); to.Text = "new"; Point p = from.Location; //?? this isn't a very smart way to decide where to place the node to.Location = new Point(p.X + 200, p.Y); myDiagram.Model.AddNode(to); Node newnode = myDiagram.PartManager.FindNodeForData(to, myDiagram.Model); myDiagram.Select(newnode); EventHandler <DiagramEventArgs> show = null; show = (snd, evt) => { myDiagram.Panel.MakeVisible(newnode, Rect.Empty); myDiagram.LayoutCompleted -= show; }; myDiagram.LayoutCompleted += show; myDiagram.Model.AddLink(from, null, to, null); myDiagram.CommitTransaction("Add State"); }
/// <summary> /// Find an element at the given point that is a tool handle. /// </summary> /// <param name="p">a <c>Point</c> in model coordinates</param> /// <param name="category">the handle's <see cref="Adornment"/>'s <see cref="Part.Category"/></param> /// <returns></returns> /// <remarks> /// A tool handle is an element that is part of an <see cref="Adornment"/> that is used by a tool. /// Typically it is a <c>ToolHandle</c> in WPF or a <c>Path</c> in Silverlight, /// but may be any FrameworkElement with the <c>go:NodePanel.Figure</c> attached property set to value other than <c>None</c>. /// This method checks that the adornment's <see cref="Part.Category"/> matches the given <paramref name="category"/>. /// </remarks> protected virtual FrameworkElement FindToolHandleAt(Point p, String category) { Diagram diagram = this.Diagram; if (diagram == null) { return(null); } FrameworkElement handle = diagram.Panel.FindElementAt <FrameworkElement>(p, FindToolHandle, x => true, SearchLayers.Temporary | SearchLayers.Nodes); if (handle != null) { Adornment ad = FindAdornment(handle); if (ad == null || ad.Category != category) { return(null); } return(handle); } return(null); }
/// <summary> /// Show an <see cref="Adornment"/> with a rotate handle at a point to the side of the <see cref="AdornedElement"/>, /// if the node is selected and visible and if <see cref="Northwoods.GoXam.Part.CanRotate"/> is true. /// </summary> /// <param name="part"></param> /// <remarks> /// You can change the template used to create the adornment by setting <see cref="Part.RotateAdornmentTemplate"/>. /// If that property is null, this uses a default template that produces a small circle. /// </remarks> public override void UpdateAdornments(Part part) { if (part == null || part is Link) { return; // this tool never applies to Links } Adornment adornment = null; if (part.IsSelected) { FrameworkElement selelt = part.SelectionElement; if (selelt != null && part.CanRotate() && Part.IsVisibleElement(selelt)) { adornment = part.GetAdornment(ToolCategory); if (adornment == null) { DataTemplate template = part.RotateAdornmentTemplate; if (template == null) { template = Diagram.FindDefault <DataTemplate>("DefaultRotateAdornmentTemplate"); } adornment = part.MakeAdornment(selelt, template); if (adornment != null) { adornment.Category = ToolCategory; adornment.LocationSpot = Spot.Center; } } if (adornment != null) { Rect rect = part.GetElementBounds(part.VisualElement); //?? outside whole node Point center = Spot.Center.PointInRect(rect); double angle = part.GetAngle(selelt); adornment.Location = Geo.RotatePoint(new Point(rect.Right + 30, center.Y), center, angle); //?? fixed distance } } } part.SetAdornment(ToolCategory, adornment); }
private void LayoutBox(TextBox box) { if (box == null) { return; } TextEditingTool tool = this.TextEditingTool; if (tool == null) { return; } TextBlock block = tool.TextBlock; if (block == null) { return; } Adornment edad = tool.EditorAdornment; if (edad == null) { return; } Thickness thick = box.BorderThickness; Thickness pad = box.Padding; if (block.TextWrapping != TextWrapping.NoWrap) { double w = MeasureWrappedTextWidth(box.Text, box, block); Size es = edad.GetEffectiveSize(block); double ww = Math.Max(w, es.Width); // at least existing width box.MaxWidth = ww + thick.Left + thick.Right + pad.Left + pad.Right + 6; //??? hard-coded sizes //Diagram.Debug(Diagram.Str(ds) + Diagram.Str(es) + " ww: " + Diagram.Str(ww) + " maxw: " + Diagram.Str(box.MaxWidth)); } edad.Remeasure(); }
public override void UpdateAdornments(Part part) { if (part == null || part is Link) { return; // this tool never applies to Links } Adornment adornment = null; if (part.IsSelected) { FrameworkElement selelt = part.SelectionElement; if (selelt != null && part.CanRotate() && Part.IsVisibleElement(selelt)) { adornment = part.GetAdornment(ToolCategory); if (adornment == null) { DataTemplate template = part.RotateAdornmentTemplate; if (template == null) { template = Diagram.FindDefault <DataTemplate>("DefaultRotateAdornmentTemplate"); } adornment = part.MakeAdornment(selelt, template); if (adornment != null) { adornment.Category = ToolCategory; adornment.LocationSpot = Spot.Center; } } if (adornment != null) { adornment.Location = part.GetElementPoint(selelt, new Spot(0.5, 0, 0, -30)); // above middle top } } } part.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); }
/// <summary> /// Start editing the text for a <see cref="TextBlock"/>. /// </summary> /// <remarks> /// <para> /// If <see cref="TextBlock"/> is not already specified, this looks for one at the current /// mouse point. If none is found, this method does nothing. /// </para> /// <para> /// This method then creates an <see cref="Adornment"/> using the <see cref="Part.GetTextEditAdornmentTemplate"/>, /// or a default data template that displays a <c>TextBox</c>. /// The adornment is remembered as the <see cref="EditorAdornment"/> property. /// </para> /// <para> /// Then this method finds an <see cref="ITextEditor"/> to manage the <see cref="EditorAdornment"/>. /// If the root visual element of the adornment template implements <see cref="ITextEditor"/>, /// it uses that. /// Otherwise it uses <see cref="Part.GetTextEditor"/> on the <c>TextBlock</c>. /// Finally, by default it uses one that understands <c>TextBox</c>es, which matches the /// implementation of the default TextEditAdornmentTemplate. /// </para> /// <para> /// This also calls <see cref="DiagramTool.StartTransaction"/> /// and sets <see cref="DiagramTool.Active"/> to true. /// You should call <see cref="AcceptText"/> if you want to finish the edit /// by modifying the <see cref="TextBlock"/> and committing the edit transaction. /// Or call <see cref="DiagramTool.DoCancel"/> if you want to abort the edit. /// </para> /// </remarks> public override void DoActivate() { Diagram diagram = this.Diagram; if (diagram == null) { return; } // there should be a TextBlock; find it if not given if (this.TextBlock == null) { this.TextBlock = diagram.Panel.FindElementAt <TextBlock>(diagram.LastMousePointInModel, Diagram.FindAncestorOrSelf <TextBlock>, x => true, SearchLayers.Parts); } if (this.TextBlock == null) { return; } //if (!Part.GetTextEditable(this.TextBlock)) return; //?? able to operate on all TextBlocks Part part = this.AdornedPart; if (part == null) { return; //?? don't check for IsSelected here, just in CanStart? } // make an EditorAdornment Adornment adornment = part.GetAdornment(ToolCategory); if (adornment == null) { DataTemplate template = Part.GetTextEditAdornmentTemplate(this.TextBlock); if (template == null) { template = Diagram.FindDefault <DataTemplate>("DefaultTextEditAdornmentTemplate"); } adornment = part.MakeAdornment(this.TextBlock, template); if (adornment != null) { adornment.Category = ToolCategory; adornment.LocationSpot = Spot.TopLeft; } } this.EditorAdornment = adornment; part.SetAdornment(ToolCategory, adornment); // start editing if (adornment != null) { this.Active = true; this.State = TextEditingState.Active; StartTransaction(ToolCategory); // make sure there's a TextEditor // If the adornment's root element is a UserControl that implements ITextEditor, use it ITextEditor editor = adornment.VisualElement as ITextEditor; if (editor != null) { this.TextEditor = editor; } // otherwise look on the part itself if (this.TextEditor == null) { this.TextEditor = Part.GetTextEditor(this.TextBlock); } if (this.TextEditor == null) { // this matches up with the default TextEditAdornmentTemplate, which creates a TextBox this.TextEditor = new TextBoxEditor(); } this.TextEditor.GotFocus += HandleFocus; // default location Point loc = this.AdornedPart.GetElementPoint(this.TextBlock, Spot.TopLeft); adornment.Location = loc; // setting the TextEditingTool should initialize its Text value and assign focus this.TextEditor.TextEditingTool = this; } }
/// <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); }
public static string ToDescriptionString(this Adornment val) { var attributes = (DescriptionAttribute[])val.GetType().GetField(val.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false); return(attributes.Length > 0 ? attributes[0].Description : string.Empty); }
/// <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); }