/// <summary> /// sets the tick values /// </summary> /// <param name="dc"></param> public override void Render(DrawingContext dc) { if (DoubleUtil.IsDoubleFinite(Width) == false) { this.Width = controlSize.Width; //base.Render(dc); //return; } Size size = new Size(Width, Height); double range = Maximum - Minimum; double tickLen = 0.0d; // Height for Primary Tick (for Mininum and Maximum value) double tickLen2; // Height for Secondary Tick double logicalToPhysical = 1.0; double progression = 1.0d; Point startPoint = new Point(0d, 0d); Point endPoint = new Point(0d, 0d); // Take Thumb size in to account double halfReservedSpace = ReservedSpace * 0.5; switch (Placement) { case TickBarPlacement.Top: if (DoubleUtil.GreaterThanOrClose(ReservedSpace, size.Width)) { return; } size = new Size(size.Width - ReservedSpace, size.Height); tickLen = -size.Height; startPoint = new Point(halfReservedSpace, size.Height); endPoint = new Point(halfReservedSpace + size.Width, size.Height); logicalToPhysical = size.Width / range; progression = 1; break; case TickBarPlacement.Bottom: if (DoubleUtil.GreaterThanOrClose(ReservedSpace, size.Width)) { return; } size = new Size(size.Width - ReservedSpace, size.Height); tickLen = size.Height; startPoint = new Point(halfReservedSpace, 0d); endPoint = new Point(halfReservedSpace + size.Width, 0d); logicalToPhysical = size.Width / range; progression = 1; break; case TickBarPlacement.Left: if (DoubleUtil.GreaterThanOrClose(ReservedSpace, size.Height)) { return; } size = new Size(size.Width, size.Height - ReservedSpace); tickLen = -size.Width; startPoint = new Point(size.Width, size.Height + halfReservedSpace); endPoint = new Point(size.Width, halfReservedSpace); logicalToPhysical = size.Height / range * -1; progression = -1; break; case TickBarPlacement.Right: if (DoubleUtil.GreaterThanOrClose(ReservedSpace, size.Height)) { return; } size = new Size(size.Width, size.Height - ReservedSpace); tickLen = size.Width; startPoint = new Point(0d, size.Height + halfReservedSpace); endPoint = new Point(0d, halfReservedSpace); logicalToPhysical = size.Height / range * -1; progression = -1; break; } ; tickLen2 = tickLen * 0.75; // Invert direciton of the ticks if (IsDirectionReversed) { progression = -progression; logicalToPhysical *= -1; // swap startPoint & endPoint Point pt = startPoint; startPoint = endPoint; endPoint = pt; } Pen pen = new Pen(Fill, 1.0d); bool snapsToDevicePixels = false;//SnapsToDevicePixels DoubleCollection xLines = snapsToDevicePixels ? new DoubleCollection() : null; DoubleCollection yLines = snapsToDevicePixels ? new DoubleCollection() : null; // Is it Vertical? if ((Placement == TickBarPlacement.Left) || (Placement == TickBarPlacement.Right)) { // Reduce tick interval if it is more than would be visible on the screen double interval = TickFrequency; if (interval > 0.0) { double minInterval = (Maximum - Minimum) / size.Height; if (interval < minInterval) { interval = minInterval; } } // Draw Min & Max tick dc.DrawLine(pen, startPoint, new Point(startPoint.X + tickLen, startPoint.Y)); dc.DrawLine(pen, new Point(startPoint.X, endPoint.Y), new Point(startPoint.X + tickLen, endPoint.Y)); if (snapsToDevicePixels) { xLines.Add(startPoint.X); yLines.Add(startPoint.Y - 0.5); xLines.Add(startPoint.X + tickLen); yLines.Add(endPoint.Y - 0.5); xLines.Add(startPoint.X + tickLen2); } // This property is rarely set so let's try to avoid the GetValue // caching of the mutable default value DoubleCollection ticks = null; if (GetValue(TicksProperty) != null) { ticks = Ticks; } // Draw ticks using specified Ticks collection if ((ticks != null) && (ticks.Count > 0)) { for (int i = 0; i < ticks.Count; i++) { if (DoubleUtil.LessThanOrClose(ticks[i], Minimum) || DoubleUtil.GreaterThanOrClose(ticks[i], Maximum)) { continue; } double adjustedTick = ticks[i] - Minimum; double y = adjustedTick * logicalToPhysical + startPoint.Y; dc.DrawLine(pen, new Point(startPoint.X, y), new Point(startPoint.X + tickLen2, y)); if (snapsToDevicePixels) { yLines.Add(y - 0.5); } } } // Draw ticks using specified TickFrequency else if (interval > 0.0) { for (double i = interval; i < range; i += interval) { double y = i * logicalToPhysical + startPoint.Y; dc.DrawLine(pen, new Point(startPoint.X, y), new Point(startPoint.X + tickLen2, y)); if (snapsToDevicePixels) { yLines.Add(y - 0.5); } } } // Draw Selection Ticks if (IsSelectionRangeEnabled) { double y0 = (SelectionStart - Minimum) * logicalToPhysical + startPoint.Y; Point pt0 = new Point(startPoint.X, y0); Point pt1 = new Point(startPoint.X + tickLen2, y0); Point pt2 = new Point(startPoint.X + tickLen2, y0 + Math.Abs(tickLen2) * progression); //PathSegment[] segments = new PathSegment[] { // //new LineSegment(pt2, true), // //new LineSegment(pt0, true), // new LineSegment{Point=pt2 }, // new LineSegment{Point=pt0 }, //}; PathSegments segments = new PathSegments(); segments.Add(new LineSegment { Point = pt2 }); segments.Add(new LineSegment { Point = pt0 }); PathGeometry geo = new PathGeometry { Figures = new PathFigures { new PathFigure { StartPoint = pt1, Segments = segments, IsClosed = true } } }; dc.DrawGeometry(Fill, pen, geo); y0 = (SelectionEnd - Minimum) * logicalToPhysical + startPoint.Y; pt0 = new Point(startPoint.X, y0); pt1 = new Point(startPoint.X + tickLen2, y0); pt2 = new Point(startPoint.X + tickLen2, y0 - Math.Abs(tickLen2) * progression); segments = new PathSegments(); segments.Add(new LineSegment { Point = pt2 }); segments.Add(new LineSegment { Point = pt0 }); geo = new PathGeometry { Figures = new PathFigures { new PathFigure { StartPoint = pt1, Segments = segments, IsClosed = true } } }; dc.DrawGeometry(Fill, pen, geo); } } else // Placement == Top || Placement == Bottom { // Reduce tick interval if it is more than would be visible on the screen double interval = TickFrequency; if (interval > 0.0) { double minInterval = (Maximum - Minimum) / size.Width; if (interval < minInterval) { interval = minInterval; } } // Draw Min & Max tick dc.DrawLine(pen, startPoint, new Point(startPoint.X, startPoint.Y + tickLen)); dc.DrawLine(pen, new Point(endPoint.X, startPoint.Y), new Point(endPoint.X, startPoint.Y + tickLen)); if (snapsToDevicePixels) { xLines.Add(startPoint.X - 0.5); yLines.Add(startPoint.Y); xLines.Add(startPoint.X - 0.5); yLines.Add(endPoint.Y + tickLen); yLines.Add(endPoint.Y + tickLen2); } // This property is rarely set so let's try to avoid the GetValue // caching of the mutable default value DoubleCollection ticks = null; if (GetValue(TicksProperty) != null) { ticks = Ticks; } // Draw ticks using specified Ticks collection if ((ticks != null) && (ticks.Count > 0)) { for (int i = 0; i < ticks.Count; i++) { if (DoubleUtil.LessThanOrClose(ticks[i], Minimum) || DoubleUtil.GreaterThanOrClose(ticks[i], Maximum)) { continue; } double adjustedTick = ticks[i] - Minimum; double x = adjustedTick * logicalToPhysical + startPoint.X; dc.DrawLine(pen, new Point(x, startPoint.Y), new Point(x, startPoint.Y + tickLen2)); if (snapsToDevicePixels) { xLines.Add(x - 0.5); } } } // Draw ticks using specified TickFrequency else if (interval > 0.0) { for (double i = interval; i < range; i += interval) { double x = i * logicalToPhysical + startPoint.X; dc.DrawLine(pen, new Point(x, startPoint.Y), new Point(x, startPoint.Y + tickLen2)); if (snapsToDevicePixels) { xLines.Add(x - 0.5); } } } // Draw Selection Ticks if (IsSelectionRangeEnabled) { double x0 = (SelectionStart - Minimum) * logicalToPhysical + startPoint.X; Point pt0 = new Point(x0, startPoint.Y); Point pt1 = new Point(x0, startPoint.Y + tickLen2); Point pt2 = new Point(x0 + Math.Abs(tickLen2) * progression, startPoint.Y + tickLen2); //PathSegment[] segments = new PathSegment[] { // new LineSegment(pt2, true), // new LineSegment(pt0, true), //}; PathSegments segments = new PathSegments(); segments.Add(new LineSegment { Point = pt2 }); segments.Add(new LineSegment { Point = pt0 }); PathGeometry geo = new PathGeometry { Figures = new PathFigures { new PathFigure { StartPoint = pt1, Segments = segments, IsClosed = true } } }; dc.DrawGeometry(Fill, pen, geo); x0 = (SelectionEnd - Minimum) * logicalToPhysical + startPoint.X; pt0 = new Point(x0, startPoint.Y); pt1 = new Point(x0, startPoint.Y + tickLen2); pt2 = new Point(x0 - Math.Abs(tickLen2) * progression, startPoint.Y + tickLen2); segments = new PathSegments(); segments.Add(new LineSegment { Point = pt2 }); segments.Add(new LineSegment { Point = pt0 }); geo = new PathGeometry { Figures = new PathFigures { new PathFigure { StartPoint = pt1, Segments = segments, IsClosed = true } } }; dc.DrawGeometry(Fill, pen, geo); } } if (snapsToDevicePixels) { xLines.Add(Width); yLines.Add(Height); VisualXSnappingGuidelines = xLines; VisualYSnappingGuidelines = yLines; } return; }
// Sets Value = SnapToTick(value+direction), unless the result of SnapToTick is Value, // then it searches for the next tick greater(if direction is positive) than value // and sets Value to that tick private void MoveToNextTick(double direction) { if (direction != 0.0) { double value = this.Value; // Find the next value by snapping double next = SnapToTick(Math.Max(this.Minimum, Math.Min(this.Maximum, value + direction))); bool greaterThan = direction > 0; //search for the next tick greater than value? // If the snapping brought us back to value, find the next tick point if (next == value && !(greaterThan && value == Maximum) && // Stop if searching up if already at Max !(!greaterThan && value == Minimum)) // Stop if searching down if already at Min { // This property is rarely set so let's try to avoid the GetValue // caching of the mutable default value DoubleCollection ticks = null; if (GetValue(TicksProperty) != null) { ticks = Ticks; } // If ticks collection is available, use it. // Note that ticks may be unsorted. if ((ticks != null) && (ticks.Count > 0)) { for (int i = 0; i < ticks.Count; i++) { double tick = ticks[i]; // Find the smallest tick greater than value or the largest tick less than value if ((greaterThan && DoubleUtil.GreaterThan(tick, value) && (DoubleUtil.LessThan(tick, next) || next == value)) || (!greaterThan && DoubleUtil.LessThan(tick, value) && (DoubleUtil.GreaterThan(tick, next) || next == value))) { next = tick; } } } else if (DoubleUtil.GreaterThan(TickFrequency, 0.0)) { // Find the current tick we are at double tickNumber = Math.Round((value - Minimum) / TickFrequency); if (greaterThan) { tickNumber += 1.0; } else { tickNumber -= 1.0; } next = Minimum + tickNumber * TickFrequency; } } // Update if we've found a better value if (next != value) { this.SetValue(ValueProperty, next); } } }