mirror of
https://github.com/wmjordan/PDFPatcher.git
synced 2026-10-18 21:52:34 +08:00
808 lines
23 KiB
C#
808 lines
23 KiB
C#
using System;
|
|
using System.ComponentModel;
|
|
using System.Drawing;
|
|
using System.Windows.Forms;
|
|
|
|
namespace Cyotek.Windows.Forms.Demo
|
|
{
|
|
// Cyotek ImageBox
|
|
// Copyright (c) 2010-2015 Cyotek Ltd.
|
|
// http://cyotek.com
|
|
// http://cyotek.com/blog/tag/imagebox
|
|
|
|
// Licensed under the MIT License. See license.txt for the full text.
|
|
|
|
// If you use this control in your applications, attribution, donations or contributions are welcome.
|
|
|
|
internal class ImageBoxEx : ImageBox
|
|
{
|
|
#region Constants
|
|
|
|
private readonly DragHandleCollection _dragHandles;
|
|
|
|
private static readonly object _eventDragHandleSizeChanged = new object();
|
|
|
|
private static readonly object _eventMaximumSelectionSizeChanged = new object();
|
|
|
|
private static readonly object _eventMinimumSelectionSizeChanged = new object();
|
|
|
|
private static readonly object _eventSelectionMoved = new object();
|
|
|
|
private static readonly object _eventSelectionMoving = new object();
|
|
|
|
private static readonly object _eventSelectionResized = new object();
|
|
|
|
private static readonly object _eventSelectionResizing = new object();
|
|
|
|
#endregion
|
|
|
|
#region Fields
|
|
|
|
private int _dragHandleSize;
|
|
|
|
private Point _dragOrigin;
|
|
|
|
private Point _dragOriginOffset;
|
|
|
|
private bool _isMoving;
|
|
|
|
private bool _isResizing;
|
|
|
|
private Size _maximumSelectionSize;
|
|
|
|
private Size _minimumSelectionSize;
|
|
|
|
private RectangleF _previousSelectionRegion;
|
|
|
|
private DragHandleAnchor _resizeAnchor;
|
|
|
|
#endregion
|
|
|
|
#region Constructors
|
|
|
|
public ImageBoxEx() {
|
|
_dragHandles = new DragHandleCollection();
|
|
_dragHandleSize = 8;
|
|
_maximumSelectionSize = Size.Empty;
|
|
PositionDragHandles();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Events
|
|
|
|
/// <summary>
|
|
/// Occurs when the DragHandleSize property value changes
|
|
/// </summary>
|
|
[Category("Property Changed")]
|
|
public event EventHandler DragHandleSizeChanged {
|
|
add { Events.AddHandler(_eventDragHandleSizeChanged, value); }
|
|
remove { Events.RemoveHandler(_eventDragHandleSizeChanged, value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Occurs when the MaximumSelectionSize property value changes
|
|
/// </summary>
|
|
[Category("Property Changed")]
|
|
public event EventHandler MaximumSelectionSizeChanged {
|
|
add { Events.AddHandler(_eventMaximumSelectionSizeChanged, value); }
|
|
remove { Events.RemoveHandler(_eventMaximumSelectionSizeChanged, value); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Occurs when the MinimumSelectionSize property value changes
|
|
/// </summary>
|
|
[Category("Property Changed")]
|
|
public event EventHandler MinimumSelectionSizeChanged {
|
|
add { Events.AddHandler(_eventMinimumSelectionSizeChanged, value); }
|
|
remove { Events.RemoveHandler(_eventMinimumSelectionSizeChanged, value); }
|
|
}
|
|
|
|
[Category("Action")]
|
|
public event EventHandler SelectionMoved {
|
|
add { Events.AddHandler(_eventSelectionMoved, value); }
|
|
remove { Events.RemoveHandler(_eventSelectionMoved, value); }
|
|
}
|
|
|
|
[Category("Action")]
|
|
public event CancelEventHandler SelectionMoving {
|
|
add { Events.AddHandler(_eventSelectionMoving, value); }
|
|
remove { Events.RemoveHandler(_eventSelectionMoving, value); }
|
|
}
|
|
|
|
[Category("Action")]
|
|
public event EventHandler SelectionResized {
|
|
add { Events.AddHandler(_eventSelectionResized, value); }
|
|
remove { Events.RemoveHandler(_eventSelectionResized, value); }
|
|
}
|
|
|
|
[Category("Action")]
|
|
public event CancelEventHandler SelectionResizing {
|
|
add { Events.AddHandler(_eventSelectionResizing, value); }
|
|
remove { Events.RemoveHandler(_eventSelectionResizing, value); }
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Properties
|
|
|
|
[Browsable(false)]
|
|
public DragHandleCollection DragHandles => _dragHandles;
|
|
|
|
[Category("Appearance")]
|
|
[DefaultValue(8)]
|
|
public virtual int DragHandleSize {
|
|
get => _dragHandleSize;
|
|
set {
|
|
if (_dragHandleSize != value) {
|
|
_dragHandleSize = value;
|
|
|
|
OnDragHandleSizeChanged(EventArgs.Empty);
|
|
}
|
|
}
|
|
}
|
|
|
|
[Browsable(false)]
|
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
public bool IsMoving {
|
|
get => _isMoving;
|
|
protected set => _isMoving = value;
|
|
}
|
|
|
|
[Browsable(false)]
|
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
public bool IsResizing {
|
|
get => _isResizing;
|
|
protected set => _isResizing = value;
|
|
}
|
|
|
|
[Category("Behavior")]
|
|
[DefaultValue(typeof(Size), "0, 0")]
|
|
public virtual Size MaximumSelectionSize {
|
|
get => _maximumSelectionSize;
|
|
set {
|
|
if (MaximumSelectionSize != value) {
|
|
_maximumSelectionSize = value;
|
|
|
|
OnMaximumSelectionSizeChanged(EventArgs.Empty);
|
|
}
|
|
}
|
|
}
|
|
|
|
[Category("Behavior")]
|
|
[DefaultValue(typeof(Size), "0, 0")]
|
|
public virtual Size MinimumSelectionSize {
|
|
get => _minimumSelectionSize;
|
|
set {
|
|
if (MinimumSelectionSize != value) {
|
|
_minimumSelectionSize = value;
|
|
|
|
OnMinimumSelectionSizeChanged(EventArgs.Empty);
|
|
}
|
|
}
|
|
}
|
|
|
|
[Browsable(false)]
|
|
public RectangleF PreviousSelectionRegion {
|
|
get => _previousSelectionRegion;
|
|
protected set => _previousSelectionRegion = value;
|
|
}
|
|
|
|
protected Point DragOrigin {
|
|
get => _dragOrigin;
|
|
set => _dragOrigin = value;
|
|
}
|
|
|
|
protected Point DragOriginOffset {
|
|
get => _dragOriginOffset;
|
|
set => _dragOriginOffset = value;
|
|
}
|
|
|
|
protected DragHandleAnchor ResizeAnchor {
|
|
get => _resizeAnchor;
|
|
set => _resizeAnchor = value;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Methods
|
|
|
|
public void CancelResize() {
|
|
SelectionRegion = _previousSelectionRegion;
|
|
CompleteResize();
|
|
}
|
|
|
|
public void StartMove() {
|
|
CancelEventArgs e;
|
|
|
|
if (_isMoving || _isResizing) {
|
|
throw new InvalidOperationException("A move or resize action is currently being performed.");
|
|
}
|
|
|
|
e = new CancelEventArgs();
|
|
|
|
OnSelectionMoving(e);
|
|
|
|
if (!e.Cancel) {
|
|
_previousSelectionRegion = SelectionRegion;
|
|
_isMoving = true;
|
|
}
|
|
}
|
|
|
|
protected virtual void DrawDragHandle(Graphics graphics, DragHandle handle) {
|
|
int left;
|
|
int top;
|
|
int width;
|
|
int height;
|
|
Pen outerPen;
|
|
Brush innerBrush;
|
|
|
|
left = handle.Bounds.Left;
|
|
top = handle.Bounds.Top;
|
|
width = handle.Bounds.Width;
|
|
height = handle.Bounds.Height;
|
|
|
|
if (handle.Enabled) {
|
|
outerPen = SystemPens.WindowFrame;
|
|
innerBrush = SystemBrushes.Window;
|
|
}
|
|
else {
|
|
outerPen = SystemPens.ControlDark;
|
|
innerBrush = SystemBrushes.Control;
|
|
}
|
|
|
|
graphics.FillRectangle(innerBrush, left + 1, top + 1, width - 2, height - 2);
|
|
graphics.DrawLine(outerPen, left + 1, top, left + width - 2, top);
|
|
graphics.DrawLine(outerPen, left, top + 1, left, top + height - 2);
|
|
graphics.DrawLine(outerPen, left + 1, top + height - 1, left + width - 2, top + height - 1);
|
|
graphics.DrawLine(outerPen, left + width - 1, top + 1, left + width - 1, top + height - 2);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Raises the <see cref="DragHandleSizeChanged" /> event.
|
|
/// </summary>
|
|
/// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
|
|
protected virtual void OnDragHandleSizeChanged(EventArgs e) {
|
|
EventHandler handler;
|
|
|
|
PositionDragHandles();
|
|
Invalidate();
|
|
|
|
handler = (EventHandler)Events[_eventDragHandleSizeChanged];
|
|
|
|
handler?.Invoke(this, e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Raises the <see cref="MaximumSelectionSizeChanged" /> event.
|
|
/// </summary>
|
|
/// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
|
|
protected virtual void OnMaximumSelectionSizeChanged(EventArgs e) {
|
|
EventHandler handler;
|
|
|
|
handler = (EventHandler)Events[_eventMaximumSelectionSizeChanged];
|
|
|
|
handler?.Invoke(this, e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Raises the <see cref="MinimumSelectionSizeChanged" /> event.
|
|
/// </summary>
|
|
/// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
|
|
protected virtual void OnMinimumSelectionSizeChanged(EventArgs e) {
|
|
EventHandler handler;
|
|
|
|
handler = (EventHandler)Events[_eventMinimumSelectionSizeChanged];
|
|
|
|
handler?.Invoke(this, e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Raises the <see cref="System.Windows.Forms.Control.MouseDown" /> event.
|
|
/// </summary>
|
|
/// <param name="e">
|
|
/// A <see cref="T:System.Windows.Forms.MouseEventArgs" /> that contains the event data.
|
|
/// </param>
|
|
protected override void OnMouseDown(MouseEventArgs e) {
|
|
Point imagePoint;
|
|
RectangleF selectionRegion;
|
|
|
|
imagePoint = PointToImage(e.Location);
|
|
selectionRegion = SelectionRegion;
|
|
|
|
if (e.Button == MouseButtons.Left && (selectionRegion.Contains(imagePoint) || HitTest(e.Location) != DragHandleAnchor.None)) {
|
|
_dragOrigin = e.Location;
|
|
_dragOriginOffset = new Point(imagePoint.X - (int)selectionRegion.X, imagePoint.Y - (int)selectionRegion.Y);
|
|
}
|
|
else {
|
|
_dragOriginOffset = Point.Empty;
|
|
_dragOrigin = Point.Empty;
|
|
}
|
|
|
|
base.OnMouseDown(e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Raises the <see cref="System.Windows.Forms.Control.MouseMove" /> event.
|
|
/// </summary>
|
|
/// <param name="e">
|
|
/// A <see cref="T:System.Windows.Forms.MouseEventArgs" /> that contains the event data.
|
|
/// </param>
|
|
protected override void OnMouseMove(MouseEventArgs e) {
|
|
// start either a move or a resize operation
|
|
if (!IsSelecting && !_isMoving && !_isResizing && e.Button == MouseButtons.Left && !_dragOrigin.IsEmpty && IsOutsideDragZone(e.Location)) {
|
|
DragHandleAnchor anchor;
|
|
|
|
anchor = HitTest(_dragOrigin);
|
|
|
|
if (anchor == DragHandleAnchor.None) {
|
|
// move
|
|
StartMove();
|
|
}
|
|
else if (_dragHandles[anchor].
|
|
Enabled && _dragHandles[anchor].
|
|
Visible) {
|
|
// resize
|
|
StartResize(anchor);
|
|
}
|
|
}
|
|
|
|
// set the cursor
|
|
SetCursor(e.Location);
|
|
|
|
// perform operations
|
|
ProcessSelectionMove(e.Location);
|
|
ProcessSelectionResize(e.Location);
|
|
|
|
base.OnMouseMove(e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Raises the <see cref="System.Windows.Forms.Control.MouseUp" /> event.
|
|
/// </summary>
|
|
/// <param name="e">
|
|
/// A <see cref="T:System.Windows.Forms.MouseEventArgs" /> that contains the event data.
|
|
/// </param>
|
|
protected override void OnMouseUp(MouseEventArgs e) {
|
|
if (_isMoving) {
|
|
CompleteMove();
|
|
}
|
|
else if (_isResizing) {
|
|
CompleteResize();
|
|
}
|
|
|
|
base.OnMouseUp(e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Raises the <see cref="System.Windows.Forms.Control.Paint" /> event.
|
|
/// </summary>
|
|
/// <param name="e">
|
|
/// A <see cref="T:System.Windows.Forms.PaintEventArgs" /> that contains the event data.
|
|
/// </param>
|
|
protected override void OnPaint(PaintEventArgs e) {
|
|
base.OnPaint(e);
|
|
|
|
if (AllowPainting && !SelectionRegion.IsEmpty) {
|
|
foreach (DragHandle handle in _dragHandles) {
|
|
if (handle.Visible) {
|
|
DrawDragHandle(e.Graphics, handle);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Raises the <see cref="ImageBox.PanStart" /> event.
|
|
/// </summary>
|
|
/// <param name="e">
|
|
/// The <see cref="System.ComponentModel.CancelEventArgs" /> instance containing the event data.
|
|
/// </param>
|
|
protected override void OnPanStart(CancelEventArgs e) {
|
|
if (_isMoving || _isResizing || !_dragOrigin.IsEmpty) {
|
|
e.Cancel = true;
|
|
}
|
|
|
|
base.OnPanStart(e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Raises the <see cref="System.Windows.Forms.Control.Resize" /> event.
|
|
/// </summary>
|
|
/// <param name="e">
|
|
/// An <see cref="T:System.EventArgs" /> that contains the event data.
|
|
/// </param>
|
|
protected override void OnResize(EventArgs e) {
|
|
base.OnResize(e);
|
|
|
|
PositionDragHandles();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Raises the <see cref="System.Windows.Forms.ScrollableControl.Scroll" /> event.
|
|
/// </summary>
|
|
/// <param name="se">
|
|
/// A <see cref="T:System.Windows.Forms.ScrollEventArgs" /> that contains the event data.
|
|
/// </param>
|
|
protected override void OnScroll(ScrollEventArgs se) {
|
|
base.OnScroll(se);
|
|
|
|
PositionDragHandles();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Raises the <see cref="ImageBox.Selecting" /> event.
|
|
/// </summary>
|
|
/// <param name="e">
|
|
/// The <see cref="System.EventArgs" /> instance containing the event data.
|
|
/// </param>
|
|
protected override void OnSelecting(ImageBoxCancelEventArgs e) {
|
|
e.Cancel = _isMoving || _isResizing || SelectionRegion.Contains(PointToImage(e.Location)) || HitTest(e.Location) != DragHandleAnchor.None;
|
|
|
|
base.OnSelecting(e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Raises the <see cref="SelectionMoved" /> event.
|
|
/// </summary>
|
|
/// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
|
|
protected virtual void OnSelectionMoved(EventArgs e) {
|
|
EventHandler handler;
|
|
|
|
handler = (EventHandler)Events[_eventSelectionMoved];
|
|
|
|
handler?.Invoke(this, e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Raises the <see cref="SelectionMoving" /> event.
|
|
/// </summary>
|
|
/// <param name="e">The <see cref="CancelEventArgs" /> instance containing the event data.</param>
|
|
protected virtual void OnSelectionMoving(CancelEventArgs e) {
|
|
CancelEventHandler handler;
|
|
|
|
handler = (CancelEventHandler)Events[_eventSelectionMoving];
|
|
|
|
handler?.Invoke(this, e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Raises the <see cref="ImageBox.SelectionRegionChanged" /> event.
|
|
/// </summary>
|
|
/// <param name="e">
|
|
/// The <see cref="System.EventArgs" /> instance containing the event data.
|
|
/// </param>
|
|
protected override void OnSelectionRegionChanged(EventArgs e) {
|
|
base.OnSelectionRegionChanged(e);
|
|
|
|
PositionDragHandles();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Raises the <see cref="SelectionResized" /> event.
|
|
/// </summary>
|
|
/// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
|
|
protected virtual void OnSelectionResized(EventArgs e) {
|
|
EventHandler handler;
|
|
|
|
handler = (EventHandler)Events[_eventSelectionResized];
|
|
|
|
handler?.Invoke(this, e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Raises the <see cref="SelectionResizing" /> event.
|
|
/// </summary>
|
|
/// <param name="e">The <see cref="CancelEventArgs" /> instance containing the event data.</param>
|
|
protected virtual void OnSelectionResizing(CancelEventArgs e) {
|
|
CancelEventHandler handler;
|
|
|
|
handler = (CancelEventHandler)Events[_eventSelectionResizing];
|
|
|
|
handler?.Invoke(this, e);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Raises the <see cref="ImageBox.ZoomChanged" /> event.
|
|
/// </summary>
|
|
/// <param name="e">
|
|
/// The <see cref="System.EventArgs" /> instance containing the event data.
|
|
/// </param>
|
|
protected override void OnZoomChanged(EventArgs e) {
|
|
base.OnZoomChanged(e);
|
|
|
|
PositionDragHandles();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Processes a dialog key.
|
|
/// </summary>
|
|
/// <returns>
|
|
/// true if the key was processed by the control; otherwise, false.
|
|
/// </returns>
|
|
/// <param name="keyData">One of the <see cref="T:System.Windows.Forms.Keys"/> values that represents the key to process. </param>
|
|
protected override bool ProcessDialogKey(Keys keyData) {
|
|
bool result;
|
|
|
|
if (keyData == Keys.Escape && (_isResizing || _isMoving)) {
|
|
if (_isResizing) {
|
|
CancelResize();
|
|
}
|
|
else {
|
|
CancelMove();
|
|
}
|
|
|
|
result = true;
|
|
}
|
|
else {
|
|
result = base.ProcessDialogKey(keyData);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
protected virtual void SetCursor(Point point) {
|
|
// http://forums.cyotek.com/imagebox/cursor-issue-in-imageboxex/msg92/#msg92
|
|
|
|
if (!IsPanning) {
|
|
Cursor cursor;
|
|
|
|
if (IsSelecting) {
|
|
cursor = Cursors.Default;
|
|
}
|
|
else {
|
|
DragHandleAnchor handleAnchor;
|
|
|
|
handleAnchor = _isResizing ? _resizeAnchor : HitTest(point);
|
|
if (handleAnchor != DragHandleAnchor.None && _dragHandles[handleAnchor].
|
|
Enabled) {
|
|
switch (handleAnchor) {
|
|
case DragHandleAnchor.TopLeft:
|
|
case DragHandleAnchor.BottomRight:
|
|
cursor = Cursors.SizeNWSE;
|
|
break;
|
|
case DragHandleAnchor.TopCenter:
|
|
case DragHandleAnchor.BottomCenter:
|
|
cursor = Cursors.SizeNS;
|
|
break;
|
|
case DragHandleAnchor.TopRight:
|
|
case DragHandleAnchor.BottomLeft:
|
|
cursor = Cursors.SizeNESW;
|
|
break;
|
|
case DragHandleAnchor.MiddleLeft:
|
|
case DragHandleAnchor.MiddleRight:
|
|
cursor = Cursors.SizeWE;
|
|
break;
|
|
default:
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
}
|
|
else if (_isMoving || SelectionRegion.Contains(PointToImage(point))) {
|
|
cursor = Cursors.SizeAll;
|
|
}
|
|
else {
|
|
cursor = Cursors.Default;
|
|
}
|
|
}
|
|
|
|
Cursor = cursor;
|
|
}
|
|
}
|
|
|
|
private void CancelMove() {
|
|
SelectionRegion = _previousSelectionRegion;
|
|
CompleteMove();
|
|
}
|
|
|
|
private void CompleteMove() {
|
|
ResetDrag();
|
|
OnSelectionMoved(EventArgs.Empty);
|
|
}
|
|
|
|
private void CompleteResize() {
|
|
ResetDrag();
|
|
OnSelectionResized(EventArgs.Empty);
|
|
}
|
|
|
|
private DragHandleAnchor HitTest(Point cursorPosition) {
|
|
return _dragHandles.HitTest(cursorPosition);
|
|
}
|
|
|
|
private bool IsOutsideDragZone(Point location) {
|
|
Rectangle dragZone;
|
|
int dragWidth;
|
|
int dragHeight;
|
|
|
|
dragWidth = SystemInformation.DragSize.Width;
|
|
dragHeight = SystemInformation.DragSize.Height;
|
|
dragZone = new Rectangle(_dragOrigin.X - (dragWidth / 2), _dragOrigin.Y - (dragHeight / 2), dragWidth, dragHeight);
|
|
|
|
return !dragZone.Contains(location);
|
|
}
|
|
|
|
private void PositionDragHandles() {
|
|
if (_dragHandles != null && _dragHandleSize > 0) {
|
|
RectangleF selectionRegion;
|
|
|
|
selectionRegion = SelectionRegion;
|
|
|
|
if (selectionRegion.IsEmpty) {
|
|
foreach (DragHandle handle in _dragHandles) {
|
|
handle.Bounds = Rectangle.Empty;
|
|
}
|
|
}
|
|
else {
|
|
int left;
|
|
int top;
|
|
int right;
|
|
int bottom;
|
|
int halfWidth;
|
|
int halfHeight;
|
|
int halfDragHandleSize;
|
|
Rectangle viewport;
|
|
int offsetX;
|
|
int offsetY;
|
|
|
|
viewport = GetImageViewPort();
|
|
offsetX = viewport.Left + Padding.Left + AutoScrollPosition.X;
|
|
offsetY = viewport.Top + Padding.Top + AutoScrollPosition.Y;
|
|
halfDragHandleSize = _dragHandleSize / 2;
|
|
left = Convert.ToInt32((selectionRegion.Left * ZoomFactor) + offsetX);
|
|
top = Convert.ToInt32((selectionRegion.Top * ZoomFactor) + offsetY);
|
|
right = left + Convert.ToInt32(selectionRegion.Width * ZoomFactor);
|
|
bottom = top + Convert.ToInt32(selectionRegion.Height * ZoomFactor);
|
|
halfWidth = Convert.ToInt32(selectionRegion.Width * ZoomFactor) / 2;
|
|
halfHeight = Convert.ToInt32(selectionRegion.Height * ZoomFactor) / 2;
|
|
|
|
_dragHandles[DragHandleAnchor.TopLeft].
|
|
Bounds = new Rectangle(left - _dragHandleSize, top - _dragHandleSize, _dragHandleSize, _dragHandleSize);
|
|
_dragHandles[DragHandleAnchor.TopCenter].
|
|
Bounds = new Rectangle(left + halfWidth - halfDragHandleSize, top - _dragHandleSize, _dragHandleSize, _dragHandleSize);
|
|
_dragHandles[DragHandleAnchor.TopRight].
|
|
Bounds = new Rectangle(right, top - _dragHandleSize, _dragHandleSize, _dragHandleSize);
|
|
_dragHandles[DragHandleAnchor.MiddleLeft].
|
|
Bounds = new Rectangle(left - _dragHandleSize, top + halfHeight - halfDragHandleSize, _dragHandleSize, _dragHandleSize);
|
|
_dragHandles[DragHandleAnchor.MiddleRight].
|
|
Bounds = new Rectangle(right, top + halfHeight - halfDragHandleSize, _dragHandleSize, _dragHandleSize);
|
|
_dragHandles[DragHandleAnchor.BottomLeft].
|
|
Bounds = new Rectangle(left - _dragHandleSize, bottom, _dragHandleSize, _dragHandleSize);
|
|
_dragHandles[DragHandleAnchor.BottomCenter].
|
|
Bounds = new Rectangle(left + halfWidth - halfDragHandleSize, bottom, _dragHandleSize, _dragHandleSize);
|
|
_dragHandles[DragHandleAnchor.BottomRight].
|
|
Bounds = new Rectangle(right, bottom, _dragHandleSize, _dragHandleSize);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void ProcessSelectionMove(Point cursorPosition) {
|
|
if (_isMoving) {
|
|
int x;
|
|
int y;
|
|
Point imagePoint;
|
|
Size viewSize;
|
|
RectangleF selectionRegion;
|
|
|
|
imagePoint = PointToImage(cursorPosition, false);
|
|
viewSize = ViewSize;
|
|
selectionRegion = SelectionRegion;
|
|
|
|
x = Math.Max(0, imagePoint.X - _dragOriginOffset.X);
|
|
if (x + selectionRegion.Width >= viewSize.Width) {
|
|
x = viewSize.Width - (int)selectionRegion.Width;
|
|
}
|
|
|
|
y = Math.Max(0, imagePoint.Y - _dragOriginOffset.Y);
|
|
if (y + selectionRegion.Height >= viewSize.Height) {
|
|
y = viewSize.Height - (int)selectionRegion.Height;
|
|
}
|
|
|
|
SelectionRegion = new RectangleF(x, y, selectionRegion.Width, selectionRegion.Height);
|
|
}
|
|
}
|
|
|
|
private void ProcessSelectionResize(Point cursorPosition) {
|
|
if (_isResizing) {
|
|
Point imagePosition;
|
|
float left;
|
|
float top;
|
|
float right;
|
|
float bottom;
|
|
bool resizingTopEdge;
|
|
bool resizingBottomEdge;
|
|
bool resizingLeftEdge;
|
|
bool resizingRightEdge;
|
|
RectangleF selectionRegion;
|
|
Size viewSize;
|
|
|
|
imagePosition = PointToImage(cursorPosition);
|
|
viewSize = ViewSize;
|
|
|
|
// get the current selection
|
|
selectionRegion = SelectionRegion;
|
|
left = selectionRegion.Left;
|
|
top = selectionRegion.Top;
|
|
right = selectionRegion.Right;
|
|
bottom = selectionRegion.Bottom;
|
|
|
|
// decide which edges we're resizing
|
|
resizingTopEdge = _resizeAnchor >= DragHandleAnchor.TopLeft && _resizeAnchor <= DragHandleAnchor.TopRight;
|
|
resizingBottomEdge = _resizeAnchor >= DragHandleAnchor.BottomLeft && _resizeAnchor <= DragHandleAnchor.BottomRight;
|
|
resizingLeftEdge = _resizeAnchor == DragHandleAnchor.TopLeft || _resizeAnchor == DragHandleAnchor.MiddleLeft || _resizeAnchor == DragHandleAnchor.BottomLeft;
|
|
resizingRightEdge = _resizeAnchor == DragHandleAnchor.TopRight || _resizeAnchor == DragHandleAnchor.MiddleRight || _resizeAnchor == DragHandleAnchor.BottomRight;
|
|
|
|
// and resize!
|
|
if (resizingTopEdge) {
|
|
top = imagePosition.Y > 0 ? imagePosition.Y : 0;
|
|
|
|
if (bottom - top < MinimumSelectionSize.Height) {
|
|
top = bottom - MinimumSelectionSize.Height;
|
|
}
|
|
else if (MaximumSelectionSize.Height > 0 && bottom - top > MaximumSelectionSize.Height) {
|
|
top = bottom - MaximumSelectionSize.Height;
|
|
}
|
|
}
|
|
else if (resizingBottomEdge) {
|
|
bottom = imagePosition.Y < viewSize.Height ? imagePosition.Y : viewSize.Height;
|
|
|
|
if (bottom - top < MinimumSelectionSize.Height) {
|
|
bottom = top + MinimumSelectionSize.Height;
|
|
}
|
|
else if (MaximumSelectionSize.Height > 0 && bottom - top > MaximumSelectionSize.Height) {
|
|
bottom = top + MaximumSelectionSize.Height;
|
|
}
|
|
}
|
|
|
|
if (resizingLeftEdge) {
|
|
left = imagePosition.X > 0 ? imagePosition.X : 0;
|
|
|
|
if (right - left < MinimumSelectionSize.Width) {
|
|
left = right - MinimumSelectionSize.Width;
|
|
}
|
|
else if (MaximumSelectionSize.Width > 0 && right - left > MaximumSelectionSize.Width) {
|
|
left = right - MaximumSelectionSize.Width;
|
|
}
|
|
}
|
|
else if (resizingRightEdge) {
|
|
right = imagePosition.X < viewSize.Width ? imagePosition.X : viewSize.Width;
|
|
|
|
if (right - left < MinimumSelectionSize.Width) {
|
|
right = left + MinimumSelectionSize.Width;
|
|
}
|
|
else if (MaximumSelectionSize.Width > 0 && right - left > MaximumSelectionSize.Width) {
|
|
right = left + MaximumSelectionSize.Width;
|
|
}
|
|
}
|
|
|
|
SelectionRegion = new RectangleF(left, top, right - left, bottom - top);
|
|
}
|
|
}
|
|
|
|
private void ResetDrag() {
|
|
_isResizing = false;
|
|
_isMoving = false;
|
|
_dragOrigin = Point.Empty;
|
|
_dragOriginOffset = Point.Empty;
|
|
}
|
|
|
|
private void StartResize(DragHandleAnchor anchor) {
|
|
CancelEventArgs e;
|
|
|
|
if (_isMoving || _isResizing) {
|
|
throw new InvalidOperationException("A move or resize action is currently being performed.");
|
|
}
|
|
|
|
e = new CancelEventArgs();
|
|
|
|
OnSelectionResizing(e);
|
|
|
|
if (!e.Cancel) {
|
|
_resizeAnchor = anchor;
|
|
_previousSelectionRegion = SelectionRegion;
|
|
_isResizing = true;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|