using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Controls.Primitives;
using System.Diagnostics;
using ZoomAndPan;
using System.Windows.Media.Animation;
using System.Windows.Threading;
namespace ZoomAndPanSample
{
/// <summary>
/// This is a Window that uses ZoomAndPanControl to zoom and pan around some content.
/// This demonstrates how to use application specific mouse handling logic with ZoomAndPanControl.
/// </summary>
public partial class MainWindow : Window
{
/// <summary>
/// Specifies the current state of the mouse handling logic.
/// </summary>
private MouseHandlingMode mouseHandlingMode = MouseHandlingMode.None;
/// <summary>
/// The point that was clicked relative to the ZoomAndPanControl.
/// </summary>
private Point origZoomAndPanControlMouseDownPoint;
/// <summary>
/// The point that was clicked relative to the content that is contained within the ZoomAndPanControl.
/// </summary>
private Point origContentMouseDownPoint;
/// <summary>
/// Records which mouse button clicked during mouse dragging.
/// </summary>
private MouseButton mouseButtonDown;
/// <summary>
/// Saves the previous zoom rectangle, pressing the backspace key jumps back to this zoom rectangle.
/// </summary>
private Rect prevZoomRect;
/// <summary>
/// Save the previous content scale, pressing the backspace key jumps back to this scale.
/// </summary>
private double prevZoomScale;
/// <summary>
/// Set to 'true' when the previous zoom rect is saved.
/// </summary>
private bool prevZoomRectSet = false;
public MainWindow()
{
InitializeComponent();
}
/// <summary>
/// Event raised when the Window has loaded.
/// </summary>
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
OverviewWindow overviewWindow = new OverviewWindow();
overviewWindow.Left = this.Left;
overviewWindow.Top = this.Top + this.Height + 5;
overviewWindow.Owner = this;
overviewWindow.Show();
HelpTextWindow helpTextWindow = new HelpTextWindow();
helpTextWindow.Left = this.Left + this.Width + 5;
helpTextWindow.Top = this.Top;
helpTextWindow.Owner = this;
helpTextWindow.Show();
}
/// <summary>
/// Event raised on mouse down in the ZoomAndPanControl.
/// </summary>
private void zoomAndPanControl_MouseDown(object sender, MouseButtonEventArgs e)
{
content.Focus();
Keyboard.Focus(content);
mouseButtonDown = e.ChangedButton;
origZoomAndPanControlMouseDownPoint = e.GetPosition(zoomAndPanControl);
origContentMouseDownPoint = e.GetPosition(content);
if ((Keyboard.Modifiers & ModifierKeys.Shift) != 0 &&
(e.ChangedButton == MouseButton.Left ||
e.ChangedButton == MouseButton.Right))
{
// Shift + left- or right-down initiates zooming mode.
mouseHandlingMode = MouseHandlingMode.Zooming;
}
else if (mouseButtonDown == MouseButton.Left)
{
// Just a plain old left-down initiates panning mode.
mouseHandlingMode = MouseHandlingMode.Panning;
}
if (mouseHandlingMode != MouseHandlingMode.None)
{
// Capture the mouse so that we eventually receive the mouse up event.
zoomAndPanControl.CaptureMouse();
e.Handled = true;
}
}
/// <summary>
/// Event raised on mouse up in the ZoomAndPanControl.
/// </summary>
private void zoomAndPanControl_MouseUp(object sender, MouseButtonEventArgs e)
{
if (mouseHandlingMode != MouseHandlingMode.None)
{
if (mouseHandlingMode == MouseHandlingMode.Zooming)
{
if (mouseButtonDown == MouseButton.Left)
{
// Shift + left-click zooms in on the content.
ZoomIn(origContentMouseDownPoint);
}
else if (mouseButtonDown == MouseButton.Right)
{
// Shift + left-click zooms out from the content.
ZoomOut(origContentMouseDownPoint);
}
}
else if (mouseHandlingMode == MouseHandlingMode.DragZooming)
{
// When drag-zooming has finished we zoom in on the rectangle that was highlighted by the user.
ApplyDragZoomRect();
}
zoomAndPanControl.ReleaseMouseCapture();
mouseHandlingMode = MouseHandlingMode.None;
e.Handled = true;
}
}
/// <summary>
/// Event raised on mouse move in the ZoomAndPanControl.
/// </summary>
private void zoomAndPanControl_MouseMove(object sender, MouseEventArgs e)
{
if (mouseHandlingMode == MouseHandlingMode.Panning)
{
//
// The user is left-dragging the mouse.
// Pan the viewport by the appropriate amount.
//
Point curContentMousePoint = e.GetPosition(content);
Vector dragOffset = curContentMousePoint - origContentMouseDownPoint;
zoomAndPanControl.ContentOffsetX -= dragOffset.X;
zoomAndPanControl.ContentOffsetY -= dragOffset.Y;
e.Handled = true;
}
else if (mouseHandlingMode == MouseHandlingMode.Zooming)
{
Point curZoomAndPanControlMousePoint = e.GetPosition(zoomAndPanControl);
Vector dragOffset = curZoomAndPanControlMousePoint - origZoomAndPanControlMouseDownPoint;
double dragThreshold = 10;
if (mouseButtonDown == MouseButton.Left &&
(Math.Abs(dragOffset.X) > dragThreshold ||
Math.Abs(dragOffset.Y) > dragThreshold))
{
//
// When Shift + left-down zooming mode and the user drags beyond the drag threshold,
// initiate drag zooming mode where the user can drag out a rectangle to select the area
// to zoom in on.
//
mouseHandlingMode = MouseHandlingMode.DragZooming;
Point curContentMousePoint = e.GetPosition(content);
InitDragZoomRect(origContentMouseDownPoint, curContentMousePoint);
}
e.Handled = true;
}
else if (mouseHandlingMode == MouseHandlingMode.DragZooming)
{
//
// When in drag zooming mode continously update the position of the rectangle
// that the user is dragging out.
//
Point curContentMousePoint = e.GetPosition(content);
SetDragZoomRect(origContentMouseDownPoint, curContentMousePoint);
e.Handled = true;
}
}
/// <summary>
/// Event raised by rotating the mouse wheel
/// </summary>
private void zoomAndPanControl_MouseWheel(object sender, MouseWheelEventArgs e)
{
e.Handled = true;
if (e.Delta > 0)
{
Point curContentMousePoint = e.GetPosition(content);
ZoomIn(curContentMousePoint);
}
else if (e.Delta < 0)
{
Point curContentMousePoint = e.GetPosition(content);
ZoomOut(curContentMousePoint);
}
}
/// <summary>
/// The 'ZoomIn' command (bound to the plus key) was executed.
/// </summary>
private void ZoomIn_Executed(object sender, ExecutedRoutedEventArgs e)
{
ZoomIn(new Point(zoomAndPanControl.ContentZoomFocusX, zoomAndPanControl.ContentZoomFocusY));
}
/// <summary>
/// The 'ZoomOut' command (bound to the minus key) was executed.
/// </summary>
private void ZoomOut_Executed(object sender, ExecutedRoutedEventArgs e)
{
ZoomOut(new Point(zoomAndPanControl.ContentZoomFocusX, zoomAndPanControl.ContentZoomFocusY));
}
/// <summary>
/// The 'JumpBackToPrevZoom' command was executed.
/// </summary>
private void JumpBackToPrevZoom_Executed(object sender, ExecutedRoutedEventArgs e)
{
JumpBackToPrevZoom();
}
/// <summary>
/// Determines whether the 'JumpBackToPrevZoom' command can be executed.
/// </summary>
private void JumpBackToPrevZoom_CanExecuted(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = prevZoomRectSet;
}
/// <summary>
/// The 'Fill' command was executed.
/// </summary>
private void Fill_Executed(object sender, ExecutedRoutedEventArgs e)
{
SavePrevZoomRect();
zoomAndPanControl.AnimatedScaleToFit();
}
/// <summary>
/// The 'OneHundredPercent' command was executed.
/// </summary>
private void OneHundredPercent_Executed(object sender, ExecutedRoutedEventArgs e)
{
SavePrevZoomRect();
zoomAndPanControl.AnimatedZoomTo(1.0);
}
/// <summary>
/// Jump back to the previous zoom level.
/// </summary>
private void JumpBackToPrevZoom()
{
zoomAndPanControl.AnimatedZoomTo(prevZoomScale, prevZoomRect);
ClearPrevZoomRect();
}
/// <summary>
/// Zoom the viewport out, centering on the specified point (in content coordinates).
/// </summary>
private void ZoomOut(Point contentZoomCenter)
{
zoomAndPanControl.ZoomAboutPoint(zoomAndPanControl.ContentScale - 0.1, contentZoomCenter);
}
/// <summary>
/// Zoom the viewport in, centering on the specified point (in content coordinates).
/// </summary>
private void ZoomIn(Point contentZoomCenter)
{
zoomAndPanControl.ZoomAboutPoint(zoomAndPanControl.ContentScale + 0.1, contentZoomCenter);
}
/// <summary>
/// Initialise the rectangle that the use is dragging out.
/// </summary>
private void InitDragZoomRect(Point pt1, Point pt2)
{
SetDragZoomRect(pt1, pt2);
dragZoomCanvas.Visibility = Visibility.Visible;
dragZoomBorder.Opacity = 0.5;
}
/// <summary>
/// Update the position and size of the rectangle that user is dragging out.
/// </summary>
private void SetDragZoomRect(Point pt1, Point pt2)
{
double x, y, width, height;
//
// Deterine x,y,width and height of the rect inverting the points if necessary.
//
if (pt2.X < pt1.X)
{
x = pt2.X;
width = pt1.X - pt2.X;
}
else
{
x = pt1.X;
width = pt2.X - pt1.X;
}
if (pt2.Y < pt1.Y)
{
y = pt2.Y;
height = pt1.Y - pt2.Y;
}
else
{
y = pt1.Y;
height = pt2.Y - pt1.Y;
}
//
// Update the coordinates of the rectangle that is being dragged out by the user.
// The we offset and rescale to convert from content coordinates.
//
Canvas.SetLeft(dragZoomBorder, x);
Canvas.SetTop(dragZoomBorder, y);
dragZoomBorder.Width = width;
dragZoomBorder.Height = height;
}
/// <summary>
/// When the user has finished dragging out the rectangle the zoom operation is applied.
/// </summary>
private void ApplyDragZoomRect()
{
//
// Record the previous zoom level, so that we can jump back to it when the backspace key is pressed.
//
SavePrevZoomRect();
//
// Retreive the rectangle that the user draggged out and zoom in on it.
//
double contentX = Canvas.GetLeft(dragZoomBorder);
double contentY = Canvas.GetTop(dragZoomBorder);
double contentWidth = dragZoomBorder.Width;
double contentHeight = dragZoomBorder.Height;
zoomAndPanControl.AnimatedZoomTo(new Rect(contentX, contentY, contentWidth, contentHeight));
FadeOutDragZoomRect();
}
//
// Fade out the drag zoom rectangle.
//
private void FadeOutDragZoomRect()
{
AnimationHelper.StartAnimation(dragZoomBorder, Border.OpacityProperty, 0.0, 0.1,
delegate(object sender, EventArgs e)
{
dragZoomCanvas.Visibility = Visibility.Collapsed;
});
}
//
// Record the previous zoom level, so that we can jump back to it when the backspace key is pressed.
//
private void SavePrevZoomRect()
{
prevZoomRect = new Rect(zoomAndPanControl.ContentOffsetX, zoomAndPanControl.ContentOffsetY, zoomAndPanControl.ContentViewportWidth, zoomAndPanControl.ContentViewportHeight);
prevZoomScale = zoomAndPanControl.ContentScale;
prevZoomRectSet = true;
}
/// <summary>
/// Clear the memory of the previous zoom level.
/// </summary>
private void ClearPrevZoomRect()
{
prevZoomRectSet = false;
}
/// <summary>
/// Event raised when the user has double clicked in the zoom and pan control.
/// </summary>
private void zoomAndPanControl_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
if ((Keyboard.Modifiers & ModifierKeys.Shift) == 0)
{
Point doubleClickPoint = e.GetPosition(content);
zoomAndPanControl.AnimatedSnapTo(doubleClickPoint);
}
}
/// <summary>
/// Event raised when a mouse button is clicked down over a Rectangle.
/// </summary>
private void Rectangle_MouseDown(object sender, MouseButtonEventArgs e)
{
content.Focus();
Keyboard.Focus(content);
Rectangle rectangle = (Rectangle)sender;
RectangleData myRectangle = (RectangleData)rectangle.DataContext;
myRectangle.IsSelected = true;
if ((Keyboard.Modifiers & ModifierKeys.Shift) != 0)
{
//
// When the shift key is held down special zooming logic is executed in content_MouseDown,
// so don't handle mouse input here.
//
return;
}
if (mouseHandlingMode != MouseHandlingMode.None)
{
//
// We are in some other mouse handling mode, don't do anything.
return;
}
mouseHandlingMode = MouseHandlingMode.DraggingRectangles;
origContentMouseDownPoint = e.GetPosition(content);
rectangle.CaptureMouse();
e.Handled = true;
}
/// <summary>
/// Event raised when a mouse button is released over a Rectangle.
/// </summary>
private void Rectangle_MouseUp(object sender, MouseButtonEventArgs e)
{
if (mouseHandlingMode != MouseHandlingMode.DraggingRectangles)
{
//
// We are not in rectangle dragging mode.
//
return;
}
mouseHandlingMode = MouseHandlingMode.None;
Rectangle rectangle = (Rectangle)sender;
rectangle.ReleaseMouseCapture();
e.Handled = true;
}
/// <summary>
/// Event raised when the mouse cursor is moved when over a Rectangle.
/// </summary>
private void Rectangle_MouseMove(object sender, MouseEventArgs e)
{
if (mouseHandlingMode != MouseHandlingMode.DraggingRectangles)
{
//
// We are not in rectangle dragging mode, so don't do anything.
//
return;
}
Point curContentPoint = e.GetPosition(content);
Vector rectangleDragVector = curContentPoint - origContentMouseDownPoint;
//
// When in 'dragging rectangles' mode update the position of the rectangle as the user drags it.
//
origContentMouseDownPoint = curContentPoint;
Rectangle rectangle = (Rectangle)sender;
RectangleData myRectangle = (RectangleData)rectangle.DataContext;
myRectangle.X += rectangleDragVector.X;
myRectangle.Y += rectangleDragVector.Y;
e.Handled = true;
}
}
}