// walk the visual tree of adornment elements private void RenderHandles(FrameworkElement elt) { if (elt == null) { return; } Path path = elt as Path; if (path != null) // if it's a Path // and if NodePanel.Figure is specified and is None, it's a SelectionHandle equivalent { NodeFigure fig = NodePanel.GetFigure(elt); if (fig == NodeFigure.None) // must explicitly set go:NodePanel.Figure="None", to distinguish this selection handle from random Path shapes { Shape adornedshape = this.AdornedElement as Shape; // hack: because GetSelectionGeometry doesn't always return a Geometry of the AdornedElement's size if (adornedshape != null && this.AdornedPart is Node && ((adornedshape is Path && NodePanel.GetFigure(adornedshape) != NodeFigure.None) || // when that Path is a NodeShape equivalent adornedshape is Polygon || adornedshape is Polyline)) // or is a Polygon or Polyline { path.Stretch = Stretch.Fill; Size sz = GetEffectiveSize(adornedshape); // can't just use ActualWidth/Height, because measuring has reset them to zero path.Width = sz.Width; path.Height = sz.Height; } path.Data = GetSelectionGeometry(path, this); } else // otherwise assume it's a ToolHandle equivalent { if (path.Data == null) { path.Stretch = Stretch.Fill; path.Data = GetFigureGeometry(path); // returns a Geometry with points from 0,0 to 1,1 } } } else { int count = VisualTreeHelper.GetChildrenCount(elt); for (int i = 0; i < count; i++) { RenderHandles(VisualTreeHelper.GetChild(elt, i) as FrameworkElement); } } }
private void RenderNodeShape(UIElement elt, Size sz) { if (elt == null) { return; } Path path = elt as Path; if (path != null) // if it's a Path // and if NodePanel.Figure is specified, it's a NodeShape equivalent { NodeFigure fig = NodePanel.GetFigure(elt); if (fig != NodeFigure.None) { path.Stretch = Stretch.Fill; path.Data = new NodeGeometry(path).GetGeometry(sz); // this also has the side-effect of setting any default Spot1/Spot2 parameters } } }
// return a Geometry that is unscaled (all points are from 0,0 to 1,1) //?? need to use NodeShape some day; promote this stuff to NodePanel also, to implement NodeShape equivalent internal static Geometry GetFigureGeometry(Shape elt) { switch (NodePanel.GetFigure(elt)) { default: case NodeFigure.Rectangle: Geometry _RectangleFigure = new RectangleGeometry() { Rect = new Rect(0, 0, 1, 1) }; return(_RectangleFigure); case NodeFigure.Ellipse: Geometry _EllipseFigure = new EllipseGeometry() { Center = new Point(0.5, 0.5), RadiusX = 0.5, RadiusY = 0.5 }; return(_EllipseFigure); case NodeFigure.Diamond: Geometry _DiamondFigure = new PathGeometry() { Figures = new PathFigureCollection() { new PathFigure() { StartPoint = new Point(0.5, 0), Segments = new PathSegmentCollection() { new LineSegment() { Point = new Point(1, 0.5) }, new LineSegment() { Point = new Point(0.5, 1) }, new LineSegment() { Point = new Point(0, 0.5) } }, IsClosed = true } } }; return(_DiamondFigure); case NodeFigure.TriangleRight: Geometry _TriangleRightFigure = new PathGeometry() { Figures = new PathFigureCollection() { new PathFigure() { StartPoint = new Point(0, 0), Segments = new PathSegmentCollection() { new LineSegment() { Point = new Point(1, 0.5) }, new LineSegment() { Point = new Point(0, 1) } }, IsClosed = true } } }; return(_TriangleRightFigure); case NodeFigure.TriangleDown: Geometry _TriangleDownFigure = new PathGeometry() { Figures = new PathFigureCollection() { new PathFigure() { StartPoint = new Point(0, 0), Segments = new PathSegmentCollection() { new LineSegment() { Point = new Point(1, 0) }, new LineSegment() { Point = new Point(0.5, 1) } }, IsClosed = true } } }; return(_TriangleDownFigure); case NodeFigure.TriangleLeft: Geometry _TriangleLeftFigure = new PathGeometry() { Figures = new PathFigureCollection() { new PathFigure() { StartPoint = new Point(1, 1), Segments = new PathSegmentCollection() { new LineSegment() { Point = new Point(0, 0.5) }, new LineSegment() { Point = new Point(1, 0) } }, IsClosed = true } } }; return(_TriangleLeftFigure); case NodeFigure.TriangleUp: Geometry _TriangleUpFigure = new PathGeometry() { Figures = new PathFigureCollection() { new PathFigure() { StartPoint = new Point(1, 1), Segments = new PathSegmentCollection() { new LineSegment() { Point = new Point(0, 1) }, new LineSegment() { Point = new Point(0.5, 0) } }, IsClosed = true } } }; return(_TriangleUpFigure); case NodeFigure.PlusLine: Geometry _PlusLineFigure = new PathGeometry() { Figures = new PathFigureCollection() { new PathFigure() { StartPoint = new Point(0.5, 0), Segments = new PathSegmentCollection() { new LineSegment() { Point = new Point(0.5, 1) } }, IsClosed = false }, new PathFigure() { StartPoint = new Point(0, 0.5), Segments = new PathSegmentCollection() { new LineSegment() { Point = new Point(1, 0.5) } }, IsClosed = false } } }; return(_PlusLineFigure); case NodeFigure.XLine: Geometry _XLineFigure = new PathGeometry() { Figures = new PathFigureCollection() { new PathFigure() { StartPoint = new Point(0, 0), Segments = new PathSegmentCollection() { new LineSegment() { Point = new Point(1, 1) } }, IsClosed = false }, new PathFigure() { StartPoint = new Point(1, 0), Segments = new PathSegmentCollection() { new LineSegment() { Point = new Point(0, 1) } }, IsClosed = false } } }; return(_XLineFigure); case NodeFigure.AsteriskLine: Geometry _AsteriskLineFigure = new PathGeometry() { Figures = new PathFigureCollection() { new PathFigure() { StartPoint = new Point(0.5, 0), Segments = new PathSegmentCollection() { new LineSegment() { Point = new Point(0.5, 1) } }, IsClosed = false }, new PathFigure() { StartPoint = new Point(0, 0.5), Segments = new PathSegmentCollection() { new LineSegment() { Point = new Point(1, 0.5) } }, IsClosed = false }, new PathFigure() { StartPoint = new Point(0, 0), Segments = new PathSegmentCollection() { new LineSegment() { Point = new Point(1, 1) } }, IsClosed = false }, new PathFigure() { StartPoint = new Point(1, 0), Segments = new PathSegmentCollection() { new LineSegment() { Point = new Point(0, 1) } }, IsClosed = false } } }; return(_AsteriskLineFigure); } }
/// <summary> /// You still need to set its <c>Stroke</c>, <c>StrokeThickness</c>, <c>Fill</c>, et al, as with any <c>Shape</c>. /// </summary> public ToolHandle() { NodePanel.SetFigure(this, NodeFigure.Rectangle); this.Stretch = Stretch.Fill; // because GetFigureGeometry always returns a Geometry with unscaled points from 0,0 to 1,1 }