using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using GeoAPI.Geometries;
using GisSharpBlog.NetTopologySuite.Geometries;
using Point = System.Drawing.Point;
namespace SharpMap.UI.Tools.Zooming
{
///
/// Zooms in / out on mouse wheel.
/// Pans on mouse wheel
///
public class PanZoomUsingMouseWheelTool : ZoomTool
{
private double wheelZoomMagnitude = 2;
public PanZoomUsingMouseWheelTool()
{
Name = "ZoomInOutUsingWheel";
}
public override bool AlwaysActive
{
get
{
return true;
}
}
public override bool IsBusy
{
get
{
return Dragging;
}
}
[Description("The amount which a single movement of the mouse wheel zooms by.")]
[DefaultValue(2)]
[Category("Behavior")]
public double WheelZoomMagnitude
{
get
{
return wheelZoomMagnitude;
}
set
{
wheelZoomMagnitude = value;
}
}
public override void OnMouseWheel(ICoordinate mouseWorldPosition, MouseEventArgs e)
{
if (Dragging)
{
return;
}
// zoom map
double scale = (-e.Delta/250.0);
double usedWheelZoomMagnutide = wheelZoomMagnitude;
// fine zoom if alt is pressed
if (IsAltPressed)
{
usedWheelZoomMagnutide = wheelZoomMagnitude/8;
}
double scaleBase = 1 + usedWheelZoomMagnutide;
double zoomFactor = scale > 0 ? scaleBase : 1/scaleBase;
Map.Zoom *= zoomFactor;
Rectangle zoomRectangle;
if (!IsShiftPressed)
{
//determine center coordinate in world units
double newCenterX = mouseWorldPosition.X - Map.PixelWidth*(e.X - MapControl.Width/2.0);
double newCenterY = mouseWorldPosition.Y - Map.PixelHeight*(MapControl.Height/2.0 - e.Y);
// use current map center if shift is pressed
Map.Center = new Coordinate(newCenterX, newCenterY);
// draw zoom rectangle (in screen coordinates)
zoomRectangle = new Rectangle(
(int) (e.X*(1 - zoomFactor)),
(int) (e.Y*(1 - zoomFactor)),
(int) (MapControl.Size.Width*zoomFactor),
(int) (MapControl.Size.Height*zoomFactor));
}
else
{
// draw zoom rectangle (in screen coordinates)
zoomRectangle = new Rectangle(
(int) (MapControl.Width/2.0*(1 - zoomFactor)),
(int) (MapControl.Height/2.0*(1 - zoomFactor)),
(int) (MapControl.Size.Width*zoomFactor),
(int) (MapControl.Size.Height*zoomFactor));
}
// draw image and clear background in a separate image first to prevent flickering
/*
using (var previewImage = (Bitmap) Map.Image.Clone())
{
using (var g = Graphics.FromImage(previewImage))
{
g.Clear(MapControl.BackColor);
g.DrawImage(Map.Image, MapControl.ClientRectangle, zoomRectangle, GraphicsUnit.Pixel);
DrawStaticTools(g); // make tools to draw themself while map is being rendered
}
// now draw preview image on control
using (var g = MapControl.CreateGraphics())
{
g.DrawImage(previewImage, 0, 0);
}
}
*/
// call full map rendering (long operation)
MapControl.Refresh();
}
///
/// pan using mousewheel down
///
///
///
public override void OnMouseDown(ICoordinate worldPosition, MouseEventArgs e)
{
if (e.Button == MouseButtons.Middle && !Dragging)
{
StartDrag(e.Location);
}
}
public override void OnMouseUp(ICoordinate worldPosition, MouseEventArgs e)
{
if (e.Button == MouseButtons.Middle && Dragging)
{
StopDrag();
}
}
public override void OnKeyUp(KeyEventArgs e)
{
if (Dragging && (!e.Control ^ !e.Alt)) //either of the keys got depressed
{
StopDrag();
}
}
public override void OnMouseMove(ICoordinate worldPosition, MouseEventArgs e)
{
if (!Dragging)
{
if (IsCtrlAndAltPressed)
{
StartDrag(e.Location);
}
return;
}
// in case key events get lost: stop dragging if no longer mouse / keyboard down
if (!IsCtrlAndAltPressed && e.Button != MouseButtons.Middle)
{
StopDrag();
return;
}
MapControl.Cursor = Cursors.Hand;
DragEndPoint = e.Location;
var point = new Point((DragEndPoint.X - DragStartPoint.X),
(DragEndPoint.Y - DragStartPoint.Y));
using (var previewImage = new Bitmap(DragImage.Width, DragImage.Height))
{
using (var g = Graphics.FromImage(previewImage))
{
g.Clear(MapControl.BackColor);
g.DrawImageUnscaled(DragImage, point);
g.DrawImageUnscaled(StaticToolsImage, 0, 0);
}
using (var g = MapControl.CreateGraphics())
{
g.DrawImage(previewImage, 0, 0);
}
}
}
private Bitmap DragImage { get; set; }
private Bitmap StaticToolsImage { get; set; }
private bool Dragging { get; set; }
private Point DragStartPoint { get; set; }
private Point DragEndPoint { get; set; }
private bool IsCtrlAndAltPressed
{
get
{
return IsCtrlPressed && IsAltPressed;
}
}
private void StartDrag(Point mouseStartLocation)
{
MapControl.Cursor = Cursors.Hand;
Dragging = true;
DragImage = (Bitmap) Map.Image.Clone();
StaticToolsImage = new Bitmap(Map.Image.Width, Map.Image.Height);
using (var g = Graphics.FromImage(StaticToolsImage))
{
DrawStaticTools(g);
}
DragStartPoint = mouseStartLocation;
DragEndPoint = mouseStartLocation;
}
private void DrawStaticTools(Graphics g)
{
foreach (var tool in MapControl.Tools)
{
if (tool.IsActive && tool.RendersInScreenCoordinates)
{
tool.OnPaint(new PaintEventArgs(g, MapControl.ClientRectangle));
}
}
}
private void StopDrag()
{
DragImage.Dispose();
StaticToolsImage.Dispose();
Dragging = false;
var point = new Point((MapControl.ClientSize.Width/2 + (DragStartPoint.X - DragEndPoint.X)),
(MapControl.ClientSize.Height/2 + (DragStartPoint.Y - DragEndPoint.Y)));
Map.Center = Map.ImageToWorld(point);
MapControl.Cursor = Cursors.Default;
MapControl.Refresh();
}
}
}