private List <List <Interval> > CollectIntervals() { List <Path> paths = new List <Path>(); foreach (UIElement e in this.Children) { paths.Add(e as Path); // include null when not a Path } List <List <Interval> > list = new List <List <Interval> >(); for (int i = 0; i < paths.Count; i++) { Path p = paths[i]; List <Interval> ints = new List <Interval>(); list.Add(ints); if (p == null) { continue; } GridFigure fig = GetFigure(p); if (fig == GridFigure.None) { continue; } bool vert = IsVertical(fig); for (int j = i + 1; j < paths.Count; j++) { Path q = paths[j]; if (q == null) { continue; } GridFigure f = GetFigure(q); if (f == GridFigure.None || IsVertical(f) != vert) { continue; } int v = GetInterval(q); int off = GetOffset(q); if (v >= 2) { ints.Add(new Interval() { Spacing = v, Offset = off }); } } } return(list); }
/// <summary> /// Supply the geometries for child <c>Path</c> elements that have a /// <see cref="GetFigure"/> that is not <see cref="GridFigure.None"/>, /// and measure all children. /// </summary> /// <param name="availableSize"></param> /// <returns></returns> protected override Size MeasureOverride(Size availableSize) { //DateTime before = DateTime.Now; double w = availableSize.Width; if (Double.IsPositiveInfinity(w) || Double.IsNaN(w)) { w = this.Width; } if (Double.IsPositiveInfinity(w) || Double.IsNaN(w)) { w = this.MinWidth; } if (Double.IsPositiveInfinity(w) || Double.IsNaN(w)) { w = this.MaxWidth; } if (Double.IsPositiveInfinity(w) || Double.IsNaN(w)) { w = 0; } double h = availableSize.Height; if (Double.IsPositiveInfinity(h) || Double.IsNaN(h)) { h = this.Height; } if (Double.IsPositiveInfinity(h) || Double.IsNaN(h)) { h = this.MinHeight; } if (Double.IsPositiveInfinity(h) || Double.IsNaN(h)) { h = this.MaxHeight; } if (Double.IsPositiveInfinity(h) || Double.IsNaN(h)) { h = 0; } //Diagram.Debug("GridPattern.Measure: " + Diagram.Str(availableSize) + Diagram.Str(w) + "x" + Diagram.Str(h)); List <List <Interval> > ints = this.GridIntervals; bool recompute = (this.GridIntervals == null || this.GeometrySize.Width != w || this.GeometrySize.Height != h); if (recompute) { ints = CollectIntervals(); // if no Intervals were cached, or if we need newly sized PathGeometries, compute them } for (int i = 0; i < this.Children.Count; i++) { UIElement e = this.Children[i]; // if there is a cached GridIntervals, assume the PathGeometries are up-to-date if (recompute) { Path path = e as Path; if (path != null) { GridFigure fig = GetFigure(path); int freq = GetInterval(path); int off = GetOffset(path); int bar = GetBarThickness(path); if (fig != GridFigure.None && freq >= 1 && bar >= 1) { path.Visibility = Visibility.Visible; path.Data = GetDefiningGeometry(fig, w, h, freq, off, ints[i], bar); if (fig == GridFigure.HorizontalDot || fig == GridFigure.VerticalDot) { path.StrokeDashCap = PenLineCap.Round; Size csz = this.CellSize; Point orig = this.Origin; double st = path.StrokeThickness; if (st <= 0) { st = 1; path.StrokeThickness = st; } if (fig == GridFigure.HorizontalDot) { path.StrokeDashArray = new DoubleCollection() { 0, csz.Width / st }; path.StrokeDashOffset = -orig.X / st; } else if (fig == GridFigure.VerticalDot) { path.StrokeDashArray = new DoubleCollection() { 0, csz.Height / st }; path.StrokeDashOffset = -orig.Y / st; } } else if (fig == GridFigure.HorizontalCross || fig == GridFigure.VerticalCross) { Size csz = this.CellSize; Point orig = this.Origin; double st = path.StrokeThickness; if (st <= 0) { st = 1; path.StrokeThickness = st; } double len = GetCrossLength(path); double halfdash = len / (st * 2); if (fig == GridFigure.HorizontalCross) { if (csz.Width > len) { path.StrokeDashArray = new DoubleCollection() { halfdash, (csz.Width - len) / st, halfdash, 0 }; path.StrokeDashOffset = -orig.X / st; } } else if (fig == GridFigure.VerticalCross) { if (csz.Height > len) { path.StrokeDashArray = new DoubleCollection() { halfdash, (csz.Height - len) / st, halfdash, 0 }; path.StrokeDashOffset = -orig.Y / st; } } } } else { path.Visibility = Visibility.Collapsed; } } } e.Measure(availableSize); } if (recompute) { this.GridIntervals = ints; // if no Intervals cached, save them } this.GeometrySize = new Size(w, h); //Diagram.Debug("GridPattern measure: " + (DateTime.Now-before).TotalMilliseconds.ToString()); return(new Size(w, h)); }
private Geometry GetDefiningGeometry(GridFigure fig, double gw, double gh, int freq, int off, List <Interval> ints, int barmult) { double scale = this.RenderedScale; if (scale <= 0) { scale = 1; } Size csz = this.CellSize; double cw = csz.Width; double ch = csz.Height; int numx = (int)Math.Ceiling(gw / cw); int numy = (int)Math.Ceiling(gh / ch); Point cpt = this.Origin; GeoStream sg = new GeoStream(); using (StreamGeometryContext context = sg.Open()) { if (fig == GridFigure.None) { context.BeginFigure(new Point(0, 0), true, true); return(sg.Geometry); } else if (IsVertical(fig)) // vertical { if (fig == GridFigure.VerticalBar) { // vertical lines int start = (int)Math.Floor(-cpt.X / cw); int i = start; for (; i < start + numx; i++) { double x = i * cw + cpt.X; double x2 = i * cw + cpt.X + barmult * cw; if (0 < x2 && x < gw && ShouldDraw(i, freq, off, ints)) { x = Math.Max(x, 0); x2 = Math.Min(x2, gw); context.BeginFigure(new Point(x, 0), true, true); context.LineTo(new Point(x, gh), true, false); context.LineTo(new Point(x2, gh), true, true); context.LineTo(new Point(x2, 0), true, true); if (cw * freq * scale < 2) { break; } } } } else { // background rectangle, for the optional Fill context.BeginFigure(new Point(0, 0), true, true); context.LineTo(new Point(gw, 0), false, false); context.LineTo(new Point(gw, gh), false, false); context.LineTo(new Point(0, gh), false, false); context.LineTo(new Point(0, 0), false, false); // vertical lines int start = (int)Math.Floor(-cpt.X / cw); for (int i = start; i <= start + numx; i++) { double x = i * cw + cpt.X; if (0 <= x && x <= gw && ShouldDraw(i, freq, off, ints)) { context.BeginFigure(new Point(x, 0), false, false); context.LineTo(new Point(x, gh), true, false); if (cw * freq * scale < 2) { break; } } } } } else { if (fig == GridFigure.HorizontalBar) { // horizontal lines int start = (int)Math.Floor(-cpt.Y / ch); int i = start; for (; i < start + numy; i++) { double y = i * ch + cpt.Y; double y2 = i * ch + cpt.Y + barmult * ch; if (0 < y2 && y < gh && ShouldDraw(i, freq, off, ints)) { y = Math.Max(y, 0); y2 = Math.Min(y2, gh); context.BeginFigure(new Point(0, y), true, true); context.LineTo(new Point(gw, y), true, false); context.LineTo(new Point(gw, y2), true, false); context.LineTo(new Point(0, y2), true, false); if (ch * freq * scale < 2) { break; } } } } else { // background rectangle, for the optional Fill context.BeginFigure(new Point(0, 0), true, true); context.LineTo(new Point(gw, 0), false, false); context.LineTo(new Point(gw, gh), false, false); context.LineTo(new Point(0, gh), false, false); context.LineTo(new Point(0, 0), false, false); // horizontal lines int start = (int)Math.Floor(-cpt.Y / ch); for (int i = start; i <= start + numy; i++) { double y = i * ch + cpt.Y; if (0 <= y && y <= gh && ShouldDraw(i, freq, off, ints)) { context.BeginFigure(new Point(0, y), false, false); context.LineTo(new Point(gw, y), true, false); if (ch * freq * scale < 2) { break; //??? NYI automatically calling InvalidateVisual on each GridPattern when the DiagramPanel.Scale changes } } } } } return(sg.Geometry); } }
private bool IsVertical(GridFigure fig) { return(fig != GridFigure.None && ((int)fig & 1) == 1); }
/// <summary> /// Sets the <see cref="GridFigure"/> of the <c>Path</c> to determine its appearance. /// </summary> /// <param name="d">a <c>Path</c></param> /// <param name="v"> /// a <see cref="GridFigure"/>; the panel assumes <see cref="GridFigure.None"/> otherwise /// </param> public static void SetFigure(DependencyObject d, GridFigure v) { d.SetValue(FigureProperty, v); }
private Geometry GetDefiningGeometry(GridFigure fig, double gw, double gh, int freq, int off, List<Interval> ints, int barmult) { double scale = this.RenderedScale; if (scale <= 0) scale = 1; Size csz = this.CellSize; double cw = csz.Width; double ch = csz.Height; int numx = (int)Math.Ceiling(gw/cw); int numy = (int)Math.Ceiling(gh/ch); Point cpt = this.Origin; GeoStream sg = new GeoStream(); using (StreamGeometryContext context = sg.Open()) { if (fig == GridFigure.None) { context.BeginFigure(new Point(0, 0), true, true); return sg.Geometry; } else if (IsVertical(fig)) { // vertical if (fig == GridFigure.VerticalBar) { // vertical lines int start = (int)Math.Floor(-cpt.X/cw); int i = start; for (; i < start+numx; i++) { double x = i*cw+cpt.X; double x2 = i*cw+cpt.X+barmult*cw; if (0 < x2 && x < gw && ShouldDraw(i, freq, off, ints)) { x = Math.Max(x, 0); x2 = Math.Min(x2, gw); context.BeginFigure(new Point(x, 0), true, true); context.LineTo(new Point(x, gh), true, false); context.LineTo(new Point(x2, gh), true, true); context.LineTo(new Point(x2, 0), true, true); if (cw*freq*scale < 2) break; } } } else { // background rectangle, for the optional Fill context.BeginFigure(new Point(0, 0), true, true); context.LineTo(new Point(gw, 0), false, false); context.LineTo(new Point(gw, gh), false, false); context.LineTo(new Point(0, gh), false, false); context.LineTo(new Point(0, 0), false, false); // vertical lines int start = (int)Math.Floor(-cpt.X/cw); for (int i = start; i <= start+numx; i++) { double x = i*cw+cpt.X; if (0 <= x && x <= gw && ShouldDraw(i, freq, off, ints)) { context.BeginFigure(new Point(x, 0), false, false); context.LineTo(new Point(x, gh), true, false); if (cw*freq*scale < 2) break; } } } } else { if (fig == GridFigure.HorizontalBar) { // horizontal lines int start = (int)Math.Floor(-cpt.Y/ch); int i = start; for (; i < start+numy; i++) { double y = i*ch+cpt.Y; double y2 = i*ch+cpt.Y+barmult*ch; if (0 < y2 && y < gh && ShouldDraw(i, freq, off, ints)) { y = Math.Max(y, 0); y2 = Math.Min(y2, gh); context.BeginFigure(new Point(0, y), true, true); context.LineTo(new Point(gw, y), true, false); context.LineTo(new Point(gw, y2), true, false); context.LineTo(new Point(0, y2), true, false); if (ch*freq*scale < 2) break; } } } else { // background rectangle, for the optional Fill context.BeginFigure(new Point(0, 0), true, true); context.LineTo(new Point(gw, 0), false, false); context.LineTo(new Point(gw, gh), false, false); context.LineTo(new Point(0, gh), false, false); context.LineTo(new Point(0, 0), false, false); // horizontal lines int start = (int)Math.Floor(-cpt.Y/ch); for (int i = start; i <= start+numy; i++) { double y = i*ch+cpt.Y; if (0 <= y && y <= gh && ShouldDraw(i, freq, off, ints)) { context.BeginFigure(new Point(0, y), false, false); context.LineTo(new Point(gw, y), true, false); if (ch*freq*scale < 2) break; //??? NYI automatically calling InvalidateVisual on each GridPattern when the DiagramPanel.Scale changes } } } } return sg.Geometry; } }
private bool IsVertical(GridFigure fig) { return (fig != GridFigure.None && ((int)fig & 1) == 1); }
/// <summary> /// Sets the <see cref="GridFigure"/> of the <c>Path</c> to determine its appearance. /// </summary> /// <param name="d">a <c>Path</c></param> /// <param name="v"> /// a <see cref="GridFigure"/>; the panel assumes <see cref="GridFigure.None"/> otherwise /// </param> public static void SetFigure(DependencyObject d, GridFigure v) { d.SetValue(FigureProperty, v); }