aboutsummaryrefslogtreecommitdiff
path: root/source/ShiftUI/Design/SelectionFrame.cs
diff options
context:
space:
mode:
Diffstat (limited to 'source/ShiftUI/Design/SelectionFrame.cs')
-rw-r--r--source/ShiftUI/Design/SelectionFrame.cs481
1 files changed, 481 insertions, 0 deletions
diff --git a/source/ShiftUI/Design/SelectionFrame.cs b/source/ShiftUI/Design/SelectionFrame.cs
new file mode 100644
index 0000000..a3c092d
--- /dev/null
+++ b/source/ShiftUI/Design/SelectionFrame.cs
@@ -0,0 +1,481 @@
+//
+// ShiftUI.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 ShiftUI;
+
+
+namespace ShiftUI.Design
+{
+ // This is not a control!
+ //
+ internal class SelectionFrame
+ {
+
+ public SelectionFrame (Widget control)
+ {
+ if (control == null)
+ throw new ArgumentNullException ("control");
+
+ _control = control;
+ }
+
+
+ private Rectangle _bounds;
+ private Widget _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) {
+ WidgetDesigner designer = host.GetDesigner (_control) as WidgetDesigner;
+ if (designer != null)
+ result = designer.SelectionRules;
+ }
+ }
+
+ return result;
+ }
+ }
+
+ public Widget Widget {
+ get { return _control; }
+ set {
+ if (value != null)
+ _control = value;
+ }
+ }
+
+ public Widget 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.Widget != null && this.Widget.Site != null) {
+ ISelectionService selection = this.Widget.Site.GetService (typeof (ISelectionService)) as ISelectionService;
+ if (selection != null && selection.PrimarySelection == this.Widget)
+ 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;
+
+ WidgetPaint.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;
+
+ WidgetPaint.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;
+
+ WidgetPaint.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;
+
+ WidgetPaint.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;
+
+ WidgetPaint.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;
+
+ WidgetPaint.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;
+
+ WidgetPaint.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;
+
+ WidgetPaint.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.Widget.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 (Widget.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
+
+ }
+}