PageRenderTime 54ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/V4/ChartControls/ContinuousAxisPanel.cs

#
C# | 687 lines | 561 code | 74 blank | 52 comment | 115 complexity | fc2fa078c379bc3eac00a5a0b195b268 MD5 | raw file
  1. //===================================================================================
  2. // Microsoft patterns & practices
  3. // Composite Application Guidance for Windows Presentation Foundation and Silverlight
  4. //===================================================================================
  5. // Copyright (c) Microsoft Corporation. All rights reserved.
  6. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
  7. // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
  8. // LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  9. // FITNESS FOR A PARTICULAR PURPOSE.
  10. //===================================================================================
  11. // The example companies, organizations, products, domain names,
  12. // e-mail addresses, logos, people, places, and events depicted
  13. // herein are fictitious. No association with any real company,
  14. // organization, product, domain name, email address, logo, person,
  15. // places, or events is intended or should be inferred.
  16. //===================================================================================
  17. using System.Windows.Controls;
  18. using System.Windows;
  19. using System.Windows.Media;
  20. using System.Collections.ObjectModel;
  21. using System;
  22. using System.Windows.Data;
  23. using System.Collections;
  24. using System.ComponentModel;
  25. using System.Collections.Specialized;
  26. namespace StockTraderRI.ChartControls
  27. {
  28. public class ContinuousAxisPanel : Panel
  29. {
  30. public ContinuousAxisPanel()
  31. {
  32. _largestLabelSize = new Size();
  33. SetValue(ItemsSourceKey, new ObservableCollection<String>());
  34. YValues = new ObservableCollection<double>();
  35. SetValue(TickPositionsKey, new ObservableCollection<double>());
  36. }
  37. protected override void OnInitialized(EventArgs e)
  38. {
  39. base.OnInitialized(e);
  40. _parentControl = ((ContinuousAxis)((FrameworkElement)VisualTreeHelper.GetParent(this)).TemplatedParent);
  41. if (_parentControl != null)
  42. {
  43. Binding valueBinding = new Binding();
  44. valueBinding.Source = _parentControl;
  45. valueBinding.Path = new PropertyPath(ContinuousAxis.SourceValuesProperty);
  46. this.SetBinding(ContinuousAxisPanel.DataValuesProperty, valueBinding);
  47. Binding itemsBinding = new Binding();
  48. itemsBinding.Source = this;
  49. itemsBinding.Path = new PropertyPath(ContinuousAxisPanel.ItemsSourceProperty);
  50. _parentControl.SetBinding(ContinuousAxis.ItemsSourceProperty, itemsBinding);
  51. Binding refLineBinding = new Binding();
  52. refLineBinding.Source = _parentControl;
  53. refLineBinding.Path = new PropertyPath(ContinuousAxis.ReferenceLineSeperationProperty);
  54. this.SetBinding(ContinuousAxisPanel.ReferenceLineSeperationProperty, refLineBinding);
  55. Binding outputBinding = new Binding();
  56. outputBinding.Source = this;
  57. outputBinding.Path = new PropertyPath(ContinuousAxisPanel.YValuesProperty);
  58. _parentControl.SetBinding(ContinuousAxis.ValuesProperty, outputBinding);
  59. Binding tickPositionBinding = new Binding();
  60. tickPositionBinding.Source = this;
  61. tickPositionBinding.Path = new PropertyPath(ContinuousAxisPanel.TickPositionsProperty);
  62. _parentControl.SetBinding(ContinuousAxis.TickPositionsProperty, tickPositionBinding);
  63. Binding zerobinding = new Binding();
  64. zerobinding.Source = this;
  65. zerobinding.Path = new PropertyPath(ContinuousAxisPanel.OriginProperty);
  66. _parentControl.SetBinding(ContinuousAxis.OriginProperty, zerobinding);
  67. }
  68. }
  69. public static void OnDataValuesChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
  70. {
  71. ContinuousAxisPanel p = sender as ContinuousAxisPanel;
  72. if (p != null && p.DataValues != null)
  73. {
  74. ((INotifyCollectionChanged)p.DataValues).CollectionChanged += new NotifyCollectionChangedEventHandler(p.Axis2Panel_CollectionChanged);
  75. p.GenerateItemsSource();
  76. }
  77. }
  78. public void Axis2Panel_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
  79. {
  80. GenerateItemsSource();
  81. }
  82. private void GenerateItemsSource()
  83. {
  84. if (DataValues==null || DataValues.Count==0)
  85. {
  86. return;
  87. }
  88. CalculateValueIncrement(_arrangeSize);
  89. ObservableCollection<String> tempItemsSource = ItemsSource;
  90. tempItemsSource.Clear();
  91. int referenceLinesCreated = 0;
  92. while (referenceLinesCreated != _numReferenceLines)
  93. {
  94. if (Orientation.Equals(Orientation.Vertical))
  95. tempItemsSource.Add(((double)(_startingIncrement + referenceLinesCreated * _valueIncrement)).ToString());
  96. else
  97. tempItemsSource.Add(((double)(_startingIncrement + (_numReferenceLines - 1 - referenceLinesCreated) * _valueIncrement)).ToString());
  98. referenceLinesCreated++;
  99. }
  100. _highValue = _startingIncrement + (_numReferenceLines - 1) * _valueIncrement;
  101. _lowValue = _startingIncrement;
  102. }
  103. protected override Size MeasureOverride(Size availableSize)
  104. {
  105. _largestLabelSize.Height = 0.0;
  106. _largestLabelSize.Width = 0.0;
  107. UIElementCollection tempInternalChildren = InternalChildren;
  108. for (int i = 0; i < tempInternalChildren.Count; i++)
  109. {
  110. tempInternalChildren[i].Measure(availableSize);
  111. _largestLabelSize.Height = _largestLabelSize.Height > tempInternalChildren[i].DesiredSize.Height
  112. ? _largestLabelSize.Height : tempInternalChildren[i].DesiredSize.Height;
  113. _largestLabelSize.Width = _largestLabelSize.Width > tempInternalChildren[i].DesiredSize.Width
  114. ? _largestLabelSize.Width : tempInternalChildren[i].DesiredSize.Width;
  115. }
  116. if (Orientation.Equals(Orientation.Vertical))
  117. {
  118. double fitAllLabelSize = _largestLabelSize.Height * InternalChildren.Count;
  119. availableSize.Height = fitAllLabelSize < availableSize.Height ? fitAllLabelSize : availableSize.Height;
  120. availableSize.Width = _largestLabelSize.Width;
  121. }
  122. else
  123. {
  124. double fitAllLabelsSize = _largestLabelSize.Width * InternalChildren.Count;
  125. availableSize.Width = fitAllLabelsSize < availableSize.Width ? fitAllLabelsSize : availableSize.Width;
  126. availableSize.Height = _largestLabelSize.Height;
  127. }
  128. return availableSize;
  129. }
  130. protected override Size ArrangeOverride(Size finalSize)
  131. {
  132. if (!_arrangeSize.Equals(finalSize))
  133. {
  134. _arrangeSize = finalSize;
  135. GenerateItemsSource();
  136. }
  137. _arrangeSize = finalSize;
  138. if (InternalChildren.Count > 0)
  139. {
  140. if (Orientation.Equals(Orientation.Vertical))
  141. {
  142. ArrangeVerticalLabels(finalSize);
  143. CalculateYOutputValues(finalSize);
  144. }
  145. else
  146. {
  147. ArrangeHorizontalLabels(finalSize);
  148. CalculateXOutputValues(finalSize);
  149. }
  150. }
  151. return base.ArrangeOverride(finalSize);
  152. }
  153. private void ArrangeHorizontalLabels(Size constraint)
  154. {
  155. double rectWidth = _largestLabelSize.Width;
  156. double rectHeight = _largestLabelSize.Height;
  157. double increments = CalculatePixelIncrements(constraint, _largestLabelSize);
  158. double start_width = constraint.Width - _largestLabelSize.Width / 2;
  159. double end_width = start_width - (InternalChildren.Count - 1) * increments;
  160. ObservableCollection<double> tempTickPositions = TickPositions;
  161. if (start_width > end_width)
  162. {
  163. tempTickPositions.Clear();
  164. Rect r = new Rect(start_width - rectWidth / 2, 0, rectWidth, rectHeight);
  165. InternalChildren[0].Arrange(r);
  166. tempTickPositions.Add(start_width);
  167. int count = InternalChildren.Count - 1;
  168. r = new Rect(start_width - count * increments - rectWidth / 2, 0, rectWidth, rectHeight);
  169. InternalChildren[count].Arrange(r);
  170. tempTickPositions.Add(start_width - count * increments);
  171. if (constraint.Width > 3 * rectWidth)
  172. {
  173. _skipFactor = (int)Math.Ceiling((InternalChildren.Count - 2) / Math.Floor((constraint.Width - 2 * rectWidth) / rectWidth));
  174. if ((InternalChildren.Count - 2) != 2.0)
  175. _skipFactor = Math.Min(_skipFactor, (int)Math.Ceiling((double)(InternalChildren.Count - 2.0) / 2.0));
  176. _canDisplayAllLabels = true;
  177. if (_skipFactor > 1)
  178. {
  179. _canDisplayAllLabels = false;
  180. }
  181. for (int i = 2; i <= InternalChildren.Count - 1; i++)
  182. {
  183. tempTickPositions.Add(start_width - (i - 1) * increments);
  184. if (_canDisplayAllLabels || (i + 1) % _skipFactor == 0)
  185. {
  186. r = new Rect(start_width - (i - 1) * increments - rectWidth / 2, 0, rectWidth, rectHeight);
  187. InternalChildren[i-1].Arrange(r);
  188. }
  189. else
  190. {
  191. InternalChildren[i-1].Arrange(new Rect(0, 0, 0, 0));
  192. }
  193. }
  194. }
  195. }
  196. }
  197. private void ArrangeVerticalLabels(Size constraint)
  198. {
  199. double rectWidth = _largestLabelSize.Width;
  200. double rectHeight = _largestLabelSize.Height;
  201. double increments = CalculatePixelIncrements(constraint, _largestLabelSize);
  202. double start_height = constraint.Height - _largestLabelSize.Height / 2;
  203. double end_height = start_height - (InternalChildren.Count - 1) * increments;
  204. ObservableCollection<double> tempTickPositions = TickPositions;
  205. if(start_height > end_height)
  206. {
  207. tempTickPositions.Clear();
  208. Rect r = new Rect(constraint.Width - rectWidth, (start_height - rectHeight / 2), rectWidth, rectHeight);
  209. InternalChildren[0].Arrange(r);
  210. tempTickPositions.Add(start_height);
  211. int count = InternalChildren.Count-1;
  212. r = new Rect(constraint.Width - rectWidth, (start_height - count*increments - rectHeight / 2), rectWidth, rectHeight);
  213. InternalChildren[count].Arrange(r);
  214. tempTickPositions.Add(start_height - count * increments);
  215. if (constraint.Height > 3 * rectHeight)
  216. {
  217. _skipFactor = (int)Math.Ceiling((InternalChildren.Count - 2) / Math.Floor((constraint.Height - 2 * rectHeight) / rectHeight));
  218. if ((InternalChildren.Count - 2) != 2.0)
  219. _skipFactor = Math.Min(_skipFactor, (int)Math.Ceiling((double)(InternalChildren.Count - 2.0) / 2.0));
  220. _canDisplayAllLabels = true;
  221. if (_skipFactor > 1)
  222. {
  223. _canDisplayAllLabels = false;
  224. }
  225. for (int i = 2; i <= InternalChildren.Count-1; i++)
  226. {
  227. tempTickPositions.Add(start_height - (i - 1) * increments);
  228. if (_canDisplayAllLabels || (i + 1) % _skipFactor == 0 )
  229. {
  230. r = new Rect(constraint.Width - rectWidth, (start_height - (i - 1) * increments - rectHeight / 2), rectWidth, rectHeight);
  231. InternalChildren[i - 1].Arrange(r);
  232. }
  233. else
  234. {
  235. InternalChildren[i - 1].Arrange(new Rect(0, 0, 0, 0));
  236. }
  237. }
  238. }
  239. }
  240. }
  241. private void CalculateYOutputValues(Size constraint)
  242. {
  243. YValues.Clear();
  244. double start_val, lowPixel, highPixel;
  245. double pixelIncrement = CalculatePixelIncrements(constraint, _largestLabelSize);
  246. if (Orientation.Equals(Orientation.Vertical))
  247. {
  248. start_val = constraint.Height - _largestLabelSize.Height / 2;
  249. lowPixel = start_val - (InternalChildren.Count - 1) * pixelIncrement;
  250. highPixel = start_val;
  251. }
  252. else
  253. {
  254. start_val = constraint.Width - _largestLabelSize.Width / 2;
  255. lowPixel = start_val - (InternalChildren.Count - 1) * pixelIncrement;
  256. highPixel = start_val;
  257. }
  258. if (highPixel < lowPixel)
  259. return;
  260. for (int i = 0; i < DataValues.Count; i++)
  261. {
  262. double outVal = highPixel - ((highPixel - lowPixel) / (_highValue - _lowValue)) * (DataValues[i] - _lowValue);
  263. YValues.Add(outVal);
  264. }
  265. if (_startsAtZero || (!_allNegativeValues && !_allPositiveValues))
  266. Origin = highPixel - ((highPixel - lowPixel) / (_highValue - _lowValue)) * (0.0 - _lowValue);
  267. else if (!_startsAtZero && _allPositiveValues)
  268. Origin = highPixel;
  269. else
  270. Origin = lowPixel;
  271. }
  272. private void CalculateXOutputValues(Size constraint)
  273. {
  274. YValues.Clear();
  275. double start_width = constraint.Width - _largestLabelSize.Width / 2;
  276. double pixelIncrement = CalculatePixelIncrements(constraint, _largestLabelSize);
  277. double lowPixel = start_width - (InternalChildren.Count - 1) * pixelIncrement;
  278. double highPixel = start_width;
  279. if (highPixel < lowPixel)
  280. return;
  281. for (int i = 0; i < DataValues.Count; i++)
  282. {
  283. double output = lowPixel + ((highPixel - lowPixel) / (_highValue - _lowValue)) * (DataValues[i] - _lowValue);
  284. YValues.Add(output);
  285. }
  286. if (_startsAtZero || (!_allNegativeValues && !_allPositiveValues))
  287. Origin = lowPixel + ((highPixel - lowPixel) / (_highValue - _lowValue)) * (0.0 - _lowValue);
  288. else if (!_startsAtZero && _allPositiveValues)
  289. Origin = lowPixel;
  290. else
  291. Origin = highPixel;
  292. }
  293. /// <summary>
  294. /// Calculate the pixel distance between each tick mark on the vertical axis
  295. /// </summary>
  296. /// <param name="constraint"></param>
  297. /// <returns></returns>
  298. private double CalculatePixelIncrements(Size constraint, Size labelSize)
  299. {
  300. if(Orientation.Equals(Orientation.Vertical))
  301. return (constraint.Height - _largestLabelSize.Height) / (_numReferenceLines - 1);
  302. else
  303. return (constraint.Width - _largestLabelSize.Width) / (_numReferenceLines - 1);
  304. }
  305. private double CalculateValueIncrement(Size size)
  306. {
  307. // Determine if the starting value is 0 or not
  308. bool startsAtZero = false;
  309. bool allPositiveValues = true;
  310. bool allNegativeValues = true;
  311. double increment_value = 0;
  312. int multiplier = 1;
  313. if (DataValues.Count == 0)
  314. return 0.0;
  315. //double low = ((DoubleHolder)DataValues[0]).DoubleValue;
  316. //double high = ((DoubleHolder)DataValues[0]).DoubleValue;
  317. double low = DataValues[0];
  318. double high = DataValues[0];
  319. for (int i = 0; i < DataValues.Count; i++)
  320. {
  321. //double temp = ((DoubleHolder)DataValues[i]).DoubleValue;
  322. double temp = DataValues[i];
  323. // Check for positive and negative values
  324. if (temp > 0)
  325. {
  326. allNegativeValues = false;
  327. }
  328. else if (temp < 0)
  329. {
  330. allPositiveValues = false;
  331. }
  332. // Reset low and high if necessary
  333. if (temp < low)
  334. {
  335. low = temp;
  336. }
  337. else if (temp > high)
  338. {
  339. high = temp;
  340. }
  341. }
  342. // Determine whether or not the increments will start at zero
  343. if (allPositiveValues && (low < (high / 2)) ||
  344. (allNegativeValues && high > (low / 2)))
  345. {
  346. _startsAtZero = true;
  347. startsAtZero = true;
  348. }
  349. // If all values in dataset are 0, draw one reference line and label it 0
  350. if (high == 0 && low == 0)
  351. {
  352. _valueIncrement = 0;
  353. _startingIncrement = 0;
  354. _numReferenceLines = 1;
  355. _startsAtZero = startsAtZero;
  356. return increment_value;
  357. }
  358. // Find an increment value that is in the set {1*10^x, 2*10^x, 5*10^x, where x is an integer
  359. // (positive, negative, or zero)}
  360. if (!allNegativeValues)
  361. {
  362. if (startsAtZero)
  363. {
  364. int exp = 0;
  365. while (true)
  366. {
  367. multiplier = IsWithinRange(high, exp, size);
  368. if (multiplier != -1)
  369. {
  370. break;
  371. }
  372. multiplier = IsWithinRange(high, (-1 * exp), size);
  373. if (multiplier != -1)
  374. {
  375. exp = -1 * exp;
  376. break;
  377. }
  378. exp++;
  379. }
  380. increment_value = multiplier * Math.Pow(10, exp);
  381. }
  382. else
  383. {
  384. int exp = 0;
  385. while (true)
  386. {
  387. multiplier = IsWithinRange((high - low), exp, size);
  388. if (multiplier != -1)
  389. {
  390. break;
  391. }
  392. multiplier = IsWithinRange((high - low), (-1 * exp), size);
  393. if (multiplier != -1)
  394. {
  395. exp = -1 * exp;
  396. break;
  397. }
  398. if (high == low)
  399. {
  400. increment_value = high;
  401. _valueIncrement = increment_value;
  402. _numReferenceLines = 1;
  403. break;
  404. }
  405. exp++;
  406. }
  407. if (increment_value == 0)
  408. {
  409. increment_value = multiplier * Math.Pow(10, exp);
  410. }
  411. }
  412. }
  413. else
  414. {
  415. if (startsAtZero)
  416. {
  417. int exp = 0;
  418. while (true)
  419. {
  420. multiplier = IsWithinRange(low, exp, size);
  421. if (multiplier != -1)
  422. {
  423. break;
  424. }
  425. multiplier = IsWithinRange(low, (-1 * exp), size);
  426. if (multiplier != -1)
  427. {
  428. exp = -1 * exp;
  429. break;
  430. }
  431. exp++;
  432. }
  433. increment_value = multiplier * Math.Pow(10, exp);
  434. }
  435. else
  436. {
  437. int exp = 0;
  438. if (low - high == 0.0)
  439. increment_value = 1.0;
  440. else
  441. {
  442. while (true)
  443. {
  444. multiplier = IsWithinRange((low - high), exp, size);
  445. if (multiplier != -1)
  446. {
  447. break;
  448. }
  449. multiplier = IsWithinRange((low - high), (-1 * exp), size);
  450. if (multiplier != -1)
  451. {
  452. exp = -1 * exp;
  453. break;
  454. }
  455. exp++;
  456. }
  457. increment_value = multiplier * Math.Pow(10, exp);
  458. }
  459. }
  460. }
  461. double starting_value = 0;
  462. // Determine starting value if it is nonzero
  463. if (!startsAtZero)
  464. {
  465. if (allPositiveValues)
  466. {
  467. if (low % increment_value == 0)
  468. {
  469. starting_value = low;
  470. }
  471. else
  472. {
  473. starting_value = (int)(low / increment_value) * increment_value;
  474. }
  475. }
  476. else
  477. {
  478. if (low % increment_value == 0)
  479. {
  480. starting_value = low;
  481. }
  482. else
  483. {
  484. starting_value = (int)((low - increment_value) / increment_value) * increment_value;
  485. }
  486. }
  487. }
  488. else if (startsAtZero && allNegativeValues)
  489. {
  490. if (low % increment_value == 0)
  491. {
  492. starting_value = low;
  493. }
  494. else
  495. {
  496. starting_value = (int)((low - increment_value) / increment_value) * increment_value;
  497. }
  498. }
  499. // Determine the number of reference lines
  500. //int numRefLines = 0;
  501. int numRefLines = (int)Math.Ceiling((high - starting_value) / increment_value) + 1;
  502. _valueIncrement = increment_value;
  503. _startingIncrement = starting_value;
  504. _numReferenceLines = numRefLines;
  505. _startsAtZero = startsAtZero;
  506. _allPositiveValues = allPositiveValues;
  507. _allNegativeValues = allNegativeValues;
  508. return increment_value;
  509. }
  510. /// <summary>
  511. /// Checks to see if the calculated increment value is between the low and high passed in,
  512. /// then returns the multiplier used
  513. /// </summary>
  514. /// <param name="numerator"></param>
  515. /// <param name="exponent"></param>
  516. /// <param name="lowRange"></param>
  517. /// <param name="highRange"></param>
  518. /// <returns></returns>
  519. private int IsWithinRange(double numerator, int exponent, Size size)
  520. {
  521. int highRange, lowRange;
  522. // highRange = (int)Math.Min(10, (int)(size.Height / labelSize.Height)) -2;
  523. if(Orientation.Equals(Orientation.Vertical))
  524. highRange = (int)(size.Height / ReferenceLineSeperation);
  525. else
  526. highRange = (int)(size.Width / ReferenceLineSeperation);
  527. lowRange = 1;
  528. highRange = (int)Math.Max(highRange, 3);
  529. if ((Math.Abs(numerator) / (1 * Math.Pow(10, exponent))) >= lowRange && (Math.Abs(numerator) / (1 * Math.Pow(10, exponent))) <= highRange)
  530. {
  531. return 1;
  532. }
  533. if ((Math.Abs(numerator) / (2 * Math.Pow(10, exponent))) >= lowRange && (Math.Abs(numerator) / (2 * Math.Pow(10, exponent))) <= highRange)
  534. {
  535. return 2;
  536. }
  537. if ((Math.Abs(numerator) / (5 * Math.Pow(10, exponent))) >= lowRange && (Math.Abs(numerator) / (5 * Math.Pow(10, exponent))) <= highRange)
  538. {
  539. return 5;
  540. }
  541. return -1;
  542. }
  543. public ObservableCollection<double> YValues
  544. {
  545. get { return (ObservableCollection<double>)GetValue(YValuesProperty); }
  546. set { SetValue(YValuesProperty, value); }
  547. }
  548. // Using a DependencyProperty as the backing store for YValues. This enables animation, styling, binding, etc...
  549. public static readonly DependencyProperty YValuesProperty =
  550. DependencyProperty.Register("YValues", typeof(ObservableCollection<double>), typeof(ContinuousAxisPanel), new UIPropertyMetadata(null));
  551. public ObservableCollection<String> ItemsSource
  552. {
  553. get { return (ObservableCollection<String>)GetValue(ItemsSourceProperty); }
  554. }
  555. // Using a DependencyProperty as the backing store for Axis2Panel. This enables animation, styling, binding, etc...
  556. private static readonly DependencyPropertyKey ItemsSourceKey =
  557. DependencyProperty.RegisterReadOnly("ItemsSource", typeof(ObservableCollection<String>), typeof(ContinuousAxisPanel), new UIPropertyMetadata());
  558. public static readonly DependencyProperty ItemsSourceProperty = ItemsSourceKey.DependencyProperty;
  559. private ObservableCollection<double> DataValues
  560. {
  561. get { return (ObservableCollection<double>)GetValue(DataValuesProperty); }
  562. set { SetValue(DataValuesProperty, value); }
  563. }
  564. // Using a DependencyProperty as the backing store for DataValues. This enables animation, styling, binding, etc...
  565. private static readonly DependencyProperty DataValuesProperty =
  566. DependencyProperty.Register("DataValues", typeof(ObservableCollection<double>), typeof(ContinuousAxisPanel), new FrameworkPropertyMetadata(OnDataValuesChanged));
  567. public ObservableCollection<double> TickPositions
  568. {
  569. get { return (ObservableCollection<double>)GetValue(TickPositionsProperty); }
  570. //set { SetValue(TickPositionsProperty, value); }
  571. }
  572. // Using a DependencyProperty as the backing store for TickPositions. This enables animation, styling, binding, etc...
  573. private static readonly DependencyPropertyKey TickPositionsKey =
  574. DependencyProperty.RegisterReadOnly("TickPositions", typeof(ObservableCollection<double>), typeof(ContinuousAxisPanel), new UIPropertyMetadata(null));
  575. public static readonly DependencyProperty TickPositionsProperty = TickPositionsKey.DependencyProperty;
  576. public double Origin
  577. {
  578. get { return (double)GetValue(OriginProperty); }
  579. set { SetValue(OriginProperty, value); }
  580. }
  581. // Using a DependencyProperty as the backing store for ZeroReferenceLinePosition. This enables animation, styling, binding, etc...
  582. public static readonly DependencyProperty OriginProperty =
  583. DependencyProperty.Register("Origin", typeof(double), typeof(ContinuousAxisPanel), new UIPropertyMetadata(0.0));
  584. public Orientation Orientation
  585. {
  586. get { return (Orientation)GetValue(OrientationProperty); }
  587. set { SetValue(OrientationProperty, value); }
  588. }
  589. // Using a DependencyProperty as the backing store for Orientation. This enables animation, styling, binding, etc...
  590. public static readonly DependencyProperty OrientationProperty =
  591. DependencyProperty.Register("Orientation", typeof(Orientation), typeof(ContinuousAxisPanel), new UIPropertyMetadata(Orientation.Vertical));
  592. public double ReferenceLineSeperation
  593. {
  594. get { return (double)GetValue(ReferenceLineSeperationProperty); }
  595. set { SetValue(ReferenceLineSeperationProperty, value); }
  596. }
  597. // Using a DependencyProperty as the backing store for ReferenceLineSeperation. This enables animation, styling, binding, etc...
  598. public static readonly DependencyProperty ReferenceLineSeperationProperty =
  599. DependencyProperty.Register("ReferenceLineSeperation", typeof(double), typeof(ContinuousAxisPanel), new UIPropertyMetadata(null));
  600. private Size _largestLabelSize;
  601. private bool _canDisplayAllLabels;
  602. private int _skipFactor;
  603. private double _lowValue, _highValue;
  604. private Size _arrangeSize;
  605. public ItemsControl _parentControl;
  606. private bool _startsAtZero;
  607. private double _startingIncrement;
  608. private double _valueIncrement;
  609. private int _numReferenceLines;
  610. private bool _allPositiveValues;
  611. private bool _allNegativeValues;
  612. }
  613. }