using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Automation.Peers;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Windows.Media.Imaging;
using Microsoft.Research.DynamicDataDisplay.Common;
using Microsoft.Research.DynamicDataDisplay.Common.Auxiliary;
using Microsoft.Research.DynamicDataDisplay.Common.UndoSystem;
using Microsoft.Research.DynamicDataDisplay.Navigation;
namespace Microsoft.Research.DynamicDataDisplay
{
/// Plotter is a base control for displaying various graphs. It provides
/// means to draw chart itself and side space for axes, annotations, etc
[ContentProperty("Children")]
[TemplatePart(Name = "PART_HeaderPanel", Type = typeof(StackPanel))]
[TemplatePart(Name = "PART_FooterPanel", Type = typeof(StackPanel))]
[TemplatePart(Name = "PART_BottomPanel", Type = typeof(StackPanel))]
[TemplatePart(Name = "PART_LeftPanel", Type = typeof(StackPanel))]
[TemplatePart(Name = "PART_RightPanel", Type = typeof(StackPanel))]
[TemplatePart(Name = "PART_TopPanel", Type = typeof(StackPanel))]
[TemplatePart(Name = "PART_MainCanvas", Type = typeof(Canvas))]
[TemplatePart(Name = "PART_CentralGrid", Type = typeof(Grid))]
[TemplatePart(Name = "PART_MainGrid", Type = typeof(Grid))]
[TemplatePart(Name = "PART_ContentsGrid", Type = typeof(Grid))]
[TemplatePart(Name = "PART_ParallelCanvas", Type = typeof(Canvas))]
public abstract class Plotter : ContentControl
{
private PlotterLoadMode loadMode = PlotterLoadMode.Normal;
protected PlotterLoadMode LoadMode
{
get { return loadMode; }
}
private static Plotter current;
///
/// Gets the current plotter. Used in VisualDebug.
///
/// The current.
internal static Plotter Current
{
get { return Plotter.current; }
}
protected Plotter() : this(PlotterLoadMode.Normal) { }
///
/// Initializes a new instance of the class.
///
protected Plotter(PlotterLoadMode loadMode)
{
current = this;
this.loadMode = loadMode;
SetPlotter(this, this);
if (loadMode == PlotterLoadMode.Normal)
{
UpdateUIParts();
}
children = new PlotterChildrenCollection(this);
children.CollectionChanged += OnChildrenCollectionChanged;
Loaded += Plotter_Loaded;
Unloaded += Plotter_Unloaded;
genericResources = (ResourceDictionary)Application.LoadComponent(new Uri("/DynamicDataDisplay;component/Themes/Generic.xaml", UriKind.Relative));
ContextMenu = null;
foreach (var panel in GetAllPanels().Where(panel => panel != null))
{
Plotter.SetIsDefaultPanel(panel, true);
}
}
private void Plotter_Unloaded(object sender, RoutedEventArgs e)
{
OnUnloaded();
}
protected virtual void OnUnloaded() { }
protected override AutomationPeer OnCreateAutomationPeer()
{
return new PlotterAutomationPeer(this);
}
[EditorBrowsable(EditorBrowsableState.Never)]
public override bool ShouldSerializeContent()
{
return false;
}
protected override bool ShouldSerializeProperty(DependencyProperty dp)
{
// do not serialize context menu if it was created by DefaultContextMenu, because that context menu items contains references of plotter
if (dp == ContextMenuProperty && children.Any(el => el is DefaultContextMenu)) return false;
if (dp == TemplateProperty) return false;
if (dp == ContentProperty) return false;
return base.ShouldSerializeProperty(dp);
}
private const string templateKey = "defaultPlotterTemplate";
private const string styleKey = "defaultPlotterStyle";
private void UpdateUIParts()
{
ResourceDictionary dict = new ResourceDictionary
{
Source = new Uri("/DynamicDataDisplay;component/Common/PlotterStyle.xaml", UriKind.Relative)
};
Resources.MergedDictionaries.Add(dict);
Style = (Style)dict[styleKey];
ControlTemplate template = (ControlTemplate)dict[templateKey];
Template = template;
ApplyTemplate();
}
private ResourceDictionary genericResources;
protected ResourceDictionary GenericResources
{
get { return genericResources; }
}
///
/// Forces plotter to load.
///
public void PerformLoad()
{
isLoadedIntensionally = true;
ApplyTemplate();
Plotter_Loaded(null, null);
}
private bool isLoadedIntensionally = false;
protected virtual bool IsLoadedInternal
{
get { return isLoadedIntensionally || IsLoaded; }
}
private void Plotter_Loaded(object sender, RoutedEventArgs e)
{
ExecuteWaitingChildrenAdditions();
OnLoaded();
}
protected internal void ExecuteWaitingChildrenAdditions()
{
executedWaitingChildrenAdding = true;
foreach (var pair in waitingForExecute)
{
pair.Value.Invoke();
}
waitingForExecute.Clear();
}
protected virtual void OnLoaded()
{
// this is done to enable keyboard shortcuts
Focus();
}
protected override void OnTemplateChanged(ControlTemplate oldTemplate, ControlTemplate newTemplate)
{
base.OnTemplateChanged(oldTemplate, newTemplate);
}
private Grid contentsGrid;
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
var headerPanel = GetPart("PART_HeaderPanel");
MigrateChildren(this.headerPanel, headerPanel);
this.headerPanel = headerPanel;
var footerPanel = GetPart("PART_FooterPanel");
MigrateChildren(this.footerPanel, footerPanel);
this.footerPanel = footerPanel;
var leftPanel = GetPart("PART_LeftPanel");
MigrateChildren(this.leftPanel, leftPanel);
this.leftPanel = leftPanel;
var bottomPanel = GetPart("PART_BottomPanel");
MigrateChildren(this.bottomPanel, bottomPanel);
this.bottomPanel = bottomPanel;
var rightPanel = GetPart("PART_RightPanel");
MigrateChildren(this.rightPanel, rightPanel);
this.rightPanel = rightPanel;
var topPanel = GetPart("PART_TopPanel");
MigrateChildren(this.topPanel, topPanel);
this.topPanel = topPanel;
var mainCanvas = GetPart