using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Diagnostics;
namespace Netron.Diagramming.Core {
// ----------------------------------------------------------------------
///
/// A tool that "pans" the diagram. The 'Origin' of the diagram is
/// adjusted when the left mouse button is held down and dragged
/// across the canvas.
///
// ----------------------------------------------------------------------
public class PanTool :
AbstractTool,
IMouseListener,
IKeyboardListener {
// ------------------------------------------------------------------
///
/// The number of times the mouse location has been updated. This is
/// used to determine if the cursor is updated. The cursor is only
/// updated every 5 times the mouse is moved and then this number is
/// reset to 0. The mouse is updated when this number is zero.
///
// ------------------------------------------------------------------
int mouseMoveNumber = 0;
// ------------------------------------------------------------------
///
/// Set to true when the left mouse buttone is down, set to false
/// all other times.
///
// ------------------------------------------------------------------
bool isLeftMouseButtonPressed = false;
// ------------------------------------------------------------------
///
/// The initial location of the mouse (when the mouse was clicked).
///
// ------------------------------------------------------------------
Point initialLocation = Point.Empty;
// ------------------------------------------------------------------
///
/// The last location of the mouse.
///
// ------------------------------------------------------------------
Point previousMouseLocation = Point.Empty;
// ------------------------------------------------------------------
///
/// Constructor.
///
/// string: The name of this tool.
// ------------------------------------------------------------------
public PanTool(string toolName)
: base(toolName) {
}
// ------------------------------------------------------------------
///
/// Activates the tool and sets the cursor to a hand cursor to provide
/// visual feedback that panning is activated.
///
// ------------------------------------------------------------------
protected override void OnActivateTool() {
base.OnActivateTool();
Cursor = CursorPalette.Pan;
}
// ------------------------------------------------------------------
///
/// Compares the location specified to the previous location and
/// sets the cursor as follows:
/// * current x < previous x and curreny y = previous y => pan W
/// * current x > previous x and curreny y = previous y => pan E
/// * current x = previous x and curreny y < previous y => pan N
/// * current x = previous x and curreny y > previous y => pan S
/// * current x < previous x and curreny y < previous y => pan NW
/// * current x > previous x and curreny y < previous y => pan NE
/// * current x < previous x and curreny y > previous y => pan SW
/// * current x > previous x and curreny y > previous y => pan SE
///
/// Point: The current cursor location.
// ------------------------------------------------------------------
protected void UpdateCursor(Point location) {
if ((location.X < previousMouseLocation.X) &&
(location.Y == previousMouseLocation.Y)) {
Cursor = Cursors.PanWest;
} else if ((location.X > previousMouseLocation.X) &&
(location.Y == previousMouseLocation.Y)) {
Cursor = Cursors.PanEast;
} else if ((location.X == previousMouseLocation.X) &&
(location.Y < previousMouseLocation.Y)) {
Cursor = Cursors.PanNorth;
} else if ((location.X == previousMouseLocation.X) &&
(location.Y > previousMouseLocation.Y)) {
Cursor = Cursors.PanSouth;
} else if ((location.X < previousMouseLocation.X) &&
(location.Y < previousMouseLocation.Y)) {
Cursor = Cursors.PanNW;
} else if ((location.X > previousMouseLocation.X) &&
(location.Y < previousMouseLocation.Y)) {
Cursor = Cursors.PanNE;
} else if ((location.X < previousMouseLocation.X) &&
(location.Y > previousMouseLocation.Y)) {
Cursor = Cursors.PanSW;
} else if ((location.X > previousMouseLocation.X) &&
(location.Y > previousMouseLocation.Y)) {
Cursor = Cursors.PanSE;
}
}
#region IMouseListener Members
// ------------------------------------------------------------------
///
/// Starts the panning action if this tool is activated and is not
/// suspended.
///
/// MouseEventArgs
// ------------------------------------------------------------------
public bool MouseDown(MouseEventArgs e) {
if ((!IsActive) ||
(IsSuspended == true)) {
this.isLeftMouseButtonPressed = false;
this.previousMouseLocation = Point.Empty;
return false;
}
if (e.Button == MouseButtons.Left) {
this.isLeftMouseButtonPressed = true;
this.previousMouseLocation =
Point.Round(Controller.View.WorldToView(e.Location));
this.initialLocation = previousMouseLocation;
return true;
} else {
this.isLeftMouseButtonPressed = false;
this.previousMouseLocation = Point.Empty;
return false;
}
}
// ------------------------------------------------------------------
///
/// Pans the diagram by the offset amount of the last mouse position
/// and the new mouse position divided by 2 (to slow things down a
/// bit; otherwise the "distance" panned is too much).
///
/// MouseEventArgs
// ------------------------------------------------------------------
public void MouseMove(MouseEventArgs e) {
Point currentLocation =
Point.Round(Controller.View.WorldToView(e.Location));
if ((!IsSuspended) &&
(IsActive) &&
(this.isLeftMouseButtonPressed)) {
// Change the cursor to indicated which direction we're
// panning.
if (mouseMoveNumber == 0) {
UpdateCursor(currentLocation);
}
mouseMoveNumber++;
if (mouseMoveNumber > 5) {
mouseMoveNumber = 0;
}
IDiagramControl control = Controller.ParentControl;
Point origin = Controller.View.Origin;
Point offset = new Point(
(previousMouseLocation.X - currentLocation.X),
(previousMouseLocation.Y - currentLocation.Y));
origin.Offset(offset);
// 0,0 is the min scrolling point.
if (origin.X < 0) {
origin.X = 0;
}
if (origin.Y < 0) {
origin.Y = 0;
}
control.AutoScrollPosition = origin;
Controller.View.Origin = origin;
previousMouseLocation = currentLocation;
}
}
// ------------------------------------------------------------------
///
/// Stops the panning action (does not deactivate the tool).
///
/// MouseEventArgs
// ------------------------------------------------------------------
public void MouseUp(MouseEventArgs e) {
if ((IsActive) && (!IsSuspended)) {
this.isLeftMouseButtonPressed = false;
this.previousMouseLocation = Point.Empty;
Cursor = CursorPalette.Pan;
}
}
#endregion
#region IKeyboardListener Members
// ------------------------------------------------------------------
///
/// Implementation of IKeyboardListener - deactivates this tool when
/// the 'escape' key is pressed.
///
/// KeyEventArgs
// ------------------------------------------------------------------
public void KeyDown(KeyEventArgs e) {
if (e.KeyCode == Keys.Escape)
DeactivateTool();
else if (e.KeyCode == Keys.Space)
ActivateTool();
}
// ------------------------------------------------------------------
///
/// Implementation of IKeyboardListener - nothing performed here.
///
/// KeyEventArgs
// ------------------------------------------------------------------
public void KeyUp(KeyEventArgs e) {
if (e.KeyCode == Keys.Space)
DeactivateTool();
}
// ------------------------------------------------------------------
///
/// Implementation of IKeyboardListener - nothing performed here.
///
/// KeyPressEventArgs
// ------------------------------------------------------------------
public void KeyPress(KeyPressEventArgs e) {
}
#endregion
}
}