455 lines
11 KiB
C#
455 lines
11 KiB
C#
using System.Windows;
|
|
using System.Windows.Input;
|
|
using System.Windows.Media;
|
|
using Microsoft.Win32;
|
|
using System;
|
|
using Microsoft.Research.DynamicDataDisplay.Common.UndoSystem;
|
|
using System.Collections.Generic;
|
|
using Microsoft.Research.DynamicDataDisplay.Charts.Navigation;
|
|
|
|
namespace Microsoft.Research.DynamicDataDisplay.Navigation
|
|
{
|
|
/// <summary>Provides keyboard navigation around viewport of ChartPlotter.</summary>
|
|
public class KeyboardNavigation : IPlotterElement
|
|
{
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="KeyboardNavigation"/> class.
|
|
/// </summary>
|
|
public KeyboardNavigation() { }
|
|
|
|
private bool isReversed = true;
|
|
/// <summary>
|
|
/// Gets or sets a value indicating whether panning directions are reversed.
|
|
/// </summary>
|
|
/// <value>
|
|
/// <c>true</c> if panning directions are reversed; otherwise, <c>false</c>.
|
|
/// </value>
|
|
public bool IsReversed
|
|
{
|
|
get { return isReversed; }
|
|
set { isReversed = value; }
|
|
}
|
|
|
|
private readonly List<CommandBinding> addedBindings = new List<CommandBinding>();
|
|
private void AddBinding(CommandBinding binding)
|
|
{
|
|
plotter2D.CommandBindings.Add(binding);
|
|
addedBindings.Add(binding);
|
|
}
|
|
|
|
private void InitCommands()
|
|
{
|
|
if (plotter2D == null)
|
|
return;
|
|
|
|
var zoomOutToMouseCommandBinding = new CommandBinding(
|
|
ChartCommands.ZoomOutToMouse,
|
|
ZoomOutToMouseExecute,
|
|
ZoomOutToMouseCanExecute);
|
|
AddBinding(zoomOutToMouseCommandBinding);
|
|
|
|
var zoomInToMouseCommandBinding = new CommandBinding(
|
|
ChartCommands.ZoomInToMouse,
|
|
ZoomInToMouseExecute,
|
|
ZoomInToMouseCanExecute);
|
|
AddBinding(zoomInToMouseCommandBinding);
|
|
|
|
var zoomWithParamCommandBinding = new CommandBinding(
|
|
ChartCommands.ZoomWithParameter,
|
|
ZoomWithParamExecute,
|
|
ZoomWithParamCanExecute);
|
|
AddBinding(zoomWithParamCommandBinding);
|
|
|
|
var zoomInCommandBinding = new CommandBinding(
|
|
ChartCommands.ZoomIn,
|
|
ZoomInExecute,
|
|
ZoomInCanExecute);
|
|
AddBinding(zoomInCommandBinding);
|
|
|
|
var zoomOutCommandBinding = new CommandBinding(
|
|
ChartCommands.ZoomOut,
|
|
ZoomOutExecute,
|
|
ZoomOutCanExecute);
|
|
AddBinding(zoomOutCommandBinding);
|
|
|
|
var fitToViewCommandBinding = new CommandBinding(
|
|
ChartCommands.FitToView,
|
|
FitToViewExecute,
|
|
FitToViewCanExecute);
|
|
AddBinding(fitToViewCommandBinding);
|
|
|
|
var ScrollLeftCommandBinding = new CommandBinding(
|
|
ChartCommands.ScrollLeft,
|
|
ScrollLeftExecute,
|
|
ScrollLeftCanExecute);
|
|
AddBinding(ScrollLeftCommandBinding);
|
|
|
|
var ScrollRightCommandBinding = new CommandBinding(
|
|
ChartCommands.ScrollRight,
|
|
ScrollRightExecute,
|
|
ScrollRightCanExecute);
|
|
AddBinding(ScrollRightCommandBinding);
|
|
|
|
var ScrollUpCommandBinding = new CommandBinding(
|
|
ChartCommands.ScrollUp,
|
|
ScrollUpExecute,
|
|
ScrollUpCanExecute);
|
|
AddBinding(ScrollUpCommandBinding);
|
|
|
|
var ScrollDownCommandBinding = new CommandBinding(
|
|
ChartCommands.ScrollDown,
|
|
ScrollDownExecute,
|
|
ScrollDownCanExecute);
|
|
AddBinding(ScrollDownCommandBinding);
|
|
|
|
var SaveScreenshotCommandBinding = new CommandBinding(
|
|
ChartCommands.SaveScreenshot,
|
|
SaveScreenshotExecute,
|
|
SaveScreenshotCanExecute);
|
|
AddBinding(SaveScreenshotCommandBinding);
|
|
|
|
var CopyScreenshotCommandBinding = new CommandBinding(
|
|
ChartCommands.CopyScreenshot,
|
|
CopyScreenshotExecute,
|
|
CopyScreenshotCanExecute);
|
|
AddBinding(CopyScreenshotCommandBinding);
|
|
|
|
var ShowHelpCommandBinding = new CommandBinding(
|
|
ChartCommands.ShowHelp,
|
|
ShowHelpExecute,
|
|
ShowHelpCanExecute);
|
|
AddBinding(ShowHelpCommandBinding);
|
|
|
|
var UndoCommandBinding = new CommandBinding(
|
|
ApplicationCommands.Undo,
|
|
UndoExecute,
|
|
UndoCanExecute);
|
|
AddBinding(UndoCommandBinding);
|
|
|
|
var RedoCommandBinding = new CommandBinding(
|
|
ApplicationCommands.Redo,
|
|
RedoExecute,
|
|
RedoCanExecute);
|
|
AddBinding(RedoCommandBinding);
|
|
}
|
|
|
|
#region Zoom Out To Mouse
|
|
|
|
private void ZoomToPoint(double coeff)
|
|
{
|
|
Point pt = Mouse.GetPosition(plotter2D.CentralGrid);
|
|
Point dataPoint = Viewport.Transform.ScreenToData(pt);
|
|
DataRect visible = Viewport.Visible;
|
|
|
|
Viewport.Visible = visible.Zoom(dataPoint, coeff);
|
|
}
|
|
|
|
private void ZoomOutToMouseExecute(object target, ExecutedRoutedEventArgs e)
|
|
{
|
|
ZoomToPoint(zoomOutCoeff);
|
|
e.Handled = true;
|
|
}
|
|
|
|
private void ZoomOutToMouseCanExecute(object target, CanExecuteRoutedEventArgs e)
|
|
{
|
|
e.CanExecute = true;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Zoom In To Mouse
|
|
|
|
private void ZoomInToMouseExecute(object target, ExecutedRoutedEventArgs e)
|
|
{
|
|
ZoomToPoint(zoomInCoeff);
|
|
e.Handled = true;
|
|
}
|
|
|
|
private void ZoomInToMouseCanExecute(object target, CanExecuteRoutedEventArgs e)
|
|
{
|
|
e.CanExecute = true;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Zoom With param
|
|
|
|
private void ZoomWithParamExecute(object target, ExecutedRoutedEventArgs e)
|
|
{
|
|
double zoomParam = (double)e.Parameter;
|
|
plotter2D.Viewport.Zoom(zoomParam);
|
|
e.Handled = true;
|
|
}
|
|
|
|
private void ZoomWithParamCanExecute(object target, CanExecuteRoutedEventArgs e)
|
|
{
|
|
e.CanExecute = true;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Zoom in
|
|
|
|
private const double zoomInCoeff = 0.9;
|
|
private void ZoomInExecute(object target, ExecutedRoutedEventArgs e)
|
|
{
|
|
Viewport.Zoom(zoomInCoeff);
|
|
e.Handled = true;
|
|
}
|
|
|
|
private void ZoomInCanExecute(object target, CanExecuteRoutedEventArgs e)
|
|
{
|
|
e.CanExecute = true;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Zoom out
|
|
|
|
private const double zoomOutCoeff = 1 / zoomInCoeff;
|
|
private void ZoomOutExecute(object target, ExecutedRoutedEventArgs e)
|
|
{
|
|
Viewport.Zoom(zoomOutCoeff);
|
|
e.Handled = true;
|
|
}
|
|
|
|
private void ZoomOutCanExecute(object target, CanExecuteRoutedEventArgs e)
|
|
{
|
|
e.CanExecute = true;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Fit to view
|
|
|
|
private void FitToViewExecute(object target, ExecutedRoutedEventArgs e)
|
|
{
|
|
// todo сделать нормально.
|
|
(Viewport as Viewport2D).FitToView();
|
|
e.Handled = true;
|
|
}
|
|
|
|
private void FitToViewCanExecute(object target, CanExecuteRoutedEventArgs e)
|
|
{
|
|
// todo add a check if viewport is already fitted to view.
|
|
e.CanExecute = true;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Scroll
|
|
|
|
private double scrollCoeff = 0.05;
|
|
private void ScrollVisibleProportionally(double xShiftCoeff, double yShiftCoeff)
|
|
{
|
|
DataRect visible = Viewport.Visible;
|
|
DataRect oldVisible = visible;
|
|
double width = visible.Width;
|
|
double height = visible.Height;
|
|
|
|
double reverseCoeff = isReversed ? -1 : 1;
|
|
visible.Offset(reverseCoeff * xShiftCoeff * width, reverseCoeff * yShiftCoeff * height);
|
|
|
|
Viewport.Visible = visible;
|
|
plotter2D.UndoProvider.AddAction(new DependencyPropertyChangedUndoAction(Viewport, Viewport2D.VisibleProperty, oldVisible, visible));
|
|
}
|
|
|
|
#region ScrollLeft
|
|
|
|
private void ScrollLeftExecute(object target, ExecutedRoutedEventArgs e)
|
|
{
|
|
ScrollVisibleProportionally(scrollCoeff, 0);
|
|
e.Handled = true;
|
|
}
|
|
|
|
private void ScrollLeftCanExecute(object target, CanExecuteRoutedEventArgs e)
|
|
{
|
|
e.CanExecute = true;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ScrollRight
|
|
|
|
private void ScrollRightExecute(object target, ExecutedRoutedEventArgs e)
|
|
{
|
|
ScrollVisibleProportionally(-scrollCoeff, 0);
|
|
e.Handled = true;
|
|
}
|
|
|
|
private void ScrollRightCanExecute(object target, CanExecuteRoutedEventArgs e)
|
|
{
|
|
e.CanExecute = true;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ScrollUp
|
|
|
|
private void ScrollUpExecute(object target, ExecutedRoutedEventArgs e)
|
|
{
|
|
ScrollVisibleProportionally(0, -scrollCoeff);
|
|
e.Handled = true;
|
|
}
|
|
|
|
private void ScrollUpCanExecute(object target, CanExecuteRoutedEventArgs e)
|
|
{
|
|
e.CanExecute = true;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ScrollDown
|
|
|
|
private void ScrollDownExecute(object target, ExecutedRoutedEventArgs e)
|
|
{
|
|
ScrollVisibleProportionally(0, scrollCoeff);
|
|
e.Handled = true;
|
|
}
|
|
|
|
private void ScrollDownCanExecute(object target, CanExecuteRoutedEventArgs e)
|
|
{
|
|
e.CanExecute = true;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region SaveScreenshot
|
|
|
|
private void SaveScreenshotExecute(object target, ExecutedRoutedEventArgs e)
|
|
{
|
|
SaveFileDialog dlg = new SaveFileDialog();
|
|
dlg.Filter = "PNG (*.png)|*.png|JPEG (*.jpg)|*.jpg|BMP (*.bmp)|*.bmp|GIF (*.gif)|*.gif";
|
|
dlg.FilterIndex = 1;
|
|
dlg.AddExtension = true;
|
|
if (dlg.ShowDialog().GetValueOrDefault(false))
|
|
{
|
|
string filePath = dlg.FileName;
|
|
plotter2D.SaveScreenshot(filePath);
|
|
e.Handled = true;
|
|
}
|
|
}
|
|
|
|
private void SaveScreenshotCanExecute(object target, CanExecuteRoutedEventArgs e)
|
|
{
|
|
e.CanExecute = true;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region CopyScreenshot
|
|
|
|
private void CopyScreenshotExecute(object target, ExecutedRoutedEventArgs e)
|
|
{
|
|
plotter2D.CopyScreenshotToClipboard();
|
|
e.Handled = true;
|
|
}
|
|
|
|
private void CopyScreenshotCanExecute(object target, CanExecuteRoutedEventArgs e)
|
|
{
|
|
e.CanExecute = true;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region ShowHelp
|
|
|
|
private bool aboutWindowOpened = false;
|
|
private void ShowHelpExecute(object target, ExecutedRoutedEventArgs e)
|
|
{
|
|
if (!aboutWindowOpened)
|
|
{
|
|
AboutWindow window = new AboutWindow();
|
|
window.Closed += new EventHandler(aboutWindow_Closed);
|
|
window.DataContext = plotter2D;
|
|
|
|
window.Owner = Window.GetWindow(plotter2D);
|
|
|
|
aboutWindowOpened = true;
|
|
window.Show();
|
|
|
|
e.Handled = true;
|
|
}
|
|
}
|
|
|
|
void aboutWindow_Closed(object sender, EventArgs e)
|
|
{
|
|
Window window = (Window)sender;
|
|
window.Closed -= aboutWindow_Closed;
|
|
aboutWindowOpened = false;
|
|
}
|
|
|
|
private void ShowHelpCanExecute(object target, CanExecuteRoutedEventArgs e)
|
|
{
|
|
e.CanExecute = !aboutWindowOpened;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Undo
|
|
|
|
private void UndoExecute(object target, ExecutedRoutedEventArgs e)
|
|
{
|
|
plotter2D.UndoProvider.Undo();
|
|
e.Handled = true;
|
|
}
|
|
|
|
private void UndoCanExecute(object target, CanExecuteRoutedEventArgs e)
|
|
{
|
|
e.CanExecute = plotter2D.UndoProvider.CanUndo;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Redo
|
|
|
|
private void RedoExecute(object target, ExecutedRoutedEventArgs e)
|
|
{
|
|
plotter2D.UndoProvider.Redo();
|
|
e.Handled = true;
|
|
}
|
|
|
|
private void RedoCanExecute(object target, CanExecuteRoutedEventArgs e)
|
|
{
|
|
e.CanExecute = plotter2D.UndoProvider.CanRedo;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region IPlotterElement Members
|
|
|
|
private Viewport2D Viewport
|
|
{
|
|
get { return plotter2D.Viewport; }
|
|
}
|
|
|
|
private Plotter2D plotter2D;
|
|
void IPlotterElement.OnPlotterAttached(Plotter plotter)
|
|
{
|
|
plotter2D = (Plotter2D)plotter;
|
|
|
|
InitCommands();
|
|
}
|
|
|
|
void IPlotterElement.OnPlotterDetaching(Plotter plotter)
|
|
{
|
|
foreach (var commandBinding in addedBindings)
|
|
{
|
|
plotter.CommandBindings.Remove(commandBinding);
|
|
}
|
|
addedBindings.Clear();
|
|
|
|
this.plotter2D = null;
|
|
}
|
|
|
|
Plotter IPlotterElement.Plotter
|
|
{
|
|
get { return plotter2D; }
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|