/Main/src/DynamicDataDisplay/ChartPlotter.cs
C# | 526 lines | 364 code | 74 blank | 88 comment | 55 complexity | ca590ef526836dbaf92113a00c203eb6 MD5 | raw file
Possible License(s): CC-BY-SA-3.0
- using System;
- using System.Linq;
- using System.ComponentModel;
- using System.Windows;
- using System.Windows.Controls;
- using Microsoft.Research.DynamicDataDisplay.Charts;
- using Microsoft.Research.DynamicDataDisplay.Charts.Navigation;
- using Microsoft.Research.DynamicDataDisplay.Navigation;
- using Microsoft.Research.DynamicDataDisplay.Common;
- using Microsoft.Research.DynamicDataDisplay.Charts.Axes;
-
- namespace Microsoft.Research.DynamicDataDisplay
- {
- /// <summary>
- /// Chart plotter is a plotter that renders axis and grid
- /// </summary>
- public class ChartPlotter : Plotter2D
- {
- private GeneralAxis horizontalAxis = new HorizontalAxis();
- private GeneralAxis verticalAxis = new VerticalAxis();
- private AxisGrid axisGrid = new AxisGrid();
-
- private Legend legend = new Legend();
-
- public ItemsPanelTemplate LegendPanelTemplate
- {
- get { return legend.ItemsPanel; }
- set
- {
- if (legend == null)
- throw new ArgumentNullException("LegendPanelTemplate");
-
- legend.ItemsPanel = value;
- }
- }
-
- public Style LegendStyle
- {
- get { return legend.Style; }
- set { legend.Style = value; }
- }
-
- /// <summary>
- /// Sets a value indicating whether to enable smooth axes panning for numeric axes.
- /// </summary>
- /// <value>
- /// <c>true</c> if enable smooth axes panning for numeric axes; otherwise, <c>false</c>.
- /// </value>
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- public bool EnableSmoothPanningForNumericAxes
- {
- // todo improve returned value
- get { return false; }// throw new NotImplementedException(); }
- set
- {
- foreach (var axis in Children.OfType<NumericAxis>())
- {
- axis.UseSmoothPanning = value;
- }
- }
- }
-
- /// <summary>
- /// Initializes a new instance of the <see cref="ChartPlotter"/> class.
- /// </summary>
- public ChartPlotter()
- : base()
- {
- horizontalAxis.TicksChanged += OnHorizontalAxisTicksChanged;
- verticalAxis.TicksChanged += OnVerticalAxisTicksChanged;
-
- SetIsDefaultAxis(horizontalAxis as DependencyObject, true);
- SetIsDefaultAxis(verticalAxis as DependencyObject, true);
-
- mouseNavigation = new MouseNavigation();
- keyboardNavigation = new KeyboardNavigation();
- defaultContextMenu = new DefaultContextMenu();
- horizontalAxisNavigation = new AxisNavigation { Placement = AxisPlacement.Bottom };
- verticalAxisNavigation = new AxisNavigation { Placement = AxisPlacement.Left };
-
- Children.AddMany(
- horizontalAxis,
- verticalAxis,
- axisGrid,
- mouseNavigation,
- keyboardNavigation,
- defaultContextMenu,
- horizontalAxisNavigation,
- verticalAxisNavigation,
- new LongOperationsIndicator(),
- legend
- );
-
- #if DEBUG
- Children.Add(new DebugMenu());
- #endif
-
- SetAllChildrenAsDefault();
- }
-
- /// <summary>
- /// Creates generic plotter from this ChartPlotter.
- /// </summary>
- /// <returns></returns>
- public GenericChartPlotter<double, double> GetGenericPlotter()
- {
- return new GenericChartPlotter<double, double>(this);
- }
-
- /// <summary>
- /// Creates generic plotter from this ChartPlotter.
- /// Horizontal and Vertical types of GenericPlotter should correspond to ChartPlotter's actual main axes types.
- /// </summary>
- /// <typeparam name="THorizontal">The type of horizontal values.</typeparam>
- /// <typeparam name="TVertical">The type of vertical values.</typeparam>
- /// <returns>GenericChartPlotter, associated to this ChartPlotter.</returns>
- public GenericChartPlotter<THorizontal, TVertical> GetGenericPlotter<THorizontal, TVertical>()
- {
- return new GenericChartPlotter<THorizontal, TVertical>(this);
- }
-
- /// <summary>
- /// Creates generic plotter from this ChartPlotter.
- /// </summary>
- /// <typeparam name="THorizontal">The type of the horizontal axis.</typeparam>
- /// <typeparam name="TVertical">The type of the vertical axis.</typeparam>
- /// <param name="horizontalAxis">The horizontal axis to use as data conversion source.</param>
- /// <param name="verticalAxis">The vertical axis to use as data conversion source.</param>
- /// <returns>GenericChartPlotter, associated to this ChartPlotter</returns>
- public GenericChartPlotter<THorizontal, TVertical> GetGenericPlotter<THorizontal, TVertical>(AxisBase<THorizontal> horizontalAxis, AxisBase<TVertical> verticalAxis)
- {
- return new GenericChartPlotter<THorizontal, TVertical>(this, horizontalAxis, verticalAxis);
- }
-
- protected ChartPlotter(PlotterLoadMode loadMode) : base(loadMode) { }
-
- /// <summary>
- /// Creates empty plotter without any axes, navigation, etc.
- /// </summary>
- /// <returns>Empty plotter without any axes, navigation, etc.</returns>
- public static ChartPlotter CreateEmpty()
- {
- return new ChartPlotter(PlotterLoadMode.OnlyViewport);
- }
-
- public void BeginLongOperation()
- {
- LongOperationsIndicator.BeginLongOperation(this);
- }
-
- public void EndLongOperation()
- {
- LongOperationsIndicator.EndLongOperation(this);
- }
-
- #region Default charts
-
- private MouseNavigation mouseNavigation;
- /// <summary>
- /// Gets the default mouse navigation of ChartPlotter.
- /// </summary>
- /// <value>The mouse navigation.</value>
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- public MouseNavigation MouseNavigation
- {
- get { return mouseNavigation; }
- }
-
- private KeyboardNavigation keyboardNavigation;
- /// <summary>
- /// Gets the default keyboard navigation of ChartPlotter.
- /// </summary>
- /// <value>The keyboard navigation.</value>
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- public KeyboardNavigation KeyboardNavigation
- {
- get { return keyboardNavigation; }
- }
-
- private DefaultContextMenu defaultContextMenu;
- /// <summary>
- /// Gets the default context menu of ChartPlotter.
- /// </summary>
- /// <value>The default context menu.</value>
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- public DefaultContextMenu DefaultContextMenu
- {
- get { return defaultContextMenu; }
- }
-
- private AxisNavigation horizontalAxisNavigation;
- /// <summary>
- /// Gets the default horizontal axis navigation of ChartPlotter.
- /// </summary>
- /// <value>The horizontal axis navigation.</value>
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- public AxisNavigation HorizontalAxisNavigation
- {
- get { return horizontalAxisNavigation; }
- }
-
- private AxisNavigation verticalAxisNavigation;
- /// <summary>
- /// Gets the default vertical axis navigation of ChartPlotter.
- /// </summary>
- /// <value>The vertical axis navigation.</value>
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- public AxisNavigation VerticalAxisNavigation
- {
- get { return verticalAxisNavigation; }
- }
-
- /// <summary>
- /// Gets the default axis grid of ChartPlotter.
- /// </summary>
- /// <value>The axis grid.</value>
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- public AxisGrid AxisGrid
- {
- get { return axisGrid; }
- }
-
- #endregion
-
- private void OnHorizontalAxisTicksChanged(object sender, EventArgs e)
- {
- GeneralAxis axis = (GeneralAxis)sender;
- UpdateHorizontalTicks(axis);
- }
-
- private void UpdateHorizontalTicks(GeneralAxis axis)
- {
- axisGrid.BeginTicksUpdate();
-
- if (axis != null)
- {
- axisGrid.HorizontalTicks = axis.ScreenTicks;
- axisGrid.MinorHorizontalTicks = axis.MinorScreenTicks;
- }
- else
- {
- axisGrid.HorizontalTicks = null;
- axisGrid.MinorHorizontalTicks = null;
- }
-
- axisGrid.EndTicksUpdate();
- }
-
- private void OnVerticalAxisTicksChanged(object sender, EventArgs e)
- {
- GeneralAxis axis = (GeneralAxis)sender;
- UpdateVerticalTicks(axis);
- }
-
- private void UpdateVerticalTicks(GeneralAxis axis)
- {
- axisGrid.BeginTicksUpdate();
-
- if (axis != null)
- {
- axisGrid.VerticalTicks = axis.ScreenTicks;
- axisGrid.MinorVerticalTicks = axis.MinorScreenTicks;
- }
- else
- {
- axisGrid.VerticalTicks = null;
- axisGrid.MinorVerticalTicks = null;
- }
-
- axisGrid.EndTicksUpdate();
- }
-
- bool keepOldAxis = false;
- bool updatingAxis = false;
-
- /// <summary>
- /// Gets or sets the main vertical axis of ChartPlotter.
- /// Main vertical axis of ChartPlotter is axis which ticks are used to draw horizontal lines on AxisGrid.
- /// Value can be set to null to completely remove main vertical axis.
- /// </summary>
- /// <value>The main vertical axis.</value>
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- public GeneralAxis MainVerticalAxis
- {
- get { return verticalAxis; }
- set
- {
- if (updatingAxis)
- return;
-
- if (value == null && verticalAxis != null)
- {
- if (!keepOldAxis)
- {
- Children.Remove(verticalAxis);
- }
- verticalAxis.TicksChanged -= OnVerticalAxisTicksChanged;
- verticalAxis = null;
-
- UpdateVerticalTicks(verticalAxis);
-
- return;
- }
-
- VerifyAxisType(value.Placement, AxisType.Vertical);
-
- if (value != verticalAxis)
- {
- ValidateVerticalAxis(value);
-
- updatingAxis = true;
-
- if (verticalAxis != null)
- {
- verticalAxis.TicksChanged -= OnVerticalAxisTicksChanged;
- SetIsDefaultAxis(verticalAxis, false);
- if (!keepOldAxis)
- {
- Children.Remove(verticalAxis);
- }
- value.Visibility = verticalAxis.Visibility;
- }
- SetIsDefaultAxis(value, true);
-
- verticalAxis = value;
- verticalAxis.TicksChanged += OnVerticalAxisTicksChanged;
-
- if (!Children.Contains(value))
- {
- Children.Add(value);
- }
-
- UpdateVerticalTicks(value);
- OnVerticalAxisChanged();
-
- updatingAxis = false;
- }
- }
- }
-
- protected virtual void OnVerticalAxisChanged() { }
- protected virtual void ValidateVerticalAxis(GeneralAxis axis) { }
-
- /// <summary>
- /// Gets or sets the main horizontal axis visibility.
- /// </summary>
- /// <value>The main horizontal axis visibility.</value>
- public Visibility MainHorizontalAxisVisibility
- {
- get { return MainHorizontalAxis != null ? ((UIElement)MainHorizontalAxis).Visibility : Visibility.Hidden; }
- set
- {
- if (MainHorizontalAxis != null)
- {
- ((UIElement)MainHorizontalAxis).Visibility = value;
- }
- }
- }
-
- /// <summary>
- /// Gets or sets the main vertical axis visibility.
- /// </summary>
- /// <value>The main vertical axis visibility.</value>
- public Visibility MainVerticalAxisVisibility
- {
- get { return MainVerticalAxis != null ? ((UIElement)MainVerticalAxis).Visibility : Visibility.Hidden; }
- set
- {
- if (MainVerticalAxis != null)
- {
- ((UIElement)MainVerticalAxis).Visibility = value;
- }
- }
- }
-
- /// <summary>
- /// Gets or sets the main horizontal axis of ChartPlotter.
- /// Main horizontal axis of ChartPlotter is axis which ticks are used to draw vertical lines on AxisGrid.
- /// Value can be set to null to completely remove main horizontal axis.
- /// </summary>
- /// <value>The main horizontal axis.</value>
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- public GeneralAxis MainHorizontalAxis
- {
- get { return horizontalAxis; }
- set
- {
- if (updatingAxis)
- return;
-
- if (value == null && horizontalAxis != null)
- {
- Children.Remove(horizontalAxis);
- horizontalAxis.TicksChanged -= OnHorizontalAxisTicksChanged;
- horizontalAxis = null;
-
- UpdateHorizontalTicks(horizontalAxis);
-
- return;
- }
-
- VerifyAxisType(value.Placement, AxisType.Horizontal);
-
- if (value != horizontalAxis)
- {
- ValidateHorizontalAxis(value);
-
- updatingAxis = true;
-
- if (horizontalAxis != null)
- {
- horizontalAxis.TicksChanged -= OnHorizontalAxisTicksChanged;
- SetIsDefaultAxis(horizontalAxis, false);
- if (!keepOldAxis)
- {
- Children.Remove(horizontalAxis);
- }
- value.Visibility = horizontalAxis.Visibility;
- }
- SetIsDefaultAxis(value, true);
-
- horizontalAxis = value;
- horizontalAxis.TicksChanged += OnHorizontalAxisTicksChanged;
-
- if (!Children.Contains(value))
- {
- Children.Add(value);
- }
-
- UpdateHorizontalTicks(value);
- OnHorizontalAxisChanged();
-
- updatingAxis = false;
- }
- }
- }
-
- protected virtual void OnHorizontalAxisChanged() { }
- protected virtual void ValidateHorizontalAxis(GeneralAxis axis) { }
-
- private static void VerifyAxisType(AxisPlacement axisPlacement, AxisType axisType)
- {
- bool result = false;
- switch (axisPlacement)
- {
- case AxisPlacement.Left:
- case AxisPlacement.Right:
- result = axisType == AxisType.Vertical;
- break;
- case AxisPlacement.Top:
- case AxisPlacement.Bottom:
- result = axisType == AxisType.Horizontal;
- break;
- default:
- break;
- }
-
- if (!result)
- throw new ArgumentException(Strings.Exceptions.InvalidAxisPlacement);
- }
-
- protected override void OnIsDefaultAxisChangedCore(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- GeneralAxis axis = d as GeneralAxis;
- if (axis != null)
- {
- bool value = (bool)e.NewValue;
- bool oldKeepOldAxis = keepOldAxis;
-
- bool horizontal = axis.Placement == AxisPlacement.Bottom || axis.Placement == AxisPlacement.Top;
- keepOldAxis = true;
-
- if (value && horizontal)
- {
- MainHorizontalAxis = axis;
- }
- else if (value && !horizontal)
- {
- MainVerticalAxis = axis;
- }
- else if (!value && horizontal)
- {
- MainHorizontalAxis = null;
- }
- else if (!value && !horizontal)
- {
- MainVerticalAxis = null;
- }
-
- keepOldAxis = oldKeepOldAxis;
- }
- }
-
- /// <summary>
- /// Gets the default legend of ChartPlotter.
- /// </summary>
- /// <value>The legend.</value>
- [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
- public Legend Legend
- {
- get { return legend; }
- }
-
- /// <summary>
- /// Gets or sets the visibility of legend.
- /// </summary>
- /// <value>The legend visibility.</value>
- public Visibility LegendVisibility
- {
- get { return legend.Visibility; }
- set { legend.Visibility = value; }
- }
-
- public bool LegendVisible
- {
- get { return legend.LegendVisible; }
- set { legend.LegendVisible = value; }
- }
-
- private enum AxisType
- {
- Horizontal,
- Vertical
- }
- }
- }