PageRenderTime 46ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/Main/src/DynamicDataDisplay/Charts/Axes/StackCanvas.cs

#
C# | 237 lines | 199 code | 36 blank | 2 comment | 33 complexity | 527dc53f9e38897aacccf9efabc881c5 MD5 | raw file
Possible License(s): CC-BY-SA-3.0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Windows.Controls;
  6. using System.Windows;
  7. using System.Windows.Media;
  8. using System.Diagnostics;
  9. using Microsoft.Research.DynamicDataDisplay.Common.Auxiliary;
  10. namespace Microsoft.Research.DynamicDataDisplay.Charts
  11. {
  12. public class StackCanvas : Panel
  13. {
  14. public StackCanvas()
  15. {
  16. }
  17. #region EndCoordinate attached property
  18. [AttachedPropertyBrowsableForChildren]
  19. public static double GetEndCoordinate(DependencyObject obj)
  20. {
  21. return (double)obj.GetValue(EndCoordinateProperty);
  22. }
  23. public static void SetEndCoordinate(DependencyObject obj, double value)
  24. {
  25. obj.SetValue(EndCoordinateProperty, value);
  26. }
  27. public static readonly DependencyProperty EndCoordinateProperty = DependencyProperty.RegisterAttached(
  28. "EndCoordinate",
  29. typeof(double),
  30. typeof(StackCanvas),
  31. new PropertyMetadata(Double.NaN, OnCoordinateChanged));
  32. #endregion
  33. #region Coordinate attached property
  34. [AttachedPropertyBrowsableForChildren]
  35. public static double GetCoordinate(DependencyObject obj)
  36. {
  37. return (double)obj.GetValue(CoordinateProperty);
  38. }
  39. public static void SetCoordinate(DependencyObject obj, double value)
  40. {
  41. obj.SetValue(CoordinateProperty, value);
  42. }
  43. public static readonly DependencyProperty CoordinateProperty = DependencyProperty.RegisterAttached(
  44. "Coordinate",
  45. typeof(double),
  46. typeof(StackCanvas),
  47. new PropertyMetadata(0.0, OnCoordinateChanged));
  48. private static void OnCoordinateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  49. {
  50. UIElement reference = d as UIElement;
  51. if (reference != null)
  52. {
  53. StackCanvas parent = VisualTreeHelper.GetParent(reference) as StackCanvas;
  54. if (parent != null)
  55. {
  56. parent.InvalidateArrange();
  57. }
  58. }
  59. }
  60. #endregion
  61. #region AxisPlacement property
  62. public AxisPlacement Placement
  63. {
  64. get { return (AxisPlacement)GetValue(PlacementProperty); }
  65. set { SetValue(PlacementProperty, value); }
  66. }
  67. public static readonly DependencyProperty PlacementProperty =
  68. DependencyProperty.Register(
  69. "Placement",
  70. typeof(AxisPlacement),
  71. typeof(StackCanvas),
  72. new FrameworkPropertyMetadata(
  73. AxisPlacement.Bottom,
  74. FrameworkPropertyMetadataOptions.AffectsArrange));
  75. #endregion
  76. private bool IsHorizontal
  77. {
  78. get { return Placement == AxisPlacement.Top || Placement == AxisPlacement.Bottom; }
  79. }
  80. protected override Size MeasureOverride(Size constraint)
  81. {
  82. Size availableSize = constraint;
  83. Size size = new Size();
  84. bool isHorizontal = IsHorizontal;
  85. if (isHorizontal)
  86. {
  87. availableSize.Width = Double.PositiveInfinity;
  88. size.Width = constraint.Width;
  89. }
  90. else
  91. {
  92. availableSize.Height = Double.PositiveInfinity;
  93. size.Height = constraint.Height;
  94. }
  95. // measuring all children and determining self width and height
  96. foreach (UIElement element in base.Children)
  97. {
  98. if (element != null)
  99. {
  100. Size childSize = GetChildSize(element, availableSize);
  101. element.Measure(childSize);
  102. Size desiredSize = element.DesiredSize;
  103. if (isHorizontal)
  104. {
  105. size.Height = Math.Max(size.Height, desiredSize.Height);
  106. }
  107. else
  108. {
  109. size.Width = Math.Max(size.Width, desiredSize.Width);
  110. }
  111. }
  112. }
  113. if (Double.IsPositiveInfinity(size.Width)) size.Width = 0;
  114. if (Double.IsPositiveInfinity(size.Height)) size.Height = 0;
  115. return size;
  116. }
  117. private Size GetChildSize(UIElement element, Size availableSize)
  118. {
  119. var coordinate = GetCoordinate(element);
  120. var endCoordinate = GetEndCoordinate(element);
  121. if (coordinate.IsNotNaN() && endCoordinate.IsNotNaN())
  122. {
  123. if (Placement.IsBottomOrTop())
  124. {
  125. availableSize.Width = Math.Abs(endCoordinate - coordinate);
  126. }
  127. else
  128. {
  129. availableSize.Height = Math.Abs(endCoordinate - coordinate);
  130. }
  131. }
  132. return availableSize;
  133. }
  134. protected override Size ArrangeOverride(Size finalSize)
  135. {
  136. bool isHorizontal = IsHorizontal;
  137. foreach (FrameworkElement element in base.Children)
  138. {
  139. if (element == null)
  140. {
  141. continue;
  142. }
  143. Size elementSize = element.DesiredSize;
  144. double x = 0.0;
  145. double y = 0.0;
  146. switch (Placement)
  147. {
  148. case AxisPlacement.Left:
  149. x = finalSize.Width - elementSize.Width;
  150. break;
  151. case AxisPlacement.Right:
  152. x = 0;
  153. break;
  154. case AxisPlacement.Top:
  155. y = finalSize.Height - elementSize.Height;
  156. break;
  157. case AxisPlacement.Bottom:
  158. y = 0;
  159. break;
  160. default:
  161. break;
  162. }
  163. double coordinate = GetCoordinate(element);
  164. if (!Double.IsNaN(GetEndCoordinate(element)))
  165. {
  166. double endCoordinate = GetEndCoordinate(element);
  167. double size = endCoordinate - coordinate;
  168. if (size < 0)
  169. {
  170. size = -size;
  171. coordinate -= size;
  172. }
  173. if (isHorizontal)
  174. elementSize.Width = size;
  175. else
  176. elementSize.Height = size;
  177. }
  178. // shift for common tick labels, not for major ones.
  179. if (isHorizontal)
  180. {
  181. x = coordinate;
  182. if (element.HorizontalAlignment == HorizontalAlignment.Center)
  183. x = coordinate - elementSize.Width / 2;
  184. }
  185. else
  186. {
  187. y = coordinate;
  188. if (element.VerticalAlignment == VerticalAlignment.Center)
  189. y = coordinate - elementSize.Height / 2;
  190. else if (element.VerticalAlignment == VerticalAlignment.Bottom)
  191. y = coordinate - elementSize.Height;
  192. else if (element.VerticalAlignment == VerticalAlignment.Top)
  193. y = coordinate;
  194. }
  195. Rect bounds = new Rect(new Point(x, y), elementSize);
  196. element.Arrange(bounds);
  197. }
  198. return finalSize;
  199. }
  200. }
  201. }