Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / wpf / src / Framework / System / Windows / Controls / Primitives / TickBar.cs / 1 / TickBar.cs
//---------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation. All rights reserved. // //--------------------------------------------------------------------------- using System; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.Collections; using MS.Internal; using System.Windows.Threading; using System.Windows; using System.Windows.Data; using System.Windows.Input; using System.Windows.Media; using System.Windows.Shapes; using MS.Internal.KnownBoxes; using MS.Win32; // For typeconverter using System.ComponentModel.Design.Serialization; using System.Reflection; namespace System.Windows.Controls.Primitives { ////// Enum which describes how to position the TickBar. /// public enum TickBarPlacement { ////// Position this tick at the left of target element. /// Left, ////// Position this tick at the top of target element. /// Top, ////// Position this tick at the right of target element. /// Right, ////// Position this tick at the bottom of target element. /// Bottom, // NOTE: if you add or remove any values in this enum, be sure to update TickBar.IsValidTickBarPlacement() }; ////// TickBar is an element that use for drawing Slider's Ticks. /// [Localizability(LocalizationCategory.None, Readability = Readability.Unreadable)] // cannot be read & localized as string public class TickBar : FrameworkElement { //------------------------------------------------------------------- // // Constructors // //------------------------------------------------------------------- #region Constructors static TickBar() { SnapsToDevicePixelsProperty.OverrideMetadata(typeof(TickBar), new FrameworkPropertyMetadata(true)); } ////// Default constructor for TickBar class /// ////// Automatic determination of current Dispatcher. Use alternative constructor /// that accepts a Dispatcher for best performance. /// public TickBar() : base() { } #endregion ////// Fill property /// public static readonly DependencyProperty FillProperty = DependencyProperty.Register( "Fill", typeof(Brush), typeof(TickBar), new FrameworkPropertyMetadata( (Brush)null, FrameworkPropertyMetadataOptions.AffectsRender, null, null) ); ////// Fill property /// public Brush Fill { get { return (Brush)GetValue(FillProperty); } set { SetValue(FillProperty, value); } } ////// The DependencyProperty for the public static readonly DependencyProperty MinimumProperty = RangeBase.MinimumProperty.AddOwner( typeof(TickBar), new FrameworkPropertyMetadata( 0.0, FrameworkPropertyMetadataOptions.AffectsRender)); ///property. /// /// Logical position where the Minimum Tick will be drawn /// [Bindable(true), Category("Appearance")] public double Minimum { get { return (double) GetValue(MinimumProperty); } set { SetValue(MinimumProperty, value); } } ////// The DependencyProperty for the public static readonly DependencyProperty MaximumProperty = RangeBase.MaximumProperty.AddOwner( typeof(TickBar), new FrameworkPropertyMetadata( 100.0, FrameworkPropertyMetadataOptions.AffectsRender)); ///property. /// /// Logical position where the Maximum Tick will be drawn /// [Bindable(true), Category("Appearance")] public double Maximum { get { return (double) GetValue(MaximumProperty); } set { SetValue(MaximumProperty, value); } } ////// The DependencyProperty for the public static readonly DependencyProperty SelectionStartProperty = Slider.SelectionStartProperty.AddOwner( typeof(TickBar), new FrameworkPropertyMetadata( -1.0d, FrameworkPropertyMetadataOptions.AffectsRender)); ///property. /// /// Logical position where the SelectionStart Tick will be drawn /// [Bindable(true), Category("Appearance")] public double SelectionStart { get { return (double) GetValue(SelectionStartProperty); } set { SetValue(SelectionStartProperty, value); } } ////// The DependencyProperty for the public static readonly DependencyProperty SelectionEndProperty = Slider.SelectionEndProperty.AddOwner( typeof(TickBar), new FrameworkPropertyMetadata( -1.0d, FrameworkPropertyMetadataOptions.AffectsRender)); ///property. /// /// Logical position where the SelectionEnd Tick will be drawn /// [Bindable(true), Category("Appearance")] public double SelectionEnd { get { return (double) GetValue(SelectionEndProperty); } set { SetValue(SelectionEndProperty, value); } } ////// The DependencyProperty for the public static readonly DependencyProperty IsSelectionRangeEnabledProperty = Slider.IsSelectionRangeEnabledProperty.AddOwner( typeof(TickBar), new FrameworkPropertyMetadata( BooleanBoxes.FalseBox, FrameworkPropertyMetadataOptions.AffectsRender)); ///property. /// /// IsSelectionRangeEnabled specifies whether to draw SelectionStart Tick and SelectionEnd Tick or not. /// [Bindable(true), Category("Appearance")] public bool IsSelectionRangeEnabled { get { return (bool) GetValue(IsSelectionRangeEnabledProperty); } set { SetValue(IsSelectionRangeEnabledProperty, BooleanBoxes.Box(value)); } } ////// DependencyProperty for public static readonly DependencyProperty TickFrequencyProperty = Slider.TickFrequencyProperty.AddOwner( typeof(TickBar), new FrameworkPropertyMetadata( 1.0, FrameworkPropertyMetadataOptions.AffectsRender)); ///property. /// /// TickFrequency property defines how the tick will be drawn. /// [Bindable(true), Category("Appearance")] public double TickFrequency { get { return (double) GetValue(TickFrequencyProperty); } set { SetValue(TickFrequencyProperty, value); } } ////// DependencyProperty for public static readonly DependencyProperty TicksProperty = Slider.TicksProperty.AddOwner( typeof(TickBar), new FrameworkPropertyMetadata( new FreezableDefaultValueFactory(DoubleCollection.Empty), FrameworkPropertyMetadataOptions.AffectsRender)); ///property. /// /// The Ticks property contains collection of value of type Double which /// are the logical positions use to draw the ticks. /// The property value is a [Bindable(true), Category("Appearance")] public DoubleCollection Ticks { get { return (DoubleCollection) GetValue(TicksProperty); } set { SetValue(TicksProperty, value); } } ///. /// /// DependencyProperty for IsDirectionReversed property. /// public static readonly DependencyProperty IsDirectionReversedProperty = Slider.IsDirectionReversedProperty.AddOwner( typeof(TickBar), new FrameworkPropertyMetadata( BooleanBoxes.FalseBox, FrameworkPropertyMetadataOptions.AffectsRender)); ////// The IsDirectionReversed property defines the direction of value incrementation. /// By default, if Tick's orientation is Horizontal, ticks will be drawn from left to right. /// (And, bottom to top for Vertical orientation). /// If IsDirectionReversed is 'true' the direction of the drawing will be in opposite direction. /// Ticks property contains collection of value of type Double which /// [Bindable(true), Category("Appearance")] public bool IsDirectionReversed { get { return (bool) GetValue(IsDirectionReversedProperty); } set { SetValue(IsDirectionReversedProperty, BooleanBoxes.Box(value)); } } ////// DependencyProperty for public static readonly DependencyProperty PlacementProperty = DependencyProperty.Register( "Placement", typeof(TickBarPlacement), typeof(TickBar), new FrameworkPropertyMetadata( TickBarPlacement.Top, FrameworkPropertyMetadataOptions.AffectsRender), new ValidateValueCallback(IsValidTickBarPlacement)); ///property. /// /// Placement property specified how the Tick will be placed. /// This property affects the way ticks are drawn. /// This property has type of [Bindable(true), Category("Appearance")] public TickBarPlacement Placement { get { return (TickBarPlacement) GetValue(PlacementProperty); } set { SetValue(PlacementProperty, value); } } private static bool IsValidTickBarPlacement(object o) { TickBarPlacement placement = (TickBarPlacement)o; return placement == TickBarPlacement.Left || placement == TickBarPlacement.Top || placement == TickBarPlacement.Right || placement == TickBarPlacement.Bottom; } ///. /// /// DependencyProperty for ReservedSpace property. /// public static readonly DependencyProperty ReservedSpaceProperty = DependencyProperty.Register( "ReservedSpace", typeof(double), typeof(TickBar), new FrameworkPropertyMetadata( 0d, FrameworkPropertyMetadataOptions.AffectsRender)); ////// TickBar will use ReservedSpaceProperty for left and right spacing (for horizontal orientation) or /// tob and bottom spacing (for vertical orienation). /// The space on both sides of TickBar is half of specified ReservedSpace. /// This property has type of [Bindable(true), Category("Appearance")] public double ReservedSpace { get { return (double) GetValue(ReservedSpaceProperty); } set { SetValue(ReservedSpaceProperty, value); } } ///. /// /// Draw ticks. /// Ticks can be draw in 8 diffrent ways depends on Placment property and IsDirectionReversed property. /// /// This function also draw selection-tick(s) if IsSelectionRangeEnabled is 'true' and /// SelectionStart and SelectionEnd are valid. /// /// The primary ticks (for Mininum and Maximum value) height will be 100% of TickBar's render size (use Width or Height /// depends on Placement property). /// /// The secondary ticks (all other ticks, including selection-tics) height will be 75% of TickBar's render size. /// /// Brush that use to fill ticks is specified by Shape.Fill property. /// /// Pen that use to draw ticks is specified by Shape.Pen property. /// protected override void OnRender(DrawingContext dc) { Size size = new Size(ActualWidth,ActualHeight); 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.Width -= ReservedSpace; 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.Width -= ReservedSpace; 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.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.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 = 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; bool hasModifiers; if (GetValueSource(TicksProperty, null, out hasModifiers) != BaseValueSourceInternal.Default || hasModifiers) { 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), }; PathGeometry geo = new PathGeometry(new PathFigure[] { new PathFigure(pt1, segments, 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 PathSegment[] { new LineSegment(pt2, true), new LineSegment(pt0, true), }; geo = new PathGeometry(new PathFigure[] { new PathFigure(pt1, segments, 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; bool hasModifiers; if (GetValueSource(TicksProperty, null, out hasModifiers) != BaseValueSourceInternal.Default || hasModifiers) { 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), }; PathGeometry geo = new PathGeometry(new PathFigure[] { new PathFigure(pt1, segments, 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 PathSegment[] { new LineSegment(pt2, true), new LineSegment(pt0, true), }; geo = new PathGeometry(new PathFigure[] { new PathFigure(pt1, segments, true) }); dc.DrawGeometry(Fill, pen, geo); } } if (snapsToDevicePixels) { xLines.Add(ActualWidth); yLines.Add(ActualHeight); VisualXSnappingGuidelines = xLines; VisualYSnappingGuidelines = yLines; } return; } private void BindToTemplatedParent(DependencyProperty target, DependencyProperty source) { if (!HasNonDefaultValue(target)) { Binding binding = new Binding(); binding.RelativeSource = RelativeSource.TemplatedParent; binding.Path = new PropertyPath(source); SetBinding(target, binding); } } ////// TickBar sets bindings on its properties to its TemplatedParent if the /// properties are not already set. /// internal override void OnPreApplyTemplate() { base.OnPreApplyTemplate(); Slider parent = TemplatedParent as Slider; if (parent != null) { BindToTemplatedParent(TicksProperty, Slider.TicksProperty); BindToTemplatedParent(TickFrequencyProperty, Slider.TickFrequencyProperty); BindToTemplatedParent(IsSelectionRangeEnabledProperty, Slider.IsSelectionRangeEnabledProperty); BindToTemplatedParent(SelectionStartProperty, Slider.SelectionStartProperty); BindToTemplatedParent(SelectionEndProperty, Slider.SelectionEndProperty); BindToTemplatedParent(MinimumProperty, Slider.MinimumProperty); BindToTemplatedParent(MaximumProperty, Slider.MaximumProperty); BindToTemplatedParent(IsDirectionReversedProperty, Slider.IsDirectionReversedProperty); if (!HasNonDefaultValue(ReservedSpaceProperty) && parent.Track != null) { Binding binding = new Binding(); binding.Source = parent.Track.Thumb; if (parent.Orientation == Orientation.Horizontal) { binding.Path = new PropertyPath(Thumb.ActualWidthProperty); } else { binding.Path = new PropertyPath(Thumb.ActualHeightProperty); } SetBinding(ReservedSpaceProperty, binding); } } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //---------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation. All rights reserved. // //--------------------------------------------------------------------------- using System; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.Collections; using MS.Internal; using System.Windows.Threading; using System.Windows; using System.Windows.Data; using System.Windows.Input; using System.Windows.Media; using System.Windows.Shapes; using MS.Internal.KnownBoxes; using MS.Win32; // For typeconverter using System.ComponentModel.Design.Serialization; using System.Reflection; namespace System.Windows.Controls.Primitives { ////// Enum which describes how to position the TickBar. /// public enum TickBarPlacement { ////// Position this tick at the left of target element. /// Left, ////// Position this tick at the top of target element. /// Top, ////// Position this tick at the right of target element. /// Right, ////// Position this tick at the bottom of target element. /// Bottom, // NOTE: if you add or remove any values in this enum, be sure to update TickBar.IsValidTickBarPlacement() }; ////// TickBar is an element that use for drawing Slider's Ticks. /// [Localizability(LocalizationCategory.None, Readability = Readability.Unreadable)] // cannot be read & localized as string public class TickBar : FrameworkElement { //------------------------------------------------------------------- // // Constructors // //------------------------------------------------------------------- #region Constructors static TickBar() { SnapsToDevicePixelsProperty.OverrideMetadata(typeof(TickBar), new FrameworkPropertyMetadata(true)); } ////// Default constructor for TickBar class /// ////// Automatic determination of current Dispatcher. Use alternative constructor /// that accepts a Dispatcher for best performance. /// public TickBar() : base() { } #endregion ////// Fill property /// public static readonly DependencyProperty FillProperty = DependencyProperty.Register( "Fill", typeof(Brush), typeof(TickBar), new FrameworkPropertyMetadata( (Brush)null, FrameworkPropertyMetadataOptions.AffectsRender, null, null) ); ////// Fill property /// public Brush Fill { get { return (Brush)GetValue(FillProperty); } set { SetValue(FillProperty, value); } } ////// The DependencyProperty for the public static readonly DependencyProperty MinimumProperty = RangeBase.MinimumProperty.AddOwner( typeof(TickBar), new FrameworkPropertyMetadata( 0.0, FrameworkPropertyMetadataOptions.AffectsRender)); ///property. /// /// Logical position where the Minimum Tick will be drawn /// [Bindable(true), Category("Appearance")] public double Minimum { get { return (double) GetValue(MinimumProperty); } set { SetValue(MinimumProperty, value); } } ////// The DependencyProperty for the public static readonly DependencyProperty MaximumProperty = RangeBase.MaximumProperty.AddOwner( typeof(TickBar), new FrameworkPropertyMetadata( 100.0, FrameworkPropertyMetadataOptions.AffectsRender)); ///property. /// /// Logical position where the Maximum Tick will be drawn /// [Bindable(true), Category("Appearance")] public double Maximum { get { return (double) GetValue(MaximumProperty); } set { SetValue(MaximumProperty, value); } } ////// The DependencyProperty for the public static readonly DependencyProperty SelectionStartProperty = Slider.SelectionStartProperty.AddOwner( typeof(TickBar), new FrameworkPropertyMetadata( -1.0d, FrameworkPropertyMetadataOptions.AffectsRender)); ///property. /// /// Logical position where the SelectionStart Tick will be drawn /// [Bindable(true), Category("Appearance")] public double SelectionStart { get { return (double) GetValue(SelectionStartProperty); } set { SetValue(SelectionStartProperty, value); } } ////// The DependencyProperty for the public static readonly DependencyProperty SelectionEndProperty = Slider.SelectionEndProperty.AddOwner( typeof(TickBar), new FrameworkPropertyMetadata( -1.0d, FrameworkPropertyMetadataOptions.AffectsRender)); ///property. /// /// Logical position where the SelectionEnd Tick will be drawn /// [Bindable(true), Category("Appearance")] public double SelectionEnd { get { return (double) GetValue(SelectionEndProperty); } set { SetValue(SelectionEndProperty, value); } } ////// The DependencyProperty for the public static readonly DependencyProperty IsSelectionRangeEnabledProperty = Slider.IsSelectionRangeEnabledProperty.AddOwner( typeof(TickBar), new FrameworkPropertyMetadata( BooleanBoxes.FalseBox, FrameworkPropertyMetadataOptions.AffectsRender)); ///property. /// /// IsSelectionRangeEnabled specifies whether to draw SelectionStart Tick and SelectionEnd Tick or not. /// [Bindable(true), Category("Appearance")] public bool IsSelectionRangeEnabled { get { return (bool) GetValue(IsSelectionRangeEnabledProperty); } set { SetValue(IsSelectionRangeEnabledProperty, BooleanBoxes.Box(value)); } } ////// DependencyProperty for public static readonly DependencyProperty TickFrequencyProperty = Slider.TickFrequencyProperty.AddOwner( typeof(TickBar), new FrameworkPropertyMetadata( 1.0, FrameworkPropertyMetadataOptions.AffectsRender)); ///property. /// /// TickFrequency property defines how the tick will be drawn. /// [Bindable(true), Category("Appearance")] public double TickFrequency { get { return (double) GetValue(TickFrequencyProperty); } set { SetValue(TickFrequencyProperty, value); } } ////// DependencyProperty for public static readonly DependencyProperty TicksProperty = Slider.TicksProperty.AddOwner( typeof(TickBar), new FrameworkPropertyMetadata( new FreezableDefaultValueFactory(DoubleCollection.Empty), FrameworkPropertyMetadataOptions.AffectsRender)); ///property. /// /// The Ticks property contains collection of value of type Double which /// are the logical positions use to draw the ticks. /// The property value is a [Bindable(true), Category("Appearance")] public DoubleCollection Ticks { get { return (DoubleCollection) GetValue(TicksProperty); } set { SetValue(TicksProperty, value); } } ///. /// /// DependencyProperty for IsDirectionReversed property. /// public static readonly DependencyProperty IsDirectionReversedProperty = Slider.IsDirectionReversedProperty.AddOwner( typeof(TickBar), new FrameworkPropertyMetadata( BooleanBoxes.FalseBox, FrameworkPropertyMetadataOptions.AffectsRender)); ////// The IsDirectionReversed property defines the direction of value incrementation. /// By default, if Tick's orientation is Horizontal, ticks will be drawn from left to right. /// (And, bottom to top for Vertical orientation). /// If IsDirectionReversed is 'true' the direction of the drawing will be in opposite direction. /// Ticks property contains collection of value of type Double which /// [Bindable(true), Category("Appearance")] public bool IsDirectionReversed { get { return (bool) GetValue(IsDirectionReversedProperty); } set { SetValue(IsDirectionReversedProperty, BooleanBoxes.Box(value)); } } ////// DependencyProperty for public static readonly DependencyProperty PlacementProperty = DependencyProperty.Register( "Placement", typeof(TickBarPlacement), typeof(TickBar), new FrameworkPropertyMetadata( TickBarPlacement.Top, FrameworkPropertyMetadataOptions.AffectsRender), new ValidateValueCallback(IsValidTickBarPlacement)); ///property. /// /// Placement property specified how the Tick will be placed. /// This property affects the way ticks are drawn. /// This property has type of [Bindable(true), Category("Appearance")] public TickBarPlacement Placement { get { return (TickBarPlacement) GetValue(PlacementProperty); } set { SetValue(PlacementProperty, value); } } private static bool IsValidTickBarPlacement(object o) { TickBarPlacement placement = (TickBarPlacement)o; return placement == TickBarPlacement.Left || placement == TickBarPlacement.Top || placement == TickBarPlacement.Right || placement == TickBarPlacement.Bottom; } ///. /// /// DependencyProperty for ReservedSpace property. /// public static readonly DependencyProperty ReservedSpaceProperty = DependencyProperty.Register( "ReservedSpace", typeof(double), typeof(TickBar), new FrameworkPropertyMetadata( 0d, FrameworkPropertyMetadataOptions.AffectsRender)); ////// TickBar will use ReservedSpaceProperty for left and right spacing (for horizontal orientation) or /// tob and bottom spacing (for vertical orienation). /// The space on both sides of TickBar is half of specified ReservedSpace. /// This property has type of [Bindable(true), Category("Appearance")] public double ReservedSpace { get { return (double) GetValue(ReservedSpaceProperty); } set { SetValue(ReservedSpaceProperty, value); } } ///. /// /// Draw ticks. /// Ticks can be draw in 8 diffrent ways depends on Placment property and IsDirectionReversed property. /// /// This function also draw selection-tick(s) if IsSelectionRangeEnabled is 'true' and /// SelectionStart and SelectionEnd are valid. /// /// The primary ticks (for Mininum and Maximum value) height will be 100% of TickBar's render size (use Width or Height /// depends on Placement property). /// /// The secondary ticks (all other ticks, including selection-tics) height will be 75% of TickBar's render size. /// /// Brush that use to fill ticks is specified by Shape.Fill property. /// /// Pen that use to draw ticks is specified by Shape.Pen property. /// protected override void OnRender(DrawingContext dc) { Size size = new Size(ActualWidth,ActualHeight); 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.Width -= ReservedSpace; 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.Width -= ReservedSpace; 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.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.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 = 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; bool hasModifiers; if (GetValueSource(TicksProperty, null, out hasModifiers) != BaseValueSourceInternal.Default || hasModifiers) { 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), }; PathGeometry geo = new PathGeometry(new PathFigure[] { new PathFigure(pt1, segments, 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 PathSegment[] { new LineSegment(pt2, true), new LineSegment(pt0, true), }; geo = new PathGeometry(new PathFigure[] { new PathFigure(pt1, segments, 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; bool hasModifiers; if (GetValueSource(TicksProperty, null, out hasModifiers) != BaseValueSourceInternal.Default || hasModifiers) { 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), }; PathGeometry geo = new PathGeometry(new PathFigure[] { new PathFigure(pt1, segments, 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 PathSegment[] { new LineSegment(pt2, true), new LineSegment(pt0, true), }; geo = new PathGeometry(new PathFigure[] { new PathFigure(pt1, segments, true) }); dc.DrawGeometry(Fill, pen, geo); } } if (snapsToDevicePixels) { xLines.Add(ActualWidth); yLines.Add(ActualHeight); VisualXSnappingGuidelines = xLines; VisualYSnappingGuidelines = yLines; } return; } private void BindToTemplatedParent(DependencyProperty target, DependencyProperty source) { if (!HasNonDefaultValue(target)) { Binding binding = new Binding(); binding.RelativeSource = RelativeSource.TemplatedParent; binding.Path = new PropertyPath(source); SetBinding(target, binding); } } ////// TickBar sets bindings on its properties to its TemplatedParent if the /// properties are not already set. /// internal override void OnPreApplyTemplate() { base.OnPreApplyTemplate(); Slider parent = TemplatedParent as Slider; if (parent != null) { BindToTemplatedParent(TicksProperty, Slider.TicksProperty); BindToTemplatedParent(TickFrequencyProperty, Slider.TickFrequencyProperty); BindToTemplatedParent(IsSelectionRangeEnabledProperty, Slider.IsSelectionRangeEnabledProperty); BindToTemplatedParent(SelectionStartProperty, Slider.SelectionStartProperty); BindToTemplatedParent(SelectionEndProperty, Slider.SelectionEndProperty); BindToTemplatedParent(MinimumProperty, Slider.MinimumProperty); BindToTemplatedParent(MaximumProperty, Slider.MaximumProperty); BindToTemplatedParent(IsDirectionReversedProperty, Slider.IsDirectionReversedProperty); if (!HasNonDefaultValue(ReservedSpaceProperty) && parent.Track != null) { Binding binding = new Binding(); binding.Source = parent.Track.Thumb; if (parent.Orientation == Orientation.Horizontal) { binding.Path = new PropertyPath(Thumb.ActualWidthProperty); } else { binding.Path = new PropertyPath(Thumb.ActualHeightProperty); } SetBinding(ReservedSpaceProperty, binding); } } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- OrderByBuilder.cs
- RequestValidator.cs
- SettingsAttributeDictionary.cs
- IPGlobalProperties.cs
- ThreadSafeMessageFilterTable.cs
- DynamicDiscoSearcher.cs
- RayHitTestParameters.cs
- UnsafeNativeMethods.cs
- XamlFilter.cs
- EditorZone.cs
- PlatformNotSupportedException.cs
- HelpKeywordAttribute.cs
- AuthenticationModuleElement.cs
- Equal.cs
- EastAsianLunisolarCalendar.cs
- WebHttpBehavior.cs
- CodeAssignStatement.cs
- MenuItemStyleCollection.cs
- TransactionFilter.cs
- Parallel.cs
- XmlTextAttribute.cs
- UnsupportedPolicyOptionsException.cs
- SourceItem.cs
- UIElementParagraph.cs
- LoginView.cs
- WinFormsUtils.cs
- ProgressiveCrcCalculatingStream.cs
- BaseEntityWrapper.cs
- TextEditorThreadLocalStore.cs
- PrintPreviewGraphics.cs
- ToolboxCategoryItems.cs
- Policy.cs
- XPathPatternBuilder.cs
- SignedXml.cs
- EntityDataSourceWrapperCollection.cs
- BaseComponentEditor.cs
- AssociatedControlConverter.cs
- TypeLibConverter.cs
- Descriptor.cs
- CodeExporter.cs
- ConnectionModeReader.cs
- NativeCppClassAttribute.cs
- IdentityVerifier.cs
- InputBuffer.cs
- InputReportEventArgs.cs
- HttpChannelListener.cs
- BypassElement.cs
- WinEventHandler.cs
- LinqDataSourceSelectEventArgs.cs
- Point3DConverter.cs
- DataServiceRequestException.cs
- DataGridHeaderBorder.cs
- UriTemplatePathSegment.cs
- IndicShape.cs
- FrameworkContentElement.cs
- RelationshipWrapper.cs
- XamlWriter.cs
- OleDbParameter.cs
- SemaphoreSecurity.cs
- mediapermission.cs
- ErrorProvider.cs
- ModulesEntry.cs
- OnOperation.cs
- DesignObjectWrapper.cs
- RIPEMD160.cs
- ActivityCodeDomSerializer.cs
- DetailsView.cs
- StorageInfo.cs
- ResourceDisplayNameAttribute.cs
- ContentFileHelper.cs
- EmptyCollection.cs
- ToolStripDropDownItem.cs
- DbTypeMap.cs
- Stack.cs
- CachedResourceDictionaryExtension.cs
- ShapeTypeface.cs
- XmlSchema.cs
- MSAAWinEventWrap.cs
- TrackingStringDictionary.cs
- XPathQilFactory.cs
- Substitution.cs
- WsdlBuildProvider.cs
- TypedOperationInfo.cs
- ExclusiveNamedPipeTransportManager.cs
- SerializationInfo.cs
- FontNamesConverter.cs
- PolicyChain.cs
- Decoder.cs
- SEHException.cs
- SignedXml.cs
- ThreadSafeList.cs
- MenuRendererClassic.cs
- BoundPropertyEntry.cs
- WindowsTokenRoleProvider.cs
- WindowVisualStateTracker.cs
- ThicknessAnimationUsingKeyFrames.cs
- PictureBox.cs
- XPathAncestorIterator.cs
- XsdDateTime.cs
- DirectoryNotFoundException.cs