/Main/src/DynamicDataDisplay/Charts/ViewportHostPanel.cs
C# | 330 lines | 248 code | 57 blank | 25 comment | 51 complexity | 50f1819e5c982265f6f99805e5a85d49 MD5 | raw file
Possible License(s): CC-BY-SA-3.0
1using System; 2using System.Collections.Generic; 3using System.Linq; 4using System.Text; 5using System.Windows.Media; 6using System.Windows; 7using System.Windows.Controls; 8using System.Diagnostics; 9using Microsoft.Research.DynamicDataDisplay.Common.Auxiliary; 10using System.Windows.Threading; 11using d3 = Microsoft.Research.DynamicDataDisplay; 12using Microsoft.Research.DynamicDataDisplay.Common; 13 14namespace Microsoft.Research.DynamicDataDisplay.Charts 15{ 16 public class ViewportHostPanel : ViewportPanel, IPlotterElement 17 { 18 static ViewportHostPanel() 19 { 20 //EventManager.RegisterClassHandler(typeof(ViewportHostPanel), d3.Plotter.PlotterChangedEvent, new PlotterChangedEventHandler(OnPlotterChanged)); 21 } 22 23 public ViewportHostPanel() 24 { 25#if false 26 // for debug purposes 27 Width = 100; 28 Height = 100; 29 Background = Brushes.PaleGreen.MakeTransparent(0.2); 30#endif 31 } 32 33 private static void OnPlotterChanged(object sender, PlotterChangedEventArgs e) 34 { 35 ViewportHostPanel owner = (ViewportHostPanel)sender; 36 37 if (owner.plotter != null && e.PreviousPlotter != null) 38 { 39 owner.viewport.PropertyChanged -= owner.Viewport_PropertyChanged; 40 owner.viewport = null; 41 owner.plotter = null; 42 } 43 if (owner.plotter == null && e.CurrentPlotter != null) 44 { 45 owner.plotter = (Plotter2D)e.CurrentPlotter; 46 owner.viewport = owner.plotter.Viewport; 47 owner.viewport.PropertyChanged += owner.Viewport_PropertyChanged; 48 } 49 } 50 51 private Canvas hostingCanvas = new Canvas(); 52 internal Canvas HostingCanvas 53 { 54 get { return hostingCanvas; } 55 } 56 57 #region IPlotterElement Members 58 59 private Plotter2D plotter; 60 public Plotter2D Plotter 61 { 62 get { return plotter; } 63 } 64 65 Viewport2D viewport; 66 public virtual void OnPlotterAttached(Plotter plotter) 67 { 68 this.plotter = (Plotter2D)plotter; 69 viewport = this.plotter.Viewport; 70 71 if (!IsMarkersHost) 72 { 73 plotter.CentralGrid.Children.Add(hostingCanvas); 74 } 75 if (Parent == null) 76 { 77 hostingCanvas.Children.Add(this); 78 } 79 this.plotter.Viewport.PropertyChanged += Viewport_PropertyChanged; 80 } 81 82 public virtual void OnPlotterDetaching(Plotter plotter) 83 { 84 this.plotter.Viewport.PropertyChanged -= Viewport_PropertyChanged; 85 86 if (!IsMarkersHost) 87 { 88 plotter.CentralGrid.Children.Remove(hostingCanvas); 89 } 90 hostingCanvas.Children.Remove(this); 91 92 this.plotter = null; 93 } 94 95 Plotter IPlotterElement.Plotter 96 { 97 get { return plotter; } 98 } 99 100 protected override void OnChildDesiredSizeChanged(UIElement child) 101 { 102 base.OnChildDesiredSizeChanged(child); 103 InvalidatePosition((FrameworkElement)child); 104 } 105 106 Vector prevVisualOffset; 107 bool sizeChanged = true; 108 DataRect visibleWhileCreation; 109 protected virtual void Viewport_PropertyChanged(object sender, ExtendedPropertyChangedEventArgs e) 110 { 111 if (e.PropertyName == Viewport2D.VisiblePropertyName) 112 { 113 DataRect visible = (DataRect)e.NewValue; 114 DataRect prevVisible = (DataRect)e.OldValue; 115 116 InvalidateMeasure(); 117 // todo previous way 118// if (prevVisible.Size.EqualsApproximately(visible.Size) && !sizeChanged) 119// { 120// var transform = viewport.Transform; 121 122// Point prevLocation = prevVisible.Location.ViewportToScreen(transform); 123// Point location = visible.Location.ViewportToScreen(transform); 124 125// Vector offset = prevLocation - location; 126// // todo was true 127//#if false 128// translateTransform.X += offset.X; 129// translateTransform.Y += offset.Y; 130//#else 131// InvalidateMeasure(); 132//#endif 133 134// } 135// else 136// { 137// visibleWhileCreation = visible; 138// translateTransform.X = 0; 139// translateTransform.Y = 0; 140// InvalidateMeasure(); 141// } 142 143 sizeChanged = false; 144 } 145 else if (e.PropertyName == "Output") 146 { 147 sizeChanged = true; 148 InvalidateMeasure(); 149 } 150 151 prevVisualOffset = VisualOffset; 152 } 153 154 #endregion 155 156 protected internal override void OnChildAdded(FrameworkElement child) 157 { 158 if (plotter == null) return; 159 160 InvalidatePosition(child); 161 //Dispatcher.BeginInvoke(((Action)(()=> InvalidatePosition(child))), DispatcherPriority.ApplicationIdle); 162 } 163 164 private DataRect overallViewportBounds = DataRect.Empty; 165 internal DataRect OverallViewportBounds 166 { 167 get { return overallViewportBounds; } 168 set { overallViewportBounds = value; } 169 } 170 171 private BoundsUnionMode boundsUnionMode; 172 internal BoundsUnionMode BoundsUnionMode 173 { 174 get { return boundsUnionMode; } 175 set { boundsUnionMode = value; } 176 } 177 178 protected override void InvalidatePosition(FrameworkElement child) 179 { 180 invalidatePositionCalls++; 181 182 if (viewport == null) return; 183 if (child.Visibility != Visibility.Visible) 184 return; 185 186 var transform = viewport.Transform; 187 188 Size elementSize = GetElementSize(child, AvailableSize, transform); 189 child.Measure(elementSize); 190 191 Rect bounds = GetElementScreenBounds(transform, child); 192 child.Arrange(bounds); 193 194 var viewportBounds = Viewport2D.GetContentBounds(this); 195 if (!viewportBounds.IsEmpty) 196 overallViewportBounds = viewportBounds; 197 198 UniteWithBounds(transform, bounds); 199 200 if (!InBatchAdd) 201 { 202 Viewport2D.SetContentBounds(this, overallViewportBounds); 203 ContentBoundsChanged.Raise(this); 204 } 205 } 206 207 private void UniteWithBounds(CoordinateTransform transform, Rect bounds) 208 { 209 var childViewportBounds = bounds.ScreenToViewport(transform); 210 if (boundsUnionMode == BoundsUnionMode.Bounds) 211 overallViewportBounds.Union(childViewportBounds); 212 else 213 { 214 overallViewportBounds.Union(childViewportBounds.GetCenter()); 215 } 216 } 217 218 int invalidatePositionCalls = 0; 219 public override void BeginBatchAdd() 220 { 221 base.BeginBatchAdd(); 222 invalidatePositionCalls = 0; 223 } 224 225 public override void EndBatchAdd() 226 { 227 base.EndBatchAdd(); 228 229 if (plotter == null) return; 230 231 UpdateContentBounds(Children.Count > 0 && invalidatePositionCalls == 0); 232 } 233 234 public void UpdateContentBounds() 235 { 236 UpdateContentBounds(true); 237 } 238 239 private void UpdateContentBounds(bool recalculate) 240 { 241 if (recalculate) 242 { 243 var transform = plotter.Viewport.Transform; 244 overallViewportBounds = DataRect.Empty; 245 foreach (FrameworkElement child in Children) 246 { 247 if (child != null) 248 { 249 if (child.Visibility != Visibility.Visible) 250 continue; 251 252 Rect bounds = GetElementScreenBounds(transform, child); 253 UniteWithBounds(transform, bounds); 254 } 255 } 256 } 257 258 Viewport2D.SetContentBounds(this, overallViewportBounds); 259 ContentBoundsChanged.Raise(this); 260 } 261 262 protected override Size ArrangeOverride(Size finalSize) 263 { 264 if (plotter == null) 265 return finalSize; 266 267 var transform = plotter.Viewport.Transform; 268 269 overallViewportBounds = DataRect.Empty; 270 foreach (UIElement child in InternalChildren) 271 { 272 if (child != null) 273 { 274 if (child.Visibility != Visibility.Visible) 275 continue; 276 277 Rect bounds = GetElementScreenBounds(transform, child); 278 child.Arrange(bounds); 279 280 UniteWithBounds(transform, bounds); 281 } 282 } 283 284 if (!InBatchAdd) 285 { 286 Viewport2D.SetContentBounds(this, overallViewportBounds); 287 ContentBoundsChanged.Raise(this); 288 } 289 290 return finalSize; 291 } 292 293 public event EventHandler ContentBoundsChanged; 294 295 protected override Size MeasureOverride(Size availableSize) 296 { 297 AvailableSize = availableSize; 298 299 if (plotter == null) 300 { 301 if (availableSize.Width.IsInfinite() || availableSize.Height.IsInfinite()) 302 return new Size(); 303 return availableSize; 304 } 305 306 var transform = plotter.Viewport.Transform; 307 308 foreach (FrameworkElement child in InternalChildren) 309 { 310 if (child != null) 311 { 312 Size elementSize = GetElementSize(child, availableSize, transform); 313 child.Measure(elementSize); 314 } 315 } 316 317 if (availableSize.Width.IsInfinite()) 318 availableSize.Width = 0; 319 if (availableSize.Height.IsInfinite()) 320 availableSize.Height = 0; 321 return availableSize; 322 } 323 } 324 325 public enum BoundsUnionMode 326 { 327 Center, 328 Bounds 329 } 330}