using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Media; using System.Windows.Controls; using System.Windows.Shapes; using System.Windows.Data; using System.Diagnostics.CodeAnalysis; namespace Microsoft.Research.DynamicDataDisplay.Charts { /// /// Represents rectangle with corners bound to viewport coordinates. /// [TemplatePart(Name = "PART_LinesPath", Type = typeof(Path))] [TemplatePart(Name = "PART_RectPath", Type = typeof(Path))] public abstract class RangeHighlight : Control, IPlotterElement { /// /// Initializes a new instance of the class. /// protected RangeHighlight() { Resources = new ResourceDictionary { Source = new Uri("/DynamicDataDisplay;component/Charts/Shapes/RangeHighlightStyle.xaml", UriKind.Relative) }; Style = (Style)FindResource(typeof(RangeHighlight)); ApplyTemplate(); } bool partsLoaded = false; protected bool PartsLoaded { get { return partsLoaded; } } public override void OnApplyTemplate() { base.OnApplyTemplate(); linesPath = (Path)Template.FindName("PART_LinesPath", this); GeometryGroup linesGroup = new GeometryGroup(); linesGroup.Children.Add(lineGeometry1); linesGroup.Children.Add(lineGeometry2); linesPath.Data = linesGroup; rectPath = (Path)Template.FindName("PART_RectPath", this); rectPath.Data = rectGeometry; partsLoaded = true; } #region Presentation DPs public static readonly DependencyProperty FillProperty = DependencyProperty.Register( "Fill", typeof(Brush), typeof(RangeHighlight), new PropertyMetadata(Shape.FillProperty.DefaultMetadata.DefaultValue)); public Brush Fill { get { return (Brush)GetValue(FillProperty); } set { SetValue(FillProperty, value); } } public static readonly DependencyProperty StrokeProperty = DependencyProperty.Register( "Stroke", typeof(Brush), typeof(RangeHighlight), new PropertyMetadata(Shape.StrokeProperty.DefaultMetadata.DefaultValue)); public Brush Stroke { get { return (Brush)GetValue(StrokeProperty); } set { SetValue(StrokeProperty, value); } } public static readonly DependencyProperty StrokeThicknessProperty = DependencyProperty.Register( "StrokeThickness", typeof(double), typeof(RangeHighlight), new PropertyMetadata(Shape.StrokeThicknessProperty.DefaultMetadata.DefaultValue)); public double StrokeThickness { get { return (double)GetValue(StrokeThicknessProperty); } set { SetValue(StrokeThicknessProperty, value); } } public static readonly DependencyProperty StrokeStartLineCapProperty = DependencyProperty.Register( "StrokeStartLineCap", typeof(PenLineCap), typeof(RangeHighlight), new PropertyMetadata(Shape.StrokeStartLineCapProperty.DefaultMetadata.DefaultValue)); public PenLineCap StrokeStartLineCap { get { return (PenLineCap)GetValue(StrokeStartLineCapProperty); } set { SetValue(StrokeStartLineCapProperty, value); } } public static readonly DependencyProperty StrokeEndLineCapProperty = DependencyProperty.Register( "StrokeEndLineCap", typeof(PenLineCap), typeof(RangeHighlight), new PropertyMetadata(Shape.StrokeEndLineCapProperty.DefaultMetadata.DefaultValue)); public PenLineCap StrokeEndLineCap { get { return (PenLineCap)GetValue(StrokeEndLineCapProperty); } set { SetValue(StrokeEndLineCapProperty, value); } } public static readonly DependencyProperty StrokeDashCapProperty = DependencyProperty.Register( "StrokeDashCap", typeof(PenLineCap), typeof(RangeHighlight), new PropertyMetadata(Shape.StrokeDashCapProperty.DefaultMetadata.DefaultValue)); public PenLineCap StrokeDashCap { get { return (PenLineCap)GetValue(StrokeDashCapProperty); } set { SetValue(StrokeDashCapProperty, value); } } public static readonly DependencyProperty StrokeLineJoinProperty = DependencyProperty.Register( "StrokeLineJoin", typeof(PenLineJoin), typeof(RangeHighlight), new PropertyMetadata(Shape.StrokeLineJoinProperty.DefaultMetadata.DefaultValue)); public PenLineJoin StrokeLineJoin { get { return (PenLineJoin)GetValue(StrokeLineJoinProperty); } set { SetValue(StrokeLineJoinProperty, value); } } public static readonly DependencyProperty StrokeMiterLimitProperty = DependencyProperty.Register( "StrokeMiterLimit", typeof(double), typeof(RangeHighlight), new PropertyMetadata(Shape.StrokeMiterLimitProperty.DefaultMetadata.DefaultValue)); public double StrokeMiterLimit { get { return (double)GetValue(StrokeMiterLimitProperty); } set { SetValue(StrokeMiterLimitProperty, value); } } public static readonly DependencyProperty StrokeDashOffsetProperty = DependencyProperty.Register( "StrokeDashOffset", typeof(double), typeof(RangeHighlight), new PropertyMetadata(Shape.StrokeDashOffsetProperty.DefaultMetadata.DefaultValue)); public double StrokeDashOffset { get { return (double)GetValue(StrokeDashOffsetProperty); } set { SetValue(StrokeDashOffsetProperty, value); } } public static readonly DependencyProperty StrokeDashArrayProperty = DependencyProperty.Register( "StrokeDashArray", typeof(DoubleCollection), typeof(RangeHighlight), new PropertyMetadata(Shape.StrokeDashArrayProperty.DefaultMetadata.DefaultValue)); [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] public DoubleCollection StrokeDashArray { get { return (DoubleCollection)GetValue(StrokeDashArrayProperty); } set { SetValue(StrokeDashArrayProperty, value); } } #endregion #region Values dependency properties /// /// Gets or sets the first value determining position of rectangle in viewport coordinates. /// /// The value1. public double Value1 { get { return (double)GetValue(Value1Property); } set { SetValue(Value1Property, value); } } public static readonly DependencyProperty Value1Property = DependencyProperty.Register( "Value1", typeof(double), typeof(RangeHighlight), new FrameworkPropertyMetadata(0.0, OnValueChanged)); private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { RangeHighlight r = (RangeHighlight)d; r.OnValueChanged(e); } /// /// Gets or sets the second value determining position of rectangle in viewport coordinates. /// /// The value2. public double Value2 { get { return (double)GetValue(Value2Property); } set { SetValue(Value2Property, value); } } public static readonly DependencyProperty Value2Property = DependencyProperty.Register( "Value2", typeof(double), typeof(RangeHighlight), new FrameworkPropertyMetadata(0.0, OnValueChanged)); private void OnValueChanged(DependencyPropertyChangedEventArgs e) { UpdateUIRepresentation(); } #endregion #region Geometry private Path rectPath; private Path linesPath; private readonly RectangleGeometry rectGeometry = new RectangleGeometry(); protected RectangleGeometry RectGeometry { get { return rectGeometry; } } private readonly LineGeometry lineGeometry1 = new LineGeometry(); protected LineGeometry LineGeometry1 { get { return lineGeometry1; } } private readonly LineGeometry lineGeometry2 = new LineGeometry(); protected LineGeometry LineGeometry2 { get { return lineGeometry2; } } #endregion #region IPlotterElement Members private Plotter2D plotter; void IPlotterElement.OnPlotterAttached(Plotter plotter) { plotter.CentralGrid.Children.Add(this); Plotter2D plotter2d = (Plotter2D)plotter; this.plotter = plotter2d; plotter2d.Viewport.PropertyChanged += Viewport_PropertyChanged; UpdateUIRepresentation(); } private void UpdateUIRepresentation() { if (Plotter == null) return; if (partsLoaded) { UpdateUIRepresentationCore(); } } protected virtual void UpdateUIRepresentationCore() { } void Viewport_PropertyChanged(object sender, ExtendedPropertyChangedEventArgs e) { UpdateUIRepresentation(); } void IPlotterElement.OnPlotterDetaching(Plotter plotter) { Plotter2D plotter2d = (Plotter2D)plotter; plotter2d.Viewport.PropertyChanged -= Viewport_PropertyChanged; plotter.CentralGrid.Children.Remove(this); this.plotter = null; } public Plotter2D Plotter { get { return plotter; } } Plotter IPlotterElement.Plotter { get { return plotter; } } #endregion } }