Initial Commit
This commit is contained in:
405
Charts/Navigation/AxisNavigation.cs
Normal file
405
Charts/Navigation/AxisNavigation.cs
Normal file
@@ -0,0 +1,405 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using Microsoft.Research.DynamicDataDisplay.Charts.Axes;
|
||||
using Microsoft.Research.DynamicDataDisplay.Common.Auxiliary;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Microsoft.Research.DynamicDataDisplay.Charts.Navigation
|
||||
{
|
||||
public class AxisNavigation : DependencyObject, IPlotterElement
|
||||
{
|
||||
public AxisPlacement Placement
|
||||
{
|
||||
get { return (AxisPlacement)GetValue(PlacementProperty); }
|
||||
set { SetValue(PlacementProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty PlacementProperty = DependencyProperty.Register(
|
||||
"Placement",
|
||||
typeof(AxisPlacement),
|
||||
typeof(AxisNavigation),
|
||||
new FrameworkPropertyMetadata(AxisPlacement.Left, OnPlacementChanged));
|
||||
|
||||
private static void OnPlacementChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
AxisNavigation navigation = (AxisNavigation)d;
|
||||
navigation.OnPlacementChanged();
|
||||
}
|
||||
|
||||
private Panel listeningPanel;
|
||||
protected Panel ListeningPanel
|
||||
{
|
||||
get { return listeningPanel; }
|
||||
}
|
||||
|
||||
private void OnPlacementChanged()
|
||||
{
|
||||
SetListeningPanel();
|
||||
}
|
||||
|
||||
private void SetListeningPanel()
|
||||
{
|
||||
if (plotter == null) return;
|
||||
|
||||
AxisPlacement placement = Placement;
|
||||
switch (placement)
|
||||
{
|
||||
case AxisPlacement.Left:
|
||||
listeningPanel = plotter.LeftPanel;
|
||||
break;
|
||||
case AxisPlacement.Right:
|
||||
listeningPanel = plotter.RightPanel;
|
||||
break;
|
||||
case AxisPlacement.Top:
|
||||
listeningPanel = plotter.TopPanel;
|
||||
break;
|
||||
case AxisPlacement.Bottom:
|
||||
listeningPanel = plotter.BottomPanel;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private CoordinateTransform Transform
|
||||
{
|
||||
get { return plotter.Viewport.Transform; }
|
||||
}
|
||||
|
||||
private Panel hostPanel;
|
||||
|
||||
#region IPlotterElement Members
|
||||
|
||||
void IPlotterElement.OnPlotterAttached(Plotter plotter)
|
||||
{
|
||||
this.plotter = (Plotter2D)plotter;
|
||||
|
||||
hostPanel = plotter.MainGrid;
|
||||
|
||||
//hostPanel.Background = Brushes.Pink;
|
||||
|
||||
SetListeningPanel();
|
||||
|
||||
if (hostPanel != null)
|
||||
{
|
||||
hostPanel.MouseLeftButtonUp += OnMouseLeftButtonUp;
|
||||
hostPanel.MouseLeftButtonDown += OnMouseLeftButtonDown;
|
||||
hostPanel.MouseMove += OnMouseMove;
|
||||
hostPanel.MouseWheel += OnMouseWheel;
|
||||
|
||||
hostPanel.MouseRightButtonDown += OnMouseRightButtonDown;
|
||||
hostPanel.MouseRightButtonUp += OnMouseRightButtonUp;
|
||||
hostPanel.LostFocus += OnLostFocus;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLostFocus(object sender, RoutedEventArgs e)
|
||||
{
|
||||
//Debug.WriteLine("Lost Focus");
|
||||
RevertChanges();
|
||||
rmbPressed = false;
|
||||
lmbPressed = false;
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
#region Right button down
|
||||
|
||||
DataRect rmbDragStartRect;
|
||||
private void OnMouseRightButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
OnMouseRightButtonDown(e);
|
||||
}
|
||||
|
||||
protected virtual void OnMouseRightButtonDown(MouseButtonEventArgs e)
|
||||
{
|
||||
rmbInitialPosition = e.GetPosition(listeningPanel);
|
||||
|
||||
var foundActivePlotter = UpdateActivePlotter(e);
|
||||
if (foundActivePlotter)
|
||||
{
|
||||
rmbPressed = true;
|
||||
dragStartInViewport = rmbInitialPosition.ScreenToViewport(activePlotter.Transform);
|
||||
rmbDragStartRect = activePlotter.Visible;
|
||||
|
||||
listeningPanel.Background = fillBrush;
|
||||
listeningPanel.CaptureMouse();
|
||||
|
||||
//e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Right button up
|
||||
|
||||
private void OnMouseRightButtonUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
OnMouseRightButtonUp(e);
|
||||
}
|
||||
|
||||
protected virtual void OnMouseRightButtonUp(MouseButtonEventArgs e)
|
||||
{
|
||||
if (rmbPressed)
|
||||
{
|
||||
rmbPressed = false;
|
||||
RevertChanges();
|
||||
|
||||
//e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private void RevertChanges()
|
||||
{
|
||||
listeningPanel.ClearValue(Panel.CursorProperty);
|
||||
listeningPanel.Background = Brushes.Transparent;
|
||||
listeningPanel.ReleaseMouseCapture();
|
||||
}
|
||||
|
||||
private const double wheelZoomSpeed = 1.2;
|
||||
private void OnMouseWheel(object sender, MouseWheelEventArgs e)
|
||||
{
|
||||
Point mousePos = e.GetPosition(listeningPanel);
|
||||
|
||||
Rect listeningPanelBounds = new Rect(listeningPanel.RenderSize);
|
||||
if (!listeningPanelBounds.Contains(mousePos))
|
||||
return;
|
||||
|
||||
var foundActivePlotter = UpdateActivePlotter(e);
|
||||
if (!foundActivePlotter) return;
|
||||
|
||||
int delta = -e.Delta;
|
||||
|
||||
Point zoomTo = mousePos.ScreenToViewport(activePlotter.Transform);
|
||||
|
||||
double zoomSpeed = Math.Abs(delta / Mouse.MouseWheelDeltaForOneLine);
|
||||
zoomSpeed *= wheelZoomSpeed;
|
||||
if (delta < 0)
|
||||
{
|
||||
zoomSpeed = 1 / zoomSpeed;
|
||||
}
|
||||
|
||||
DataRect visible = activePlotter.Viewport.Visible.Zoom(zoomTo, zoomSpeed);
|
||||
DataRect oldVisible = activePlotter.Viewport.Visible;
|
||||
if (Placement.IsBottomOrTop())
|
||||
{
|
||||
visible.YMin = oldVisible.YMin;
|
||||
visible.Height = oldVisible.Height;
|
||||
}
|
||||
else
|
||||
{
|
||||
visible.XMin = oldVisible.XMin;
|
||||
visible.Width = oldVisible.Width;
|
||||
}
|
||||
activePlotter.Viewport.Visible = visible;
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private const int RmbZoomScale = 200;
|
||||
private void OnMouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (lmbPressed)
|
||||
{
|
||||
// panning:
|
||||
if (e.LeftButton == MouseButtonState.Released)
|
||||
{
|
||||
lmbPressed = false;
|
||||
RevertChanges();
|
||||
return;
|
||||
}
|
||||
|
||||
Point screenMousePos = e.GetPosition(listeningPanel);
|
||||
Point dataMousePos = screenMousePos.ScreenToViewport(activePlotter.Transform);
|
||||
DataRect visible = activePlotter.Viewport.Visible;
|
||||
double delta;
|
||||
if (Placement.IsBottomOrTop())
|
||||
{
|
||||
delta = (dataMousePos - dragStartInViewport).X;
|
||||
visible.XMin -= delta;
|
||||
}
|
||||
else
|
||||
{
|
||||
delta = (dataMousePos - dragStartInViewport).Y;
|
||||
visible.YMin -= delta;
|
||||
}
|
||||
|
||||
if (screenMousePos != lmbInitialPosition)
|
||||
{
|
||||
listeningPanel.Cursor = Placement.IsBottomOrTop() ? Cursors.ScrollWE : Cursors.ScrollNS;
|
||||
}
|
||||
|
||||
activePlotter.Viewport.Visible = visible;
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (rmbPressed)
|
||||
{
|
||||
// one direction zooming:
|
||||
if (e.RightButton == MouseButtonState.Released)
|
||||
{
|
||||
rmbPressed = false;
|
||||
RevertChanges();
|
||||
return;
|
||||
}
|
||||
|
||||
Point screenMousePos = e.GetPosition(listeningPanel);
|
||||
DataRect visible = activePlotter.Viewport.Visible;
|
||||
double delta;
|
||||
|
||||
bool isHorizontal = Placement.IsBottomOrTop();
|
||||
if (isHorizontal)
|
||||
{
|
||||
delta = (screenMousePos - rmbInitialPosition).X;
|
||||
}
|
||||
else
|
||||
{
|
||||
delta = (screenMousePos - rmbInitialPosition).Y;
|
||||
}
|
||||
|
||||
if (delta < 0)
|
||||
delta = 1 / Math.Exp(-delta / RmbZoomScale);
|
||||
else
|
||||
delta = Math.Exp(delta / RmbZoomScale);
|
||||
|
||||
Point center = dragStartInViewport;
|
||||
|
||||
if (isHorizontal)
|
||||
{
|
||||
visible = rmbDragStartRect.ZoomX(center, delta);
|
||||
}
|
||||
else
|
||||
{
|
||||
visible = rmbDragStartRect.ZoomY(center, delta);
|
||||
}
|
||||
|
||||
if (screenMousePos != lmbInitialPosition)
|
||||
{
|
||||
listeningPanel.Cursor = Placement.IsBottomOrTop() ? Cursors.ScrollWE : Cursors.ScrollNS;
|
||||
}
|
||||
|
||||
|
||||
activePlotter.Viewport.Visible = visible;
|
||||
|
||||
//e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private Point lmbInitialPosition;
|
||||
protected Point LmbInitialPosition
|
||||
{
|
||||
get { return lmbInitialPosition; }
|
||||
}
|
||||
|
||||
private Point rmbInitialPosition;
|
||||
private readonly SolidColorBrush fillBrush = new SolidColorBrush(Color.FromRgb(255, 228, 209)).MakeTransparent(0.2);
|
||||
private bool lmbPressed;
|
||||
private bool rmbPressed;
|
||||
private Point dragStartInViewport;
|
||||
private Plotter2D activePlotter;
|
||||
|
||||
#region Left button down
|
||||
|
||||
private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
OnMouseLeftButtonDown(e);
|
||||
}
|
||||
|
||||
protected virtual void OnMouseLeftButtonDown(MouseButtonEventArgs e)
|
||||
{
|
||||
lmbInitialPosition = e.GetPosition(listeningPanel);
|
||||
|
||||
var foundActivePlotter = UpdateActivePlotter(e);
|
||||
if (foundActivePlotter)
|
||||
{
|
||||
lmbPressed = true;
|
||||
dragStartInViewport = lmbInitialPosition.ScreenToViewport(activePlotter.Transform);
|
||||
|
||||
listeningPanel.Background = fillBrush;
|
||||
listeningPanel.CaptureMouse();
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private bool UpdateActivePlotter(MouseEventArgs e)
|
||||
{
|
||||
var axes = listeningPanel.Children.OfType<GeneralAxis>();
|
||||
|
||||
foreach (var axis in axes)
|
||||
{
|
||||
var positionInAxis = e.GetPosition(axis);
|
||||
Rect axisBounds = new Rect(axis.RenderSize);
|
||||
if (axisBounds.Contains(positionInAxis))
|
||||
{
|
||||
activePlotter = axis.Plotter;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#region Left button up
|
||||
|
||||
private void OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
OnMouseLeftButtonUp(e);
|
||||
}
|
||||
|
||||
protected virtual void OnMouseLeftButtonUp(MouseButtonEventArgs e)
|
||||
{
|
||||
if (lmbPressed)
|
||||
{
|
||||
lmbPressed = false;
|
||||
RevertChanges();
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public void OnPlotterDetaching(Plotter plotter)
|
||||
{
|
||||
if (plotter.MainGrid != null)
|
||||
{
|
||||
hostPanel.MouseLeftButtonUp -= OnMouseLeftButtonUp;
|
||||
hostPanel.MouseLeftButtonDown -= OnMouseLeftButtonDown;
|
||||
hostPanel.MouseMove -= OnMouseMove;
|
||||
hostPanel.MouseWheel -= OnMouseWheel;
|
||||
|
||||
hostPanel.MouseRightButtonDown -= OnMouseRightButtonDown;
|
||||
hostPanel.MouseRightButtonUp -= OnMouseRightButtonUp;
|
||||
|
||||
hostPanel.LostFocus -= OnLostFocus;
|
||||
}
|
||||
listeningPanel = null;
|
||||
this.plotter = null;
|
||||
}
|
||||
|
||||
private Plotter2D plotter;
|
||||
Plotter IPlotterElement.Plotter
|
||||
{
|
||||
get { return plotter; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return "AxisNavigation: " + Placement;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user