PageRenderTime 150ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/MahApps.Metro/Controls/RangeSlider.cs

https://github.com/smiron/MahApps.Metro
C# | 2439 lines | 2017 code | 233 blank | 189 comment | 391 complexity | 69e258185c7f33d9ebf3c7c05a756a8e MD5 | raw file
Possible License(s): CC-BY-SA-3.0

Large files files are truncated, but you can click here to view the full file

  1. using System;
  2. using System.ComponentModel;
  3. using System.Globalization;
  4. using System.Windows;
  5. using System.Windows.Controls;
  6. using System.Windows.Controls.Primitives;
  7. using System.Windows.Input;
  8. using System.Windows.Threading;
  9. namespace MahApps.Metro.Controls
  10. {
  11. public delegate void RangeSelectionChangedEventHandler(object sender, RangeSelectionChangedEventArgs e);
  12. public delegate void RangeParameterChangedEventHandler(object sender, RangeParameterChangedEventArgs e);
  13. /// <summary>
  14. /// A slider control with the ability to select a range between two values.
  15. /// </summary>
  16. [DefaultEvent("RangeSelectionChanged"),
  17. TemplatePart(Name = "PART_Container", Type = typeof(StackPanel)),
  18. TemplatePart(Name = "PART_RangeSliderContainer", Type = typeof(StackPanel)),
  19. TemplatePart(Name = "PART_LeftEdge", Type = typeof(RepeatButton)),
  20. TemplatePart(Name = "PART_RightEdge", Type = typeof(RepeatButton)),
  21. TemplatePart(Name = "PART_LeftThumb", Type = typeof(Thumb)),
  22. TemplatePart(Name = "PART_MiddleThumb", Type = typeof(Thumb)),
  23. TemplatePart(Name = "PART_PART_TopTick", Type = typeof(TickBar)),
  24. TemplatePart(Name = "PART_PART_BottomTick", Type = typeof(TickBar)),
  25. TemplatePart(Name = "PART_RightThumb", Type = typeof(Thumb))]
  26. public class RangeSlider : RangeBase
  27. {
  28. #region Routed UI commands
  29. public static RoutedUICommand MoveBack = new RoutedUICommand("MoveBack", "MoveBack", typeof (RangeSlider),
  30. new InputGestureCollection(new InputGesture[] {new KeyGesture(Key.B, ModifierKeys.Control)}));
  31. public static RoutedUICommand MoveForward = new RoutedUICommand("MoveForward", "MoveForward",
  32. typeof (RangeSlider),
  33. new InputGestureCollection(new InputGesture[] {new KeyGesture(Key.F, ModifierKeys.Control)}));
  34. public static RoutedUICommand MoveAllForward = new RoutedUICommand("MoveAllForward", "MoveAllForward",
  35. typeof (RangeSlider),
  36. new InputGestureCollection(new InputGesture[] {new KeyGesture(Key.F, ModifierKeys.Alt)}));
  37. public static RoutedUICommand MoveAllBack = new RoutedUICommand("MoveAllBack", "MoveAllBack",
  38. typeof (RangeSlider),
  39. new InputGestureCollection(new InputGesture[] {new KeyGesture(Key.B, ModifierKeys.Alt)}));
  40. #endregion
  41. #region Routed events
  42. public static readonly RoutedEvent RangeSelectionChangedEvent =
  43. EventManager.RegisterRoutedEvent("RangeSelectionChanged", RoutingStrategy.Bubble,
  44. typeof (RangeSelectionChangedEventHandler), typeof (RangeSlider));
  45. public static readonly RoutedEvent LowerValueChangedEvent =
  46. EventManager.RegisterRoutedEvent("LowerValueChanged", RoutingStrategy.Bubble,
  47. typeof (RangeParameterChangedEventHandler), typeof (RangeSlider));
  48. public static readonly RoutedEvent UpperValueChangedEvent =
  49. EventManager.RegisterRoutedEvent("UpperValueChanged", RoutingStrategy.Bubble,
  50. typeof (RangeParameterChangedEventHandler), typeof (RangeSlider));
  51. public static readonly RoutedEvent LowerThumbDragStartedEvent =
  52. EventManager.RegisterRoutedEvent("LowerThumbDragStarted", RoutingStrategy.Bubble,
  53. typeof (DragStartedEventHandler), typeof (RangeSlider));
  54. public static readonly RoutedEvent LowerThumbDragCompletedEvent =
  55. EventManager.RegisterRoutedEvent("LowerThumbDragCompleted", RoutingStrategy.Bubble,
  56. typeof (DragCompletedEventHandler), typeof (RangeSlider));
  57. public static readonly RoutedEvent UpperThumbDragStartedEvent =
  58. EventManager.RegisterRoutedEvent("UpperThumbDragStarted", RoutingStrategy.Bubble,
  59. typeof (DragStartedEventHandler), typeof (RangeSlider));
  60. public static readonly RoutedEvent UpperThumbDragCompletedEvent =
  61. EventManager.RegisterRoutedEvent("UpperThumbDragCompleted", RoutingStrategy.Bubble,
  62. typeof (DragCompletedEventHandler), typeof (RangeSlider));
  63. public static readonly RoutedEvent CentralThumbDragStartedEvent =
  64. EventManager.RegisterRoutedEvent("CentralThumbDragStarted", RoutingStrategy.Bubble,
  65. typeof(DragStartedEventHandler), typeof(RangeSlider));
  66. public static readonly RoutedEvent CentralThumbDragCompletedEvent =
  67. EventManager.RegisterRoutedEvent("CentralThumbDragCompleted", RoutingStrategy.Bubble,
  68. typeof(DragCompletedEventHandler), typeof(RangeSlider));
  69. public static readonly RoutedEvent LowerThumbDragDeltaEvent =
  70. EventManager.RegisterRoutedEvent("LowerThumbDragDelta", RoutingStrategy.Bubble,
  71. typeof(DragDeltaEventHandler), typeof(RangeSlider));
  72. public static readonly RoutedEvent UpperThumbDragDeltaEvent =
  73. EventManager.RegisterRoutedEvent("UpperThumbDragDelta", RoutingStrategy.Bubble,
  74. typeof(DragDeltaEventHandler), typeof(RangeSlider));
  75. public static readonly RoutedEvent CentralThumbDragDeltaEvent =
  76. EventManager.RegisterRoutedEvent("CentralThumbDragDelta", RoutingStrategy.Bubble,
  77. typeof(DragDeltaEventHandler), typeof(RangeSlider));
  78. #endregion
  79. #region Event handlers
  80. public event RangeSelectionChangedEventHandler RangeSelectionChanged
  81. {
  82. add { AddHandler(RangeSelectionChangedEvent, value); }
  83. remove { RemoveHandler(RangeSelectionChangedEvent, value); }
  84. }
  85. public event RangeParameterChangedEventHandler LowerValueChanged
  86. {
  87. add { AddHandler(LowerValueChangedEvent, value); }
  88. remove { RemoveHandler(LowerValueChangedEvent, value); }
  89. }
  90. public event RangeParameterChangedEventHandler UpperValueChanged
  91. {
  92. add { AddHandler(UpperValueChangedEvent, value); }
  93. remove { RemoveHandler(UpperValueChangedEvent, value); }
  94. }
  95. public event DragStartedEventHandler LowerThumbDragStarted
  96. {
  97. add { AddHandler(LowerThumbDragStartedEvent, value); }
  98. remove { RemoveHandler(LowerThumbDragStartedEvent, value); }
  99. }
  100. public event DragCompletedEventHandler LowerThumbDragCompleted
  101. {
  102. add { AddHandler(LowerThumbDragCompletedEvent, value); }
  103. remove { RemoveHandler(LowerThumbDragCompletedEvent, value); }
  104. }
  105. public event DragStartedEventHandler UpperThumbDragStarted
  106. {
  107. add { AddHandler(UpperThumbDragStartedEvent, value); }
  108. remove { RemoveHandler(UpperThumbDragStartedEvent, value); }
  109. }
  110. public event DragCompletedEventHandler UpperThumbDragCompleted
  111. {
  112. add { AddHandler(UpperThumbDragCompletedEvent, value); }
  113. remove { RemoveHandler(UpperThumbDragCompletedEvent, value); }
  114. }
  115. public event DragStartedEventHandler CentralThumbDragStarted
  116. {
  117. add { AddHandler(CentralThumbDragStartedEvent, value); }
  118. remove { RemoveHandler(CentralThumbDragStartedEvent, value); }
  119. }
  120. public event DragCompletedEventHandler CentralThumbDragCompleted
  121. {
  122. add { AddHandler(CentralThumbDragCompletedEvent, value); }
  123. remove { RemoveHandler(CentralThumbDragCompletedEvent, value); }
  124. }
  125. public event DragDeltaEventHandler LowerThumbDragDelta
  126. {
  127. add { AddHandler(LowerThumbDragDeltaEvent, value); }
  128. remove { RemoveHandler(LowerThumbDragDeltaEvent, value); }
  129. }
  130. public event DragDeltaEventHandler UpperThumbDragDelta
  131. {
  132. add { AddHandler(UpperThumbDragDeltaEvent, value); }
  133. remove { RemoveHandler(UpperThumbDragDeltaEvent, value); }
  134. }
  135. public event DragDeltaEventHandler CentralThumbDragDelta
  136. {
  137. add { AddHandler(CentralThumbDragDeltaEvent, value); }
  138. remove { RemoveHandler(CentralThumbDragDeltaEvent, value); }
  139. }
  140. #endregion
  141. #region Dependency properties
  142. public static readonly DependencyProperty UpperValueProperty =
  143. DependencyProperty.Register("UpperValue", typeof (Double), typeof (RangeSlider),
  144. new FrameworkPropertyMetadata((Double) 0,
  145. FrameworkPropertyMetadataOptions.BindsTwoWayByDefault | FrameworkPropertyMetadataOptions.AffectsRender, RangesChanged, CoerceUpperValue));
  146. public static readonly DependencyProperty LowerValueProperty =
  147. DependencyProperty.Register("LowerValue", typeof(Double), typeof(RangeSlider),
  148. new FrameworkPropertyMetadata((Double)0,
  149. FrameworkPropertyMetadataOptions.BindsTwoWayByDefault | FrameworkPropertyMetadataOptions.AffectsRender, RangesChanged, CoerceLowerValue));
  150. public static readonly DependencyProperty MinRangeProperty =
  151. DependencyProperty.Register("MinRange", typeof (Double), typeof (RangeSlider),
  152. new FrameworkPropertyMetadata((Double)0, MinRangeChanged, CoerceMinRange), IsValidMinRange);
  153. public static readonly DependencyProperty MinRangeWidthProperty =
  154. DependencyProperty.Register("MinRangeWidth", typeof(Double), typeof(RangeSlider),
  155. new FrameworkPropertyMetadata(30.0, MinRangeWidthChanged, CoerceMinRangeWidth), IsValidMinRange);
  156. public static readonly DependencyProperty MoveWholeRangeProperty =
  157. DependencyProperty.Register("MoveWholeRange", typeof(Boolean), typeof(RangeSlider),
  158. new PropertyMetadata(false));
  159. public static readonly DependencyProperty ExtendedModeProperty =
  160. DependencyProperty.Register("ExtendedMode", typeof(Boolean), typeof(RangeSlider),
  161. new PropertyMetadata(false));
  162. public static readonly DependencyProperty IsSnapToTickEnabledProperty =
  163. DependencyProperty.Register("IsSnapToTickEnabled", typeof(Boolean), typeof(RangeSlider),
  164. new PropertyMetadata(false));
  165. public static readonly DependencyProperty OrientationProperty =
  166. DependencyProperty.Register("Orientation", typeof(Orientation), typeof(RangeSlider),
  167. new FrameworkPropertyMetadata(Orientation.Horizontal));
  168. public static readonly DependencyProperty TickFrequencyProperty =
  169. DependencyProperty.Register("TickFrequency", typeof(Double), typeof(RangeSlider),
  170. new FrameworkPropertyMetadata(1.0), IsValidTickFrequency);
  171. public static readonly DependencyProperty IsMoveToPointEnabledProperty =
  172. DependencyProperty.Register("IsMoveToPointEnabled", typeof(Boolean), typeof(RangeSlider),
  173. new PropertyMetadata(false));
  174. public static readonly DependencyProperty TickPlacementProperty =
  175. DependencyProperty.Register("TickPlacement", typeof(TickPlacement), typeof(RangeSlider),
  176. new FrameworkPropertyMetadata(TickPlacement.None));
  177. public static readonly DependencyProperty AutoToolTipPlacementProperty =
  178. DependencyProperty.Register("AutoToolTipPlacement", typeof(AutoToolTipPlacement), typeof(RangeSlider),
  179. new FrameworkPropertyMetadata(AutoToolTipPlacement.None));
  180. public static readonly DependencyProperty AutoToolTipPrecisionProperty =
  181. DependencyProperty.Register("AutoToolTipPrecision", typeof (Int32), typeof (RangeSlider),
  182. new FrameworkPropertyMetadata(0), IsValidPrecision);
  183. public static readonly DependencyProperty IntervalProperty =
  184. DependencyProperty.Register("Interval", typeof(Int32), typeof(RangeSlider),
  185. new FrameworkPropertyMetadata(100, IntervalChangedCallback), IsValidPrecision);
  186. /// <summary>
  187. /// Get/sets value how fast thumbs will move when user press on left/right/central with left mouse button (IsMoveToPoint must be set to FALSE)
  188. /// </summary>
  189. [Bindable(true), Category("Behavior")]
  190. public Int32 Interval
  191. {
  192. get { return (Int32)GetValue(IntervalProperty); }
  193. set { SetValue(IntervalProperty, value); }
  194. }
  195. /// <summary>
  196. /// Get/sets precision of the value, which displaying inside AutotToolTip
  197. /// </summary>
  198. [Bindable(true), Category("Appearance")]
  199. public Int32 AutoToolTipPrecision
  200. {
  201. get { return (Int32)GetValue(AutoToolTipPrecisionProperty); }
  202. set { SetValue(AutoToolTipPrecisionProperty, value); }
  203. }
  204. /// <summary>
  205. /// Get/sets tooltip, which will show while dragging thumbs and display currect value
  206. /// </summary>
  207. [Bindable(true), Category("Behavior")]
  208. public AutoToolTipPlacement AutoToolTipPlacement
  209. {
  210. get { return (AutoToolTipPlacement)GetValue(AutoToolTipPlacementProperty); }
  211. set { SetValue(AutoToolTipPlacementProperty, value); }
  212. }
  213. /// <summary>
  214. /// Get/sets tick placement position
  215. /// </summary>
  216. [Bindable(true), Category("Common")]
  217. public TickPlacement TickPlacement
  218. {
  219. get { return (TickPlacement)GetValue(TickPlacementProperty); }
  220. set { SetValue(TickPlacementProperty, value); }
  221. }
  222. /// <summary>
  223. /// Get/sets IsMoveToPoint feature which will enable/disable moving to exact point inside control when user clicked on it
  224. /// </summary>
  225. [Bindable(true), Category("Common")]
  226. public Boolean IsMoveToPointEnabled
  227. {
  228. get { return (Boolean)GetValue(IsMoveToPointEnabledProperty); }
  229. set { SetValue(IsMoveToPointEnabledProperty, value); }
  230. }
  231. /// <summary>
  232. /// Get/sets tickFrequency
  233. /// </summary>
  234. [Bindable(true), Category("Common")]
  235. public Double TickFrequency
  236. {
  237. get { return (Double)GetValue(TickFrequencyProperty); }
  238. set { SetValue(TickFrequencyProperty, value); }
  239. }
  240. /// <summary>
  241. /// Get/sets orientation of range slider
  242. /// </summary>
  243. [Bindable(true), Category("Common")]
  244. public Orientation Orientation
  245. {
  246. get { return (Orientation)GetValue(OrientationProperty); }
  247. set { SetValue(OrientationProperty, value); }
  248. }
  249. /// <summary>
  250. /// Get/sets whether possibility to make manipulations inside range with left/right mouse buttons + cotrol button
  251. /// </summary>
  252. [Bindable(true), Category("Appearance")]
  253. public Boolean IsSnapToTickEnabled
  254. {
  255. get { return (Boolean)GetValue(IsSnapToTickEnabledProperty); }
  256. set { SetValue(IsSnapToTickEnabledProperty, value); }
  257. }
  258. /// <summary>
  259. /// Get/sets whether possibility to make manipulations inside range with left/right mouse buttons + cotrol button
  260. /// </summary>
  261. [Bindable(true), Category("Behavior")]
  262. public Boolean ExtendedMode
  263. {
  264. get { return (Boolean)GetValue(ExtendedModeProperty); }
  265. set { SetValue(ExtendedModeProperty, value); }
  266. }
  267. /// <summary>
  268. /// Get/sets whether whole range will be moved when press on right/left/central part of control
  269. /// </summary>
  270. [Bindable(true), Category("Behavior")]
  271. public Boolean MoveWholeRange
  272. {
  273. get { return (Boolean)GetValue(MoveWholeRangeProperty); }
  274. set { SetValue(MoveWholeRangeProperty, value); }
  275. }
  276. /// <summary>
  277. /// Get/sets the minimal distance between two thumbs.
  278. /// </summary>
  279. [Bindable(true), Category("Common")]
  280. public Double MinRangeWidth
  281. {
  282. get { return (Double)GetValue(MinRangeWidthProperty); }
  283. set { SetValue(MinRangeWidthProperty, value); }
  284. }
  285. /// <summary>
  286. /// Get/sets the beginning of the range selection.
  287. /// </summary>
  288. [Bindable(true), Category("Common")]
  289. public Double LowerValue
  290. {
  291. get { return (Double) GetValue(LowerValueProperty); }
  292. set { SetValue(LowerValueProperty, value); }
  293. }
  294. /// <summary>
  295. /// Get/sets the end of the range selection.
  296. /// </summary>
  297. [Bindable(true), Category("Common")]
  298. public Double UpperValue
  299. {
  300. get { return (Double) GetValue(UpperValueProperty); }
  301. set { SetValue(UpperValueProperty, value); }
  302. }
  303. /// <summary>
  304. /// Get/sets the minimum range that can be selected.
  305. /// </summary>
  306. [Bindable(true), Category("Common")]
  307. public Double MinRange
  308. {
  309. get { return (Double) GetValue(MinRangeProperty); }
  310. set { SetValue(MinRangeProperty, value); }
  311. }
  312. #endregion
  313. #region Variables
  314. private const double Epsilon = 0.00000153;
  315. private Boolean _internalUpdate;
  316. private Thumb _centerThumb;
  317. private Thumb _leftThumb;
  318. private Thumb _rightThumb;
  319. private RepeatButton _leftButton;
  320. private RepeatButton _rightButton;
  321. private StackPanel _visualElementsContainer;
  322. private StackPanel _container;
  323. private Double _movableWidth;
  324. private readonly DispatcherTimer _timer;
  325. private uint _tickCount;
  326. private Double _currentpoint;
  327. private Boolean _isInsideRange;
  328. private Boolean _centerThumbBlocked;
  329. private Direction _direction;
  330. private ButtonType _bType;
  331. private Point _position;
  332. private Point _basePoint;
  333. private Double _currenValue;
  334. private Double _density;
  335. private ToolTip _autoToolTip;
  336. Double _oldLower;
  337. Double _oldUpper;
  338. private Boolean _isMoved;
  339. private Boolean _roundToPrecision;
  340. private Int32 _precision;
  341. #endregion
  342. public double MovableRange
  343. {
  344. get
  345. {
  346. return Maximum - Minimum - MinRange;
  347. }
  348. }
  349. public RangeSlider()
  350. {
  351. CommandBindings.Add(new CommandBinding(MoveBack, MoveBackHandler));
  352. CommandBindings.Add(new CommandBinding(MoveForward, MoveForwardHandler));
  353. CommandBindings.Add(new CommandBinding(MoveAllForward, MoveAllForwardHandler));
  354. CommandBindings.Add(new CommandBinding(MoveAllBack, MoveAllBackHandler));
  355. DependencyPropertyDescriptor.FromProperty(ActualWidthProperty, typeof(RangeSlider)).AddValueChanged(this, delegate { ReCalculateSize(); });
  356. DependencyPropertyDescriptor.FromProperty(ActualHeightProperty, typeof(RangeSlider)).AddValueChanged(this, delegate { ReCalculateSize(); });
  357. _timer = new DispatcherTimer();
  358. _timer.Tick += MoveToNextValue;
  359. _timer.Interval = TimeSpan.FromMilliseconds(Interval);
  360. }
  361. static RangeSlider()
  362. {
  363. DefaultStyleKeyProperty.OverrideMetadata(typeof(RangeSlider), new FrameworkPropertyMetadata(typeof(RangeSlider)));
  364. MinimumProperty.OverrideMetadata(typeof(RangeSlider), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsMeasure, MinPropertyChangedCallback, CoerceMinimum));
  365. MaximumProperty.OverrideMetadata(typeof(RangeSlider), new FrameworkPropertyMetadata(100.0, FrameworkPropertyMetadataOptions.AffectsMeasure, MaxPropertyChangedCallback, CoerceMaximum));
  366. }
  367. /// <summary>
  368. /// Responds to a change in the value of the <see cref="P:System.Windows.Controls.Primitives.RangeBase.Minimum"/> property.
  369. /// </summary>
  370. /// <param name="oldMinimum">The old value of the <see cref="P:System.Windows.Controls.Primitives.RangeBase.Minimum"/> property.</param><param name="newMinimum">The new value of the <see cref="P:System.Windows.Controls.Primitives.RangeBase.Minimum"/> property.</param>
  371. protected override void OnMinimumChanged(double oldMinimum, double newMinimum)
  372. {
  373. ReCalculateSize();
  374. }
  375. /// <summary>
  376. /// Responds to a change in the value of the <see cref="P:System.Windows.Controls.Primitives.RangeBase.Maximum"/> property.
  377. /// </summary>
  378. /// <param name="oldMaximum">The old value of the <see cref="P:System.Windows.Controls.Primitives.RangeBase.Maximum"/> property.</param><param name="newMaximum">The new value of the <see cref="P:System.Windows.Controls.Primitives.RangeBase.Maximum"/> property.</param>
  379. protected override void OnMaximumChanged(double oldMaximum, double newMaximum)
  380. {
  381. ReCalculateSize();
  382. }
  383. void MoveAllBackHandler(object sender, ExecutedRoutedEventArgs e)
  384. {
  385. ResetSelection(true);
  386. }
  387. void MoveAllForwardHandler(object sender, ExecutedRoutedEventArgs e)
  388. {
  389. ResetSelection(false);
  390. }
  391. void MoveBackHandler(object sender, ExecutedRoutedEventArgs e)
  392. {
  393. MoveSelection(true);
  394. }
  395. void MoveForwardHandler(object sender, ExecutedRoutedEventArgs e)
  396. {
  397. MoveSelection(false);
  398. }
  399. private static void MoveThumb(FrameworkElement x, FrameworkElement y, double horizonalChange,
  400. Orientation orientation)
  401. {
  402. double change;
  403. if (orientation == Orientation.Horizontal)
  404. {
  405. if (!Double.IsNaN(x.Width) && !Double.IsNaN(y.Width))
  406. {
  407. if (horizonalChange < 0) //slider went left
  408. {
  409. change = GetChangeKeepPositive(x.Width, horizonalChange);
  410. if (x.Name == "PART_MiddleThumb")
  411. {
  412. if (x.Width > x.MinWidth)
  413. {
  414. if (x.Width + change < x.MinWidth)
  415. {
  416. double dif = x.Width - x.MinWidth;
  417. x.Width = x.MinWidth;
  418. y.Width += dif;
  419. }
  420. else
  421. {
  422. x.Width += change;
  423. y.Width -= change;
  424. }
  425. }
  426. }
  427. else
  428. {
  429. x.Width += change;
  430. y.Width -= change;
  431. }
  432. }
  433. else if (horizonalChange > 0) //slider went right if(horizontal change == 0 do nothing)
  434. {
  435. change = -GetChangeKeepPositive(y.Width, -horizonalChange);
  436. if (y.Name == "PART_MiddleThumb")
  437. {
  438. if (y.Width > y.MinWidth)
  439. {
  440. if (y.Width - change < y.MinWidth)
  441. {
  442. double dif = y.Width - y.MinWidth;
  443. y.Width = y.MinWidth;
  444. x.Width += dif;
  445. }
  446. else
  447. {
  448. x.Width += change;
  449. y.Width -= change;
  450. }
  451. }
  452. }
  453. else
  454. {
  455. x.Width += change;
  456. y.Width -= change;
  457. }
  458. }
  459. }
  460. }
  461. else if (orientation == Orientation.Vertical)
  462. {
  463. if (!Double.IsNaN(x.Height) && !Double.IsNaN(y.Height))
  464. {
  465. if (horizonalChange < 0) //slider went up
  466. {
  467. change = -GetChangeKeepPositive(y.Height, horizonalChange);//get positive number
  468. if (y.Name == "PART_MiddleThumb")
  469. {
  470. if (y.Height > y.MinHeight)
  471. {
  472. if (y.Height - change < y.MinHeight)
  473. {
  474. double dif = y.Height - y.MinHeight;
  475. y.Height = y.MinHeight;
  476. x.Height += dif;
  477. }
  478. else
  479. {
  480. x.Height += change;
  481. y.Height -= change;
  482. }
  483. }
  484. }
  485. else
  486. {
  487. x.Height += change;
  488. y.Height -= change;
  489. }
  490. }
  491. else if (horizonalChange > 0) //slider went down if(horizontal change == 0 do nothing)
  492. {
  493. change = GetChangeKeepPositive(x.Height, -horizonalChange);//get negative number
  494. if (x.Name == "PART_MiddleThumb")
  495. {
  496. if (x.Height > y.MinHeight)
  497. {
  498. if (x.Height + change < x.MinHeight)
  499. {
  500. double dif = x.Height - x.MinHeight;
  501. x.Height = x.MinHeight;
  502. y.Height += dif;
  503. }
  504. else
  505. {
  506. x.Height += change;
  507. y.Height -= change;
  508. }
  509. }
  510. }
  511. else
  512. {
  513. x.Height += change;
  514. y.Height -= change;
  515. }
  516. }
  517. }
  518. }
  519. }
  520. private static void MoveThumb(FrameworkElement x, FrameworkElement y, double horizonalChange,
  521. Orientation orientation, out Direction direction)
  522. {
  523. double change;
  524. direction = Direction.Increase;
  525. if (orientation == Orientation.Horizontal)
  526. {
  527. if (!Double.IsNaN(x.Width) && !Double.IsNaN(y.Width))
  528. {
  529. if (horizonalChange < 0) //slider went left
  530. {
  531. direction = Direction.Decrease;
  532. change = GetChangeKeepPositive(x.Width, horizonalChange);
  533. if (x.Name == "PART_MiddleThumb")
  534. {
  535. if (x.Width > x.MinWidth)
  536. {
  537. if (x.Width + change < x.MinWidth)
  538. {
  539. double dif = x.Width - x.MinWidth;
  540. x.Width = x.MinWidth;
  541. y.Width += dif;
  542. }
  543. else
  544. {
  545. x.Width += change;
  546. y.Width -= change;
  547. }
  548. }
  549. }
  550. else
  551. {
  552. x.Width += change;
  553. y.Width -= change;
  554. }
  555. }
  556. else if (horizonalChange > 0) //slider went right if(horizontal change == 0 do nothing)
  557. {
  558. direction = Direction.Increase;
  559. change = -GetChangeKeepPositive(y.Width, -horizonalChange);
  560. if (y.Name == "PART_MiddleThumb")
  561. {
  562. if (y.Width > y.MinWidth)
  563. {
  564. if (y.Width - change < y.MinWidth)
  565. {
  566. double dif = y.Width - y.MinWidth;
  567. y.Width = y.MinWidth;
  568. x.Width += dif;
  569. }
  570. else
  571. {
  572. x.Width += change;
  573. y.Width -= change;
  574. }
  575. }
  576. }
  577. else
  578. {
  579. x.Width += change;
  580. y.Width -= change;
  581. }
  582. }
  583. }
  584. }
  585. else
  586. {
  587. if (!Double.IsNaN(x.Height) && !Double.IsNaN(y.Height))
  588. {
  589. if (horizonalChange < 0) //slider went up
  590. {
  591. direction = Direction.Increase;
  592. change = -GetChangeKeepPositive(y.Height, horizonalChange);//get positive number
  593. if (y.Name == "PART_MiddleThumb")
  594. {
  595. if (y.Height > y.MinHeight)
  596. {
  597. if (y.Height - change < y.MinHeight)
  598. {
  599. double dif = y.Height - y.MinHeight;
  600. y.Height = y.MinHeight;
  601. x.Height += dif;
  602. }
  603. else
  604. {
  605. x.Height += change;
  606. y.Height -= change;
  607. }
  608. }
  609. }
  610. else
  611. {
  612. x.Height += change;
  613. y.Height -= change;
  614. }
  615. }
  616. else if (horizonalChange > 0) //slider went down if(horizontal change == 0 do nothing)
  617. {
  618. direction = Direction.Decrease;
  619. change = GetChangeKeepPositive(x.Height, -horizonalChange);//get negative number
  620. if (x.Name == "PART_MiddleThumb")
  621. {
  622. if (x.Height > y.MinHeight)
  623. {
  624. if (x.Height + change < x.MinHeight)
  625. {
  626. double dif = x.Height - x.MinHeight;
  627. x.Height = x.MinHeight;
  628. y.Height += dif;
  629. }
  630. else
  631. {
  632. x.Height += change;
  633. y.Height -= change;
  634. }
  635. }
  636. }
  637. else
  638. {
  639. x.Height += change;
  640. y.Height -= change;
  641. }
  642. }
  643. }
  644. }
  645. }
  646. //Recalculation of Control Height or Width
  647. private void ReCalculateSize()
  648. {
  649. if (_leftButton != null && _rightButton != null && _centerThumb != null)
  650. {
  651. if (Orientation == Orientation.Horizontal)
  652. {
  653. _movableWidth =
  654. Math.Max(
  655. ActualWidth - _rightThumb.ActualWidth - _leftThumb.ActualWidth - MinRangeWidth, 1);
  656. if (MovableRange <= 0)
  657. {
  658. _leftButton.Width = Double.NaN;
  659. _rightButton.Width = Double.NaN;
  660. }
  661. else
  662. {
  663. _leftButton.Width = Math.Max(_movableWidth * (LowerValue - Minimum) / MovableRange, 0);
  664. _rightButton.Width = Math.Max(_movableWidth * (Maximum - UpperValue) / MovableRange, 0);
  665. }
  666. if (IsValidDouble(_rightButton.Width) && IsValidDouble(_leftButton.Width))
  667. {
  668. _centerThumb.Width =
  669. Math.Max(
  670. ActualWidth - (_leftButton.Width + _rightButton.Width + _rightThumb.ActualWidth +
  671. _leftThumb.ActualWidth), 0);
  672. }
  673. else
  674. {
  675. _centerThumb.Width =
  676. Math.Max(
  677. ActualWidth - (_rightThumb.ActualWidth + _leftThumb.ActualWidth), 0);
  678. }
  679. }
  680. else if (Orientation == Orientation.Vertical)
  681. {
  682. _movableWidth =
  683. Math.Max(
  684. ActualHeight - _rightThumb.ActualHeight - _leftThumb.ActualHeight - MinRangeWidth, 1);
  685. if (MovableRange <= 0)
  686. {
  687. _leftButton.Height = Double.NaN;
  688. _rightButton.Height = Double.NaN;
  689. }
  690. else
  691. {
  692. _leftButton.Height = Math.Max(_movableWidth * (LowerValue - Minimum) / MovableRange, 0);
  693. _rightButton.Height = Math.Max(_movableWidth * (Maximum - UpperValue) / MovableRange, 0);
  694. }
  695. if (IsValidDouble(_rightButton.Height) && IsValidDouble(_leftButton.Height))
  696. {
  697. _centerThumb.Height =
  698. Math.Max(
  699. ActualHeight - (_leftButton.Height + _rightButton.Height + _rightThumb.ActualHeight +
  700. _leftThumb.ActualHeight), 0);
  701. }
  702. else
  703. {
  704. _centerThumb.Height =
  705. Math.Max(
  706. ActualHeight - (_rightThumb.ActualHeight + _leftThumb.ActualHeight), 0);
  707. }
  708. }
  709. _density = _movableWidth / MovableRange;
  710. }
  711. }
  712. /*
  713. //private void ReCalculateRangeSelected(bool reCalculateLowerValue, bool reCalculateUpperValue)
  714. //{
  715. // _internalUpdate = true; //set flag to signal that the properties are being set by the object itself
  716. // if (reCalculateLowerValue)
  717. // {
  718. // _oldLower = LowerValue;
  719. // double width = Orientation == Orientation.Horizontal ? _leftButton.Width : _leftButton.Height;
  720. // //Check first if button width is not Double.NaN
  721. // if (IsValidDouble(width))
  722. // {
  723. // // Make sure to get exactly rangestart if thumb is at the start
  724. // double lower = Equals(width, 0.0)
  725. // ? Minimum
  726. // : Math.Max(Minimum, (Minimum + MovableRange * width / _movableWidth));
  727. // if (!_isMoved)
  728. // {
  729. // LowerValue = _roundToPrecision ? Math.Round(lower, _precision) : lower;
  730. // }
  731. // else
  732. // {
  733. // LowerValue = lower;
  734. // }
  735. // }
  736. // }
  737. // if (reCalculateUpperValue)
  738. // {
  739. // _oldUpper = UpperValue;
  740. // double width = Orientation == Orientation.Horizontal ? _rightButton.Width : _rightButton.Height;
  741. // //Check first if button width is not Double.NaN
  742. // if (IsValidDouble(width))
  743. // {
  744. // // Make sure to get exactly rangestop if thumb is at the end
  745. // double upper = Equals(width, 0.0)
  746. // ? Maximum
  747. // : Math.Min(Maximum, (Maximum - MovableRange * width / _movableWidth));
  748. // if (!_isMoved)
  749. // {
  750. // UpperValue = _roundToPrecision
  751. // ? Math.Round(upper, _precision)
  752. // : upper;
  753. // }
  754. // else
  755. // {
  756. // UpperValue = upper;
  757. // }
  758. // }
  759. // }
  760. // _roundToPrecision = false;
  761. // _internalUpdate = false; //set flag to signal that the properties are being set by the object itself
  762. // if (reCalculateLowerValue || reCalculateUpperValue)
  763. // {
  764. // if (!Equals(_oldLower, LowerValue) || !Equals(_oldUpper, UpperValue))
  765. // {
  766. // //raise the RangeSelectionChanged event
  767. // OnRangeSelectionChanged(new RangeSelectionChangedEventArgs(LowerValue, UpperValue, _oldLower,
  768. // _oldUpper));
  769. // }
  770. // }
  771. // if (reCalculateLowerValue && !Equals(_oldLower, LowerValue))
  772. // {
  773. // OnRangeParameterChanged(
  774. // new RangeParameterChangedEventArgs(RangeParameterChangeType.Lower, _oldLower, LowerValue),
  775. // LowerValueChangedEvent);
  776. // }
  777. // if (reCalculateUpperValue && !Equals(_oldUpper, UpperValue))
  778. // {
  779. // OnRangeParameterChanged(
  780. // new RangeParameterChangedEventArgs(RangeParameterChangeType.Upper, _oldUpper, UpperValue),
  781. // UpperValueChangedEvent);
  782. // }
  783. //}
  784. */
  785. //Method calculates new values when IsSnapToTickEnabled = FALSE
  786. private void ReCalculateRangeSelected(bool reCalculateLowerValue, bool reCalculateUpperValue, Direction direction)
  787. {
  788. _internalUpdate = true; //set flag to signal that the properties are being set by the object itself
  789. if (direction == Direction.Increase)
  790. {
  791. if (reCalculateUpperValue)
  792. {
  793. _oldUpper = UpperValue;
  794. double width = Orientation == Orientation.Horizontal ? _rightButton.Width : _rightButton.Height;
  795. //Check first if button width is not Double.NaN
  796. if (IsValidDouble(width))
  797. {
  798. // Make sure to get exactly rangestop if thumb is at the end
  799. double upper = Equals(width, 0.0)
  800. ? Maximum
  801. : Math.Min(Maximum, (Maximum - MovableRange * width / _movableWidth));
  802. if (!_isMoved)
  803. {
  804. UpperValue = _roundToPrecision
  805. ? Math.Round(upper, _precision)
  806. : upper;
  807. }
  808. else
  809. {
  810. UpperValue = upper;
  811. }
  812. }
  813. }
  814. if (reCalculateLowerValue)
  815. {
  816. _oldLower = LowerValue;
  817. double width = Orientation == Orientation.Horizontal ? _leftButton.Width : _leftButton.Height;
  818. //Check first if button width is not Double.NaN
  819. if (IsValidDouble(width))
  820. {
  821. // Make sure to get exactly rangestart if thumb is at the start
  822. double lower = Equals(width, 0.0)
  823. ? Minimum
  824. : Math.Max(Minimum, (Minimum + MovableRange*width/_movableWidth));
  825. if (!_isMoved)
  826. {
  827. LowerValue = _roundToPrecision ? Math.Round(lower, _precision) : lower;
  828. }
  829. else
  830. {
  831. LowerValue = lower;
  832. }
  833. }
  834. }
  835. }
  836. else
  837. {
  838. if (reCalculateLowerValue)
  839. {
  840. _oldLower = LowerValue;
  841. double width = Orientation == Orientation.Horizontal ? _leftButton.Width : _leftButton.Height;
  842. //Check first if button width is not Double.NaN
  843. if (IsValidDouble(width))
  844. {
  845. // Make sure to get exactly rangestart if thumb is at the start
  846. double lower = Equals(width, 0.0)
  847. ? Minimum
  848. : Math.Max(Minimum, (Minimum + MovableRange * width / _movableWidth));
  849. if (!_isMoved)
  850. {
  851. LowerValue = _roundToPrecision ? Math.Round(lower, _precision) : lower;
  852. }
  853. else
  854. {
  855. LowerValue = lower;
  856. }
  857. }
  858. }
  859. if (reCalculateUpperValue)
  860. {
  861. _oldUpper = UpperValue;
  862. double width = Orientation == Orientation.Horizontal ? _rightButton.Width : _rightButton.Height;
  863. //Check first if button width is not Double.NaN
  864. if (IsValidDouble(width))
  865. {
  866. // Make sure to get exactly rangestop if thumb is at the end
  867. double upper = Equals(width, 0.0)
  868. ? Maximum
  869. : Math.Min(Maximum, (Maximum - MovableRange * width / _movableWidth));
  870. if (!_isMoved)
  871. {
  872. UpperValue = _roundToPrecision
  873. ? Math.Round(upper, _precision)
  874. : upper;
  875. }
  876. else
  877. {
  878. UpperValue = upper;
  879. }
  880. }
  881. }
  882. }
  883. _roundToPrecision = false;
  884. _internalUpdate = false; //set flag to signal that the properties are being set by the object itself
  885. if (reCalculateLowerValue || reCalculateUpperValue)
  886. {
  887. if (!Equals(_oldLower, LowerValue) || !Equals(_oldUpper, UpperValue))
  888. {
  889. //raise the RangeSelectionChanged event
  890. OnRangeSelectionChanged(new RangeSelectionChangedEventArgs(LowerValue, UpperValue, _oldLower,
  891. _oldUpper));
  892. }
  893. }
  894. if (reCalculateLowerValue && !Equals(_oldLower, LowerValue))
  895. {
  896. OnRangeParameterChanged(
  897. new RangeParameterChangedEventArgs(RangeParameterChangeType.Lower, _oldLower, LowerValue),
  898. LowerValueChangedEvent);
  899. }
  900. if (reCalculateUpperValue && !Equals(_oldUpper, UpperValue))
  901. {
  902. OnRangeParameterChanged(
  903. new RangeParameterChangedEventArgs(RangeParameterChangeType.Upper, _oldUpper, UpperValue),
  904. UpperValueChangedEvent);
  905. }
  906. }
  907. //Method used for cheking and setting correct values when IsSnapToTickEnable = TRUE (When thumb moving separately)
  908. private void ReCalculateRangeSelected(bool reCalculateLowerValue, bool reCalculateUpperValue, double value, Direction direction)
  909. {
  910. _internalUpdate = true; //set flag to signal that the properties are being set by the object itself
  911. if (reCalculateLowerValue)
  912. {
  913. _oldLower = LowerValue;
  914. double lower = 0;
  915. if (IsSnapToTickEnabled)
  916. {
  917. if (direction == Direction.Increase)
  918. {
  919. lower = Math.Min(UpperValue - MinRange, value);
  920. }
  921. else
  922. {
  923. lower = Math.Max(Minimum, value);
  924. }
  925. }
  926. if (!TickFrequency.ToString(CultureInfo.InvariantCulture).ToLower().Contains("e+") &&
  927. TickFrequency.ToString(CultureInfo.InvariantCulture).Contains("."))
  928. {
  929. //decimal part is for cutting value exactly on that number of digits, which has TickFrequency to have correct values
  930. String[] decimalPart = TickFrequency.ToString(CultureInfo.InvariantCulture).Split('.');
  931. LowerValue = Math.Round(lower, decimalPart[1].Length, MidpointRounding.AwayFromZero);
  932. }
  933. else
  934. {
  935. LowerValue = lower;
  936. }
  937. }
  938. if (reCalculateUpperValue)
  939. {
  940. _oldUpper = UpperValue;
  941. double upper = 0;
  942. if (IsSnapToTickEnabled)
  943. {
  944. if (direction == Direction.Increase)
  945. {
  946. upper = Math.Min(value, Maximum);
  947. }
  948. else
  949. {
  950. upper = Math.Max(LowerValue + MinRange, value);
  951. }
  952. }
  953. if (!TickFrequency.ToString(CultureInfo.InvariantCulture).ToLower().Contains("e+") &&
  954. TickFrequency.ToString(CultureInfo.InvariantCulture).Contains("."))
  955. {
  956. String[] decimalPart = TickFrequency.ToString(CultureInfo.InvariantCulture).Split('.');
  957. UpperValue = Math.Round(upper, decimalPart[1].Length, MidpointRounding.AwayFromZero);
  958. }
  959. else
  960. {
  961. UpperValue = upper;
  962. }
  963. }
  964. _internalUpdate = false; //set flag to signal that the properties are being set by the object itself
  965. if (reCalculateLowerValue || reCalculateUpperValue)
  966. {
  967. if (!Equals(_oldLower, LowerValue) || !Equals(_oldUpper, UpperValue))
  968. {
  969. //raise the RangeSelectionChanged event
  970. OnRangeSelectionChanged(new RangeSelectionChangedEventArgs(LowerValue, UpperValue, _oldLower,
  971. _oldUpper));
  972. }
  973. }
  974. if (reCalculateLowerValue && !Equals(_oldLower, LowerValue))
  975. {
  976. OnRangeParameterChanged(
  977. new RangeParameterChangedEventArgs(RangeParameterChangeType.Lower, _oldLower, LowerValue),
  978. LowerValueChangedEvent);
  979. }
  980. if (reCalculateUpperValue && !Equals(_oldUpper, UpperValue))
  981. {
  982. OnRangeParameterChanged(
  983. new RangeParameterChangedEventArgs(RangeParameterChangeType.Upper, _oldUpper, UpperValue),
  984. UpperValueChangedEvent);
  985. }
  986. }
  987. //Method used for cheking and setting correct values when IsSnapToTickEnable = TRUE (When thumb moving together)
  988. private void ReCalculateRangeSelected(double newLower, double newUpper, Direction direction)
  989. {
  990. double lower = 0, upper = 0;
  991. _internalUpdate = true; //set flag to signal that the properties are being set by the object itself
  992. _oldLower = LowerValue;
  993. _oldUpper = UpperValue;
  994. if (IsSnapToTickEnabled)
  995. {
  996. if (direction == Direction.Increase)
  997. {
  998. lower = Math.Min(newLower, Maximum-(UpperValue - LowerValue));
  999. upper = Math.Min(newUpper, Maximum);
  1000. }
  1001. else
  1002. {
  1003. lower = Math.Max(newLower, Minimum);
  1004. upper = Math.Max(Minimum+(UpperValue - LowerValue), newUpper);
  1005. }
  1006. if (!TickFrequency.ToString(CultureInfo.InvariantCulture).ToLower().Contains("e+") &&
  1007. TickFrequency.ToString(CultureInfo.InvariantCulture).Contains("."))
  1008. {
  1009. //decimal part is for cutting value exactly on that number of digits, which has TickFrequency to have correct values
  1010. String[] decimalPart = TickFrequency.ToString(CultureInfo.InvariantCulture).Split('.');
  1011. //used when whole range decreasing to have correct updated values (lower first, upper - second)
  1012. if (direction == Direction.Decrease)
  1013. {
  1014. LowerValue = Math.Round(lower, decimalPart[1].Length,

Large files files are truncated, but you can click here to view the full file