482 lines
16 KiB
C#
482 lines
16 KiB
C#
|
//
|
||
|
// System.Windows.Forms.Design.SelectionFrame
|
||
|
//
|
||
|
// Authors:
|
||
|
// Ivan N. Zlatev (contact i-nZ.net)
|
||
|
//
|
||
|
// (C) 2006-2007 Ivan N. Zlatev
|
||
|
|
||
|
//
|
||
|
// Permission is hereby granted, free of charge, to any person obtaining
|
||
|
// a copy of this software and associated documentation files (the
|
||
|
// "Software"), to deal in the Software without restriction, including
|
||
|
// without limitation the rights to use, copy, modify, merge, publish,
|
||
|
// distribute, sublicense, and/or sell copies of the Software, and to
|
||
|
// permit persons to whom the Software is furnished to do so, subject to
|
||
|
// the following conditions:
|
||
|
//
|
||
|
// The above copyright notice and this permission notice shall be
|
||
|
// included in all copies or substantial portions of the Software.
|
||
|
//
|
||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||
|
//
|
||
|
|
||
|
using System;
|
||
|
using System.Collections;
|
||
|
using System.ComponentModel;
|
||
|
using System.ComponentModel.Design;
|
||
|
using System.Drawing;
|
||
|
using System.Drawing.Drawing2D;
|
||
|
using System.Windows.Forms;
|
||
|
|
||
|
|
||
|
namespace System.Windows.Forms.Design
|
||
|
{
|
||
|
// This is not a control!
|
||
|
//
|
||
|
internal class SelectionFrame
|
||
|
{
|
||
|
|
||
|
public SelectionFrame (Control control)
|
||
|
{
|
||
|
if (control == null)
|
||
|
throw new ArgumentNullException ("control");
|
||
|
|
||
|
_control = control;
|
||
|
}
|
||
|
|
||
|
|
||
|
private Rectangle _bounds;
|
||
|
private Control _control;
|
||
|
private Rectangle[] _handles = new Rectangle[8];
|
||
|
private GrabHandle _handle = GrabHandle.None;
|
||
|
private const int BORDER_SIZE = 7;
|
||
|
|
||
|
|
||
|
#region Properties
|
||
|
private enum GrabHandle {
|
||
|
None = -1,
|
||
|
TopLeft = 0,
|
||
|
TopMiddle,
|
||
|
TopRight,
|
||
|
Right,
|
||
|
BottomRight,
|
||
|
BottomMiddle,
|
||
|
BottomLeft,
|
||
|
Left,
|
||
|
Border // the border surrounding the control.
|
||
|
}
|
||
|
|
||
|
public Rectangle Bounds {
|
||
|
get {
|
||
|
_bounds.X = _control.Location.X - BORDER_SIZE;
|
||
|
_bounds.Y = _control.Location.Y - BORDER_SIZE;
|
||
|
_bounds.Width = _control.Width + BORDER_SIZE *2;
|
||
|
_bounds.Height = _control.Height + BORDER_SIZE *2;
|
||
|
|
||
|
return _bounds;
|
||
|
}
|
||
|
set {
|
||
|
_bounds = value;
|
||
|
_control.Bounds = _bounds;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private SelectionRules SelectionRules {
|
||
|
get {
|
||
|
SelectionRules result = SelectionRules.AllSizeable;
|
||
|
|
||
|
if (_control.Site != null) {
|
||
|
IDesignerHost host = _control.Site.GetService (typeof (IDesignerHost)) as IDesignerHost;
|
||
|
if (host != null) {
|
||
|
ControlDesigner designer = host.GetDesigner (_control) as ControlDesigner;
|
||
|
if (designer != null)
|
||
|
result = designer.SelectionRules;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public Control Control {
|
||
|
get { return _control; }
|
||
|
set {
|
||
|
if (value != null)
|
||
|
_control = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public Control Parent {
|
||
|
get {
|
||
|
if (_control.Parent == null)
|
||
|
return _control;
|
||
|
else
|
||
|
return _control.Parent;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private GrabHandle GrabHandleSelected {
|
||
|
get { return _handle; }
|
||
|
set { _handle = value; }
|
||
|
}
|
||
|
|
||
|
private bool PrimarySelection{
|
||
|
get {
|
||
|
bool result = false;
|
||
|
if (this.Control != null && this.Control.Site != null) {
|
||
|
ISelectionService selection = this.Control.Site.GetService (typeof (ISelectionService)) as ISelectionService;
|
||
|
if (selection != null && selection.PrimarySelection == this.Control)
|
||
|
result = true;
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
}
|
||
|
#endregion
|
||
|
|
||
|
|
||
|
#region Drawing
|
||
|
public void OnPaint (Graphics gfx)
|
||
|
{
|
||
|
DrawFrame (gfx);
|
||
|
DrawGrabHandles (gfx);
|
||
|
}
|
||
|
|
||
|
private void DrawGrabHandles (Graphics gfx)
|
||
|
{
|
||
|
GraphicsState state = gfx.Save();
|
||
|
gfx.TranslateTransform (this.Bounds.X, this.Bounds.Y);
|
||
|
|
||
|
for (int i = 0; i < _handles.Length; i++) {
|
||
|
_handles[i].Width = BORDER_SIZE;
|
||
|
_handles[i].Height = BORDER_SIZE;
|
||
|
}
|
||
|
|
||
|
SelectionRules rules = this.SelectionRules;
|
||
|
bool primarySelection = this.PrimarySelection;
|
||
|
bool enabled = false;
|
||
|
|
||
|
_handles[(int) GrabHandle.TopLeft].Location = new Point (0,0);
|
||
|
if (this.CheckSelectionRules (rules, SelectionRules.TopSizeable | SelectionRules.LeftSizeable))
|
||
|
enabled = true;
|
||
|
|
||
|
ControlPaint.DrawGrabHandle (gfx, _handles[(int)GrabHandle.TopLeft], primarySelection, enabled);
|
||
|
enabled = false;
|
||
|
|
||
|
_handles[(int) GrabHandle.TopMiddle].Location = new Point ((this.Bounds.Width - BORDER_SIZE) / 2, 0);
|
||
|
if (this.CheckSelectionRules (rules, SelectionRules.TopSizeable))
|
||
|
enabled = true;
|
||
|
|
||
|
ControlPaint.DrawGrabHandle (gfx, _handles[(int)GrabHandle.TopMiddle], primarySelection, enabled);
|
||
|
enabled = false;
|
||
|
|
||
|
_handles[(int) GrabHandle.TopRight].Location = new Point (this.Bounds.Width - BORDER_SIZE, 0);
|
||
|
if (this.CheckSelectionRules (rules, SelectionRules.TopSizeable | SelectionRules.RightSizeable))
|
||
|
enabled = true;
|
||
|
|
||
|
ControlPaint.DrawGrabHandle (gfx, _handles[(int)GrabHandle.TopRight], primarySelection, enabled);
|
||
|
enabled = false;
|
||
|
|
||
|
_handles[(int) GrabHandle.Right].Location = new Point (this.Bounds.Width - BORDER_SIZE,
|
||
|
(this.Bounds.Height - BORDER_SIZE) / 2);
|
||
|
if (this.CheckSelectionRules (rules, SelectionRules.RightSizeable))
|
||
|
enabled = true;
|
||
|
|
||
|
ControlPaint.DrawGrabHandle (gfx, _handles[(int)GrabHandle.Right], primarySelection, enabled);
|
||
|
enabled = false;
|
||
|
|
||
|
_handles[(int) GrabHandle.BottomRight].Location = new Point (this.Bounds.Width - BORDER_SIZE,
|
||
|
this.Bounds.Height - BORDER_SIZE);
|
||
|
if (this.CheckSelectionRules (rules, SelectionRules.BottomSizeable | SelectionRules.RightSizeable))
|
||
|
enabled = true;
|
||
|
|
||
|
ControlPaint.DrawGrabHandle (gfx, _handles[(int)GrabHandle.BottomRight], primarySelection, enabled);
|
||
|
enabled = false;
|
||
|
|
||
|
_handles[(int) GrabHandle.BottomMiddle].Location = new Point ((this.Bounds.Width - BORDER_SIZE) / 2,
|
||
|
this.Bounds.Height - BORDER_SIZE);
|
||
|
if (this.CheckSelectionRules (rules, SelectionRules.BottomSizeable))
|
||
|
enabled = true;
|
||
|
|
||
|
ControlPaint.DrawGrabHandle (gfx, _handles[(int)GrabHandle.BottomMiddle], primarySelection, enabled);
|
||
|
enabled = false;
|
||
|
|
||
|
_handles[(int) GrabHandle.BottomLeft].Location = new Point (0, this.Bounds.Height - BORDER_SIZE);
|
||
|
if (this.CheckSelectionRules (rules, SelectionRules.BottomSizeable | SelectionRules.LeftSizeable))
|
||
|
enabled = true;
|
||
|
|
||
|
ControlPaint.DrawGrabHandle (gfx, _handles[(int)GrabHandle.BottomLeft], primarySelection, enabled);
|
||
|
enabled = false;
|
||
|
|
||
|
_handles[(int) GrabHandle.Left].Location = new Point (0, (this.Bounds.Height - BORDER_SIZE) / 2);
|
||
|
if (this.CheckSelectionRules (rules, SelectionRules.LeftSizeable))
|
||
|
enabled = true;
|
||
|
|
||
|
ControlPaint.DrawGrabHandle (gfx, _handles[(int)GrabHandle.Left], primarySelection, enabled);
|
||
|
gfx.Restore (state);
|
||
|
}
|
||
|
|
||
|
protected void DrawFrame (Graphics gfx)
|
||
|
{
|
||
|
Color negativeColor = Color.FromArgb ((byte)~(_control.Parent.BackColor.R),
|
||
|
(byte)~(_control.Parent.BackColor.G),
|
||
|
(byte)~(_control.Parent.BackColor.B));
|
||
|
Pen pen = new Pen (new HatchBrush (HatchStyle.Percent30, negativeColor, Color.FromArgb (0)), BORDER_SIZE);
|
||
|
gfx.DrawRectangle (pen, this.Control.Bounds);
|
||
|
}
|
||
|
#endregion
|
||
|
|
||
|
|
||
|
#region Dragging
|
||
|
private bool _resizing = false;
|
||
|
|
||
|
|
||
|
public bool SetCursor (int x, int y)
|
||
|
{
|
||
|
bool modified = false;
|
||
|
|
||
|
if (!_resizing) {
|
||
|
GrabHandle handle = PointToGrabHandle (this.PointToClient (Control.MousePosition));
|
||
|
if (handle != GrabHandle.None)
|
||
|
modified = true;
|
||
|
|
||
|
if (handle == GrabHandle.TopLeft)
|
||
|
Cursor.Current = Cursors.SizeNWSE;
|
||
|
else if (handle == GrabHandle.TopMiddle)
|
||
|
Cursor.Current = Cursors.SizeNS;
|
||
|
else if (handle == GrabHandle.TopRight)
|
||
|
Cursor.Current = Cursors.SizeNESW;
|
||
|
else if (handle == GrabHandle.Right)
|
||
|
Cursor.Current = Cursors.SizeWE;
|
||
|
else if (handle == GrabHandle.BottomRight)
|
||
|
Cursor.Current = Cursors.SizeNWSE;
|
||
|
else if (handle == GrabHandle.BottomMiddle)
|
||
|
Cursor.Current = Cursors.SizeNS;
|
||
|
else if (handle == GrabHandle.BottomLeft)
|
||
|
Cursor.Current = Cursors.SizeNESW;
|
||
|
else if (handle == GrabHandle.Left)
|
||
|
Cursor.Current = Cursors.SizeWE;
|
||
|
else
|
||
|
Cursor.Current = Cursors.Default;
|
||
|
}
|
||
|
return modified;
|
||
|
}
|
||
|
|
||
|
// container coordinates
|
||
|
public void ResizeBegin (int x, int y)
|
||
|
{
|
||
|
this.GrabHandleSelected = PointToGrabHandle (this.PointToClient (this.Parent.PointToScreen (new Point (x, y))));
|
||
|
|
||
|
if (this.GrabHandleSelected != GrabHandle.None)
|
||
|
_resizing = true;
|
||
|
}
|
||
|
|
||
|
private bool CheckSelectionRules (SelectionRules rules, SelectionRules toCheck)
|
||
|
{
|
||
|
return ((rules & toCheck) == toCheck);
|
||
|
}
|
||
|
|
||
|
// container coordinates returns deltaBounds
|
||
|
public Rectangle ResizeContinue (int x, int y)
|
||
|
{
|
||
|
//Console.WriteLine ("ResizeContinue: " + x + " : " + y);
|
||
|
//Console.WriteLine ("GrabHandleSelected: " + GrabHandleSelected);
|
||
|
|
||
|
Rectangle bounds = (Rectangle)TypeDescriptor.GetProperties (_control)["Bounds"].GetValue (_control);
|
||
|
Rectangle deltaBounds = bounds;
|
||
|
Point pointerLocation = new Point (x, y);
|
||
|
SelectionRules rules = this.SelectionRules;
|
||
|
int top, height, left, width = 0;
|
||
|
|
||
|
if (_resizing && this.GrabHandleSelected != GrabHandle.None && rules != SelectionRules.Locked) {
|
||
|
if (this.GrabHandleSelected == GrabHandle.TopLeft &&
|
||
|
CheckSelectionRules (rules, SelectionRules.LeftSizeable | SelectionRules.TopSizeable)) {
|
||
|
|
||
|
top = _control.Top;
|
||
|
height = _control.Height;
|
||
|
left = _control.Left;
|
||
|
width = _control.Width;
|
||
|
|
||
|
if (pointerLocation.Y < _control.Bottom) {
|
||
|
top = pointerLocation.Y;
|
||
|
height = _control.Bottom - pointerLocation.Y;
|
||
|
}
|
||
|
if (pointerLocation.X < _control.Right) {
|
||
|
left = pointerLocation.X;
|
||
|
width = _control.Right - pointerLocation.X;
|
||
|
bounds = new Rectangle (left, top, width, height);
|
||
|
}
|
||
|
}
|
||
|
else if (this.GrabHandleSelected == GrabHandle.TopRight &&
|
||
|
CheckSelectionRules (rules, SelectionRules.TopSizeable | SelectionRules.RightSizeable)) {
|
||
|
|
||
|
top = _control.Top;
|
||
|
height = _control.Height;
|
||
|
width = _control.Width;
|
||
|
|
||
|
if (pointerLocation.Y < _control.Bottom) {
|
||
|
top = pointerLocation.Y;
|
||
|
height = _control.Bottom - pointerLocation.Y;
|
||
|
}
|
||
|
width = pointerLocation.X - _control.Left;
|
||
|
bounds = new Rectangle (_control.Left, top, width, height);
|
||
|
}
|
||
|
else if (GrabHandleSelected == GrabHandle.TopMiddle && CheckSelectionRules (rules, SelectionRules.TopSizeable)) {
|
||
|
if (pointerLocation.Y < _control.Bottom) {
|
||
|
top = pointerLocation.Y;
|
||
|
height = _control.Bottom - pointerLocation.Y;
|
||
|
bounds = new Rectangle (_control.Left, top, _control.Width, height);
|
||
|
}
|
||
|
}
|
||
|
else if (this.GrabHandleSelected == GrabHandle.Right && CheckSelectionRules (rules, SelectionRules.RightSizeable)) {
|
||
|
width = pointerLocation.X - _control.Left;
|
||
|
bounds = new Rectangle (_control.Left, _control.Top, width, _control.Height);
|
||
|
}
|
||
|
else if (this.GrabHandleSelected == GrabHandle.BottomRight &&
|
||
|
CheckSelectionRules (rules, SelectionRules.BottomSizeable | SelectionRules.RightSizeable)) {
|
||
|
|
||
|
width = pointerLocation.X - _control.Left;
|
||
|
height = pointerLocation.Y - _control.Top;
|
||
|
bounds = new Rectangle (_control.Left, _control.Top, width, height);
|
||
|
}
|
||
|
else if (GrabHandleSelected == GrabHandle.BottomMiddle && CheckSelectionRules (rules, SelectionRules.BottomSizeable)) {
|
||
|
height = pointerLocation.Y - _control.Top;
|
||
|
bounds = new Rectangle (_control.Left, _control.Top, _control.Width, height);
|
||
|
}
|
||
|
else if (GrabHandleSelected == GrabHandle.BottomLeft &&
|
||
|
CheckSelectionRules (rules, SelectionRules.BottomSizeable | SelectionRules.LeftSizeable)) {
|
||
|
|
||
|
height = _control.Height;
|
||
|
left = _control.Left;
|
||
|
width = _control.Width;
|
||
|
|
||
|
if (pointerLocation.X < _control.Right) {
|
||
|
left = pointerLocation.X;
|
||
|
width = _control.Right - pointerLocation.X;
|
||
|
}
|
||
|
height = pointerLocation.Y - _control.Top;
|
||
|
bounds = new Rectangle (left, _control.Top, width, height);
|
||
|
}
|
||
|
else if (GrabHandleSelected == GrabHandle.Left && CheckSelectionRules (rules, SelectionRules.LeftSizeable)) {
|
||
|
if (pointerLocation.X < _control.Right) {
|
||
|
left = pointerLocation.X;
|
||
|
width = _control.Right - pointerLocation.X;
|
||
|
bounds = new Rectangle (left, _control.Top, width, _control.Height);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//Console.WriteLine ("bounds: " + bounds.ToString ());
|
||
|
TypeDescriptor.GetProperties (_control)["Bounds"].SetValue (_control, bounds);
|
||
|
|
||
|
}
|
||
|
|
||
|
this.Parent.Refresh ();
|
||
|
deltaBounds.X = bounds.X - deltaBounds.X;
|
||
|
deltaBounds.Y = bounds.Y - deltaBounds.Y;
|
||
|
deltaBounds.Height = bounds.Height - deltaBounds.Height;
|
||
|
deltaBounds.Width = bounds.Width - deltaBounds.Width;
|
||
|
return deltaBounds;
|
||
|
}
|
||
|
|
||
|
|
||
|
public void ResizeEnd (bool cancel)
|
||
|
{
|
||
|
this.GrabHandleSelected = GrabHandle.None;
|
||
|
_resizing = false;
|
||
|
}
|
||
|
|
||
|
public void Resize (Rectangle deltaBounds)
|
||
|
{
|
||
|
SelectionRules rules = this.SelectionRules;
|
||
|
|
||
|
if (this.CheckSelectionRules (rules, SelectionRules.Locked) || !this.CheckSelectionRules (rules, SelectionRules.Moveable))
|
||
|
return;
|
||
|
|
||
|
Rectangle bounds = (Rectangle)TypeDescriptor.GetProperties (_control)["Bounds"].GetValue (_control);
|
||
|
|
||
|
if (CheckSelectionRules (rules, SelectionRules.LeftSizeable)) {
|
||
|
bounds.X += deltaBounds.X;
|
||
|
bounds.Width += deltaBounds.Width;
|
||
|
}
|
||
|
if (CheckSelectionRules (rules, SelectionRules.RightSizeable) && !CheckSelectionRules (rules, SelectionRules.LeftSizeable)) {
|
||
|
bounds.Y += deltaBounds.Y;
|
||
|
bounds.Width += deltaBounds.Width;
|
||
|
}
|
||
|
if (CheckSelectionRules (rules, SelectionRules.TopSizeable)) {
|
||
|
bounds.Y += deltaBounds.Y;
|
||
|
bounds.Height += deltaBounds.Height;
|
||
|
}
|
||
|
if (CheckSelectionRules (rules, SelectionRules.BottomSizeable) && !CheckSelectionRules (rules, SelectionRules.TopSizeable)) {
|
||
|
bounds.Height += deltaBounds.Height;
|
||
|
}
|
||
|
|
||
|
TypeDescriptor.GetProperties (_control)["Bounds"].SetValue (_control, bounds);
|
||
|
}
|
||
|
#endregion
|
||
|
|
||
|
|
||
|
#region Utility methods
|
||
|
|
||
|
public bool HitTest (int x, int y)
|
||
|
{
|
||
|
if (PointToGrabHandle (this.PointToClient (this.Parent.PointToScreen (new Point (x, y)))) != GrabHandle.None)
|
||
|
return true;
|
||
|
else
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
private GrabHandle PointToGrabHandle (Point pointerLocation)
|
||
|
{
|
||
|
GrabHandle result = GrabHandle.None;
|
||
|
|
||
|
if (IsCursorOnGrabHandle (pointerLocation, _handles[0]))
|
||
|
result = GrabHandle.TopLeft;
|
||
|
else if (IsCursorOnGrabHandle (pointerLocation, _handles[1]))
|
||
|
result = GrabHandle.TopMiddle;
|
||
|
else if (IsCursorOnGrabHandle (pointerLocation, _handles[2]))
|
||
|
result = GrabHandle.TopRight;
|
||
|
else if (IsCursorOnGrabHandle (pointerLocation, _handles[3]))
|
||
|
result = GrabHandle.Right;
|
||
|
else if (IsCursorOnGrabHandle (pointerLocation, _handles[4]))
|
||
|
result = GrabHandle.BottomRight;
|
||
|
else if (IsCursorOnGrabHandle (pointerLocation, _handles[5]))
|
||
|
result = GrabHandle.BottomMiddle;
|
||
|
else if (IsCursorOnGrabHandle (pointerLocation, _handles[6]))
|
||
|
result = GrabHandle.BottomLeft;
|
||
|
else if (IsCursorOnGrabHandle (pointerLocation, _handles[7]))
|
||
|
result = GrabHandle.Left;
|
||
|
else
|
||
|
result = GrabHandle.None;
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
private bool IsCursorOnGrabHandle (Point pointerLocation, Rectangle handleRectangle)
|
||
|
{
|
||
|
if (pointerLocation.X >= handleRectangle.X &&
|
||
|
pointerLocation.X <= handleRectangle.X + handleRectangle.Width &&
|
||
|
pointerLocation.Y >= handleRectangle.Y &&
|
||
|
pointerLocation.Y <= handleRectangle.Y + handleRectangle.Height) {
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
private Point PointToClient (Point screenPoint)
|
||
|
{
|
||
|
Point pointerLocation = this.Parent.PointToClient (screenPoint);
|
||
|
pointerLocation.X = pointerLocation.X - this.Bounds.X;
|
||
|
pointerLocation.Y = pointerLocation.Y - this.Bounds.Y;
|
||
|
return pointerLocation;
|
||
|
}
|
||
|
#endregion
|
||
|
|
||
|
}
|
||
|
}
|