using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using Microsoft.Research.DynamicDataDisplay.Common.Auxiliary; using System.Windows.Threading; using System.Diagnostics; namespace Microsoft.Research.DynamicDataDisplay { public partial class Viewport2D { #region IsContentBoundsHost attached property public static bool GetIsContentBoundsHost(DependencyObject obj) { return (bool)obj.GetValue(IsContentBoundsHostProperty); } public static void SetIsContentBoundsHost(DependencyObject obj, bool value) { obj.SetValue(IsContentBoundsHostProperty, value); } public static readonly DependencyProperty IsContentBoundsHostProperty = DependencyProperty.RegisterAttached( "IsContentBoundsHost", typeof(bool), typeof(Viewport2D), new FrameworkPropertyMetadata(true, OnIsContentBoundsChanged)); private static void OnIsContentBoundsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { IPlotterElement plotterElement = d as IPlotterElement; if (plotterElement != null && plotterElement.Plotter != null) { Plotter2D plotter2d = (Plotter2D)plotterElement.Plotter; plotter2d.Viewport.UpdateContentBoundsHosts(); } } #endregion #region ContentBounds attached property public static DataRect GetContentBounds(DependencyObject obj) { return (DataRect)obj.GetValue(ContentBoundsProperty); } public static void SetContentBounds(DependencyObject obj, DataRect value) { obj.SetValue(ContentBoundsProperty, value); } public static readonly DependencyProperty ContentBoundsProperty = DependencyProperty.RegisterAttached( "ContentBounds", typeof(DataRect), typeof(Viewport2D), new FrameworkPropertyMetadata(DataRect.Empty, OnContentBoundsChanged, CoerceContentBounds)); private static object CoerceContentBounds(DependencyObject d, object value) { DataRect prevBounds = GetContentBounds(d); DataRect currBounds = (DataRect)value; bool approximateComparanceAllowed = GetUsesApproximateContentBoundsComparison(d); bool areClose = approximateComparanceAllowed && currBounds.IsCloseTo(prevBounds, 0.005); if (areClose) return DependencyProperty.UnsetValue; else return value; } private static void OnContentBoundsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { IPlotterElement element = d as IPlotterElement; if (element != null) { FrameworkElement frElement = element as FrameworkElement; if (frElement != null) { frElement.RaiseEvent(new RoutedEventArgs(ContentBoundsChangedEvent)); } Plotter2D plotter2d = element.Plotter as Plotter2D; if (plotter2d != null) { plotter2d.Viewport.UpdateContentBoundsHosts(); } } } public static readonly RoutedEvent ContentBoundsChangedEvent = EventManager.RegisterRoutedEvent( "ContentBoundsChanged", RoutingStrategy.Direct, typeof(RoutedEventHandler), typeof(Viewport2D)); #endregion #region UsesApproximateContentBoundsComparison /// /// Gets a value indicating whether approximate content bounds comparison will be used while deciding whether to updating Viewport2D.ContentBounds /// attached dependency property or not. /// Approximate content bounds comparison can make Viewport's Visible to changed less frequent, but it can lead to /// some bugs if content bounds are large but visible area is not compared to them. /// /// /// true if approximate content bounds comparison is used while deciding whether to set new value of content bounds, or not; otherwise, false. /// public static bool GetUsesApproximateContentBoundsComparison(DependencyObject obj) { return (bool)obj.GetValue(UsesApproximateContentBoundsComparisonProperty); } /// /// Sets a value indicating whether approximate content bounds comparison will be used while deciding whether to updating Viewport2D.ContentBounds /// attached dependency property or not. /// Approximate content bounds comparison can make Viewport's Visible to changed less frequent, but it can lead to /// some bugs if content bounds are large but visible area is not compared to them. /// /// /// true if approximate content bounds comparison is used while deciding whether to set new value of content bounds, or not; otherwise, false. /// public static void SetUsesApproximateContentBoundsComparison(DependencyObject obj, bool value) { obj.SetValue(UsesApproximateContentBoundsComparisonProperty, value); } public static readonly DependencyProperty UsesApproximateContentBoundsComparisonProperty = DependencyProperty.RegisterAttached( "UsesApproximateContentBoundsComparison", typeof(bool), typeof(Viewport2D), new FrameworkPropertyMetadata(true, OnUsesApproximateContentBoundsComparisonChanged)); private static void OnUsesApproximateContentBoundsComparisonChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { IPlotterElement element = d as IPlotterElement; if (element != null) { Plotter2D plotter2d = element.Plotter as Plotter2D; if (plotter2d != null) { plotter2d.Viewport.UpdateVisible(); } } } #endregion // end of UsesApproximateContentBoundsComparison #region UseDeferredPanning attached property public static bool GetUseDeferredPanning(DependencyObject obj) { return (bool)obj.GetValue(UseDeferredPanningProperty); } public static void SetUseDeferredPanning(DependencyObject obj, bool value) { obj.SetValue(UseDeferredPanningProperty, value); } public static readonly DependencyProperty UseDeferredPanningProperty = DependencyProperty.RegisterAttached( "UseDeferredPanning", typeof(bool), typeof(Viewport2D), new FrameworkPropertyMetadata(false)); #endregion // end of UseDeferredPanning attached property } }