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