PageRenderTime 49ms CodeModel.GetById 12ms app.highlight 32ms RepoModel.GetById 1ms app.codeStats 0ms

/V1/trunk/Source/ChartControls/DiscreteAxisPanel.cs

#
C# | 265 lines | 209 code | 36 blank | 20 comment | 22 complexity | 74856e5cf05d493f42236d2ba4e39c63 MD5 | raw file
  1//===============================================================================
  2// Microsoft patterns & practices
  3// Composite Application Guidance for Windows Presentation Foundation
  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
 18using System.Windows.Controls;
 19using System.Windows;
 20using System.Windows.Media;
 21using System.Collections.ObjectModel;
 22using System.Windows.Data;
 23using System;
 24
 25namespace StockTraderRI.ChartControls
 26{
 27    public class DiscreteAxisPanel : Panel
 28    {
 29        public DiscreteAxisPanel()
 30        {
 31            TickPositions = new ObservableCollection<double>();
 32            _largestLabelSize = new Size();
 33        }
 34
 35        protected override void OnInitialized(System.EventArgs e)
 36        {
 37            base.OnInitialized(e);
 38            _parentControl = ((ItemsControl)((FrameworkElement)VisualTreeHelper.GetParent(this)).TemplatedParent);
 39
 40            Binding tickBinding = new Binding();
 41            tickBinding.Path = new PropertyPath(DiscreteAxisPanel.TickPositionsProperty);
 42            tickBinding.Source = this;
 43            _parentControl.SetBinding(DiscreteAxis.TickPositionsProperty, tickBinding);
 44
 45            Binding originBinding = new Binding();
 46            originBinding.Path = new PropertyPath(DiscreteAxisPanel.OriginProperty);
 47            originBinding.Source = this;
 48            _parentControl.SetBinding(DiscreteAxis.OriginProperty, originBinding);
 49        }
 50
 51        protected override Size MeasureOverride(Size availableSize)
 52        {
 53            _largestLabelSize.Height = 0.0;
 54            _largestLabelSize.Width = 0.0;
 55            UIElementCollection tempInternalChildren = InternalChildren;
 56            for (int i = 0; i < tempInternalChildren.Count; i++)
 57            {
 58                tempInternalChildren[i].Measure(availableSize);
 59                _largestLabelSize.Height = _largestLabelSize.Height > tempInternalChildren[i].DesiredSize.Height
 60                    ? _largestLabelSize.Height : tempInternalChildren[i].DesiredSize.Height;
 61                _largestLabelSize.Width = _largestLabelSize.Width > tempInternalChildren[i].DesiredSize.Width
 62                    ? _largestLabelSize.Width : tempInternalChildren[i].DesiredSize.Width;
 63            }
 64            if (Orientation.Equals(Orientation.Vertical))
 65            {
 66                double fitAllLabelSize = _largestLabelSize.Height * InternalChildren.Count;
 67                availableSize.Height = fitAllLabelSize < availableSize.Height ? fitAllLabelSize : availableSize.Height;
 68                availableSize.Width = _largestLabelSize.Width;
 69            }
 70            else
 71            {
 72                double fitAllLabelsSize = _largestLabelSize.Width * InternalChildren.Count;
 73                availableSize.Width = fitAllLabelsSize < availableSize.Width ? fitAllLabelsSize : availableSize.Width;
 74                availableSize.Height = _largestLabelSize.Height;
 75            }
 76            return availableSize;
 77        }
 78
 79        protected override Size ArrangeOverride(Size finalSize)
 80        {
 81            if (InternalChildren.Count > 0)
 82            {
 83                if (Orientation.Equals(Orientation.Horizontal))
 84                {
 85                    Origin = TickMarksLength / 2;
 86                    ArrangeHorizontalLabels(finalSize);
 87                }
 88                else
 89                {
 90                    Origin = finalSize.Height - TickMarksLength / 2;
 91                    ArrangeVerticalLabels(finalSize);
 92                }
 93            }
 94            return base.ArrangeOverride(finalSize);
 95        }
 96
 97
 98        private void ArrangeHorizontalLabels(Size constraint)
 99        {
100            double rectHeight = _largestLabelSize.Height;
101            double rectWidth = _largestLabelSize.Width;
102
103            TickPositions.Clear();
104
105            double availableWidth = constraint.Width - TickMarksLength / 2;
106            int skipfactor;
107            if (availableWidth < rectWidth)
108                skipfactor = InternalChildren.Count + 1;
109            else
110                skipfactor = (int)Math.Ceiling(InternalChildren.Count/Math.Floor(availableWidth / rectWidth));
111            skipfactor = Math.Min(skipfactor, (int)Math.Ceiling((double)InternalChildren.Count/2.0));
112            bool canDisplayAllLabels = true;
113
114            if (skipfactor > 1)
115            {
116                canDisplayAllLabels = false;
117            }
118
119            double sections = availableWidth / InternalChildren.Count;
120            double startCord = TickMarksLength/2;
121            TickPositions.Add(startCord);
122            for (int i = 0; i < InternalChildren.Count; i++)
123            {
124                if (TickPositions.Count - 1 <= i)
125                    TickPositions.Add(startCord + (i + 1) * sections);
126                else
127                    TickPositions[i + 1] = startCord + (i + 1) * sections;
128                
129                if (canDisplayAllLabels)
130                {
131                    Rect r = new Rect(i * sections + sections / 2 - rectWidth / 2, 0, rectWidth, InternalChildren[i].DesiredSize.Height);
132                    InternalChildren[i].Arrange(r);
133                }
134                else
135                {
136                    if((i+1)%skipfactor == 0)
137                    {
138                        double x = i * sections + sections / 2 - rectWidth / 2;
139                        if (x < 0 || x + rectWidth > availableWidth)
140                        {
141                            Rect r1 = new Rect(0, 0, 0, 0);
142                            InternalChildren[i].Arrange(r1);
143                            continue;
144                        }
145                        Rect r = new Rect(i * sections + sections / 2 - rectWidth / 2, 0, rectWidth, InternalChildren[i].DesiredSize.Height);
146                        InternalChildren[i].Arrange(r);
147                    }
148                    else
149                    {
150                        Rect r = new Rect(0, 0, 0, 0);
151                        InternalChildren[i].Arrange(r);
152                    }
153                }
154            }
155        }
156
157        private void ArrangeVerticalLabels(Size constraint)
158        {
159            double rectHeight = _largestLabelSize.Height;
160            double rectWidth = _largestLabelSize.Width;
161
162            TickPositions.Clear();
163            double availableHeight = constraint.Height - TickMarksLength / 2;
164
165            int skipfactor;
166            if (availableHeight < rectHeight)
167                skipfactor = InternalChildren.Count + 1;
168            else
169                skipfactor = (int)Math.Ceiling(InternalChildren.Count / Math.Floor(availableHeight / rectHeight));
170            skipfactor = Math.Min(skipfactor, (int)Math.Ceiling((double)InternalChildren.Count / 2.0));
171            bool canDisplayAllLabels = true;
172
173            if (skipfactor > 1)
174            {
175                canDisplayAllLabels = false;
176            }
177
178            double sections = availableHeight / InternalChildren.Count;
179
180            for (int i = 0; i < InternalChildren.Count; i++)
181            {
182                if (TickPositions.Count <= i)
183                    TickPositions.Add(i * sections);
184                else
185                    TickPositions[i] = i * sections;
186
187                if (canDisplayAllLabels)
188                {
189                    Rect r = new Rect(0, i * sections + sections / 2 - rectHeight / 2, InternalChildren[i].DesiredSize.Width, InternalChildren[i].DesiredSize.Height);
190                    InternalChildren[i].Arrange(r);
191                }
192                else
193                {
194                    if ((i + 1) % skipfactor == 0)
195                    {
196                        double x = i * sections + sections / 2 - rectHeight / 2;
197                        if (x < 0 || x + rectHeight > availableHeight)
198                        {
199                            Rect r1 = new Rect(0, 0, 0, 0);
200                            InternalChildren[i].Arrange(r1);
201                            continue;
202                        }
203                        Rect r = new Rect(0, i * sections + sections / 2 - rectHeight / 2, InternalChildren[i].DesiredSize.Width, InternalChildren[i].DesiredSize.Height);
204                        InternalChildren[i].Arrange(r);
205                    }
206                    else
207                    {
208                        Rect r = new Rect(0, 0, 0, 0);
209                        InternalChildren[i].Arrange(r);
210                    }
211                }
212            }
213            TickPositions.Add(availableHeight);
214        }
215
216
217        public double TickMarksLength
218        {
219            get { return (double)GetValue(TickMarksLengthProperty); }
220            set { SetValue(TickMarksLengthProperty, value); }
221        }
222
223        // Using a DependencyProperty as the backing store for TickMarksLength.  This enables animation, styling, binding, etc...
224        public static readonly DependencyProperty TickMarksLengthProperty =
225            DependencyProperty.Register("TickMarksLength", typeof(double), typeof(DiscreteAxisPanel), new UIPropertyMetadata(null));
226
227
228        public ObservableCollection<double> TickPositions
229        {
230            get { return (ObservableCollection<double>)GetValue(TickPositionsProperty); }
231            set { SetValue(TickPositionsProperty, value); }
232        }
233
234        // Using a DependencyProperty as the backing store for HorizontalAxisTickPositions.  This enables animation, styling, binding, etc...
235        public static readonly DependencyProperty TickPositionsProperty =
236            DependencyProperty.Register("TickPositions", typeof(ObservableCollection<double>), typeof(DiscreteAxisPanel), new UIPropertyMetadata(null));
237
238
239
240        public Orientation Orientation
241        {
242            get { return (Orientation)GetValue(OrientationProperty); }
243            set { SetValue(OrientationProperty, value); }
244        }
245
246        // Using a DependencyProperty as the backing store for Orientation.  This enables animation, styling, binding, etc...
247        public static readonly DependencyProperty OrientationProperty =
248            DependencyProperty.Register("Orientation", typeof(Orientation), typeof(DiscreteAxisPanel), new UIPropertyMetadata(Orientation.Horizontal));
249
250
251        public double Origin
252        {
253            get { return (double)GetValue(OriginProperty); }
254            set { SetValue(OriginProperty, value); }
255        }
256
257        // Using a DependencyProperty as the backing store for Origin.  This enables animation, styling, binding, etc...
258        public static readonly DependencyProperty OriginProperty =
259            DependencyProperty.Register("Origin", typeof(double), typeof(DiscreteAxisPanel), new UIPropertyMetadata(0.0));
260
261
262        private ItemsControl _parentControl;
263        private Size _largestLabelSize;
264    }
265}