2010-04-06 Jb Evain <jbevain@novell.com>
[mcs.git] / class / System.Design / System.Windows.Forms.Design / SelectionFrame.cs
blob1d8555be747a4540f4822c72c8a3bcb2f1667f0e
1 //
2 // System.Windows.Forms.Design.SelectionFrame
3 //
4 // Authors:
5 // Ivan N. Zlatev (contact i-nZ.net)
6 //
7 // (C) 2006-2007 Ivan N. Zlatev
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System;
31 using System.Collections;
32 using System.ComponentModel;
33 using System.ComponentModel.Design;
34 using System.Drawing;
35 using System.Drawing.Drawing2D;
36 using System.Windows.Forms;
39 namespace System.Windows.Forms.Design
41 // This is not a control!
42 //
43 internal class SelectionFrame
46 public SelectionFrame (Control control)
48 if (control == null)
49 throw new ArgumentNullException ("control");
51 _control = control;
55 private Rectangle _bounds;
56 private Control _control;
57 private Rectangle[] _handles = new Rectangle[8];
58 private GrabHandle _handle = GrabHandle.None;
59 private const int BORDER_SIZE = 7;
62 #region Properties
63 private enum GrabHandle {
64 None = -1,
65 TopLeft = 0,
66 TopMiddle,
67 TopRight,
68 Right,
69 BottomRight,
70 BottomMiddle,
71 BottomLeft,
72 Left,
73 Border // the border surrounding the control.
76 public Rectangle Bounds {
77 get {
78 _bounds.X = _control.Location.X - BORDER_SIZE;
79 _bounds.Y = _control.Location.Y - BORDER_SIZE;
80 _bounds.Width = _control.Width + BORDER_SIZE *2;
81 _bounds.Height = _control.Height + BORDER_SIZE *2;
83 return _bounds;
85 set {
86 _bounds = value;
87 _control.Bounds = _bounds;
91 private SelectionRules SelectionRules {
92 get {
93 SelectionRules result = SelectionRules.AllSizeable;
95 if (_control.Site != null) {
96 IDesignerHost host = _control.Site.GetService (typeof (IDesignerHost)) as IDesignerHost;
97 if (host != null) {
98 ControlDesigner designer = host.GetDesigner (_control) as ControlDesigner;
99 if (designer != null)
100 result = designer.SelectionRules;
104 return result;
108 public Control Control {
109 get { return _control; }
110 set {
111 if (value != null)
112 _control = value;
116 public Control Parent {
117 get {
118 if (_control.Parent == null)
119 return _control;
120 else
121 return _control.Parent;
125 private GrabHandle GrabHandleSelected {
126 get { return _handle; }
127 set { _handle = value; }
130 private bool PrimarySelection{
131 get {
132 bool result = false;
133 if (this.Control != null && this.Control.Site != null) {
134 ISelectionService selection = this.Control.Site.GetService (typeof (ISelectionService)) as ISelectionService;
135 if (selection != null && selection.PrimarySelection == this.Control)
136 result = true;
138 return result;
141 #endregion
144 #region Drawing
145 public void OnPaint (Graphics gfx)
147 DrawFrame (gfx);
148 DrawGrabHandles (gfx);
151 private void DrawGrabHandles (Graphics gfx)
153 GraphicsState state = gfx.Save();
154 gfx.TranslateTransform (this.Bounds.X, this.Bounds.Y);
156 for (int i = 0; i < _handles.Length; i++) {
157 _handles[i].Width = BORDER_SIZE;
158 _handles[i].Height = BORDER_SIZE;
161 SelectionRules rules = this.SelectionRules;
162 bool primarySelection = this.PrimarySelection;
163 bool enabled = false;
165 _handles[(int) GrabHandle.TopLeft].Location = new Point (0,0);
166 if (this.CheckSelectionRules (rules, SelectionRules.TopSizeable | SelectionRules.LeftSizeable))
167 enabled = true;
169 ControlPaint.DrawGrabHandle (gfx, _handles[(int)GrabHandle.TopLeft], primarySelection, enabled);
170 enabled = false;
172 _handles[(int) GrabHandle.TopMiddle].Location = new Point ((this.Bounds.Width - BORDER_SIZE) / 2, 0);
173 if (this.CheckSelectionRules (rules, SelectionRules.TopSizeable))
174 enabled = true;
176 ControlPaint.DrawGrabHandle (gfx, _handles[(int)GrabHandle.TopMiddle], primarySelection, enabled);
177 enabled = false;
179 _handles[(int) GrabHandle.TopRight].Location = new Point (this.Bounds.Width - BORDER_SIZE, 0);
180 if (this.CheckSelectionRules (rules, SelectionRules.TopSizeable | SelectionRules.RightSizeable))
181 enabled = true;
183 ControlPaint.DrawGrabHandle (gfx, _handles[(int)GrabHandle.TopRight], primarySelection, enabled);
184 enabled = false;
186 _handles[(int) GrabHandle.Right].Location = new Point (this.Bounds.Width - BORDER_SIZE,
187 (this.Bounds.Height - BORDER_SIZE) / 2);
188 if (this.CheckSelectionRules (rules, SelectionRules.RightSizeable))
189 enabled = true;
191 ControlPaint.DrawGrabHandle (gfx, _handles[(int)GrabHandle.Right], primarySelection, enabled);
192 enabled = false;
194 _handles[(int) GrabHandle.BottomRight].Location = new Point (this.Bounds.Width - BORDER_SIZE,
195 this.Bounds.Height - BORDER_SIZE);
196 if (this.CheckSelectionRules (rules, SelectionRules.BottomSizeable | SelectionRules.RightSizeable))
197 enabled = true;
199 ControlPaint.DrawGrabHandle (gfx, _handles[(int)GrabHandle.BottomRight], primarySelection, enabled);
200 enabled = false;
202 _handles[(int) GrabHandle.BottomMiddle].Location = new Point ((this.Bounds.Width - BORDER_SIZE) / 2,
203 this.Bounds.Height - BORDER_SIZE);
204 if (this.CheckSelectionRules (rules, SelectionRules.BottomSizeable))
205 enabled = true;
207 ControlPaint.DrawGrabHandle (gfx, _handles[(int)GrabHandle.BottomMiddle], primarySelection, enabled);
208 enabled = false;
210 _handles[(int) GrabHandle.BottomLeft].Location = new Point (0, this.Bounds.Height - BORDER_SIZE);
211 if (this.CheckSelectionRules (rules, SelectionRules.BottomSizeable | SelectionRules.LeftSizeable))
212 enabled = true;
214 ControlPaint.DrawGrabHandle (gfx, _handles[(int)GrabHandle.BottomLeft], primarySelection, enabled);
215 enabled = false;
217 _handles[(int) GrabHandle.Left].Location = new Point (0, (this.Bounds.Height - BORDER_SIZE) / 2);
218 if (this.CheckSelectionRules (rules, SelectionRules.LeftSizeable))
219 enabled = true;
221 ControlPaint.DrawGrabHandle (gfx, _handles[(int)GrabHandle.Left], primarySelection, enabled);
222 gfx.Restore (state);
225 protected void DrawFrame (Graphics gfx)
227 Color negativeColor = Color.FromArgb ((byte)~(_control.Parent.BackColor.R),
228 (byte)~(_control.Parent.BackColor.G),
229 (byte)~(_control.Parent.BackColor.B));
230 Pen pen = new Pen (new HatchBrush (HatchStyle.Percent30, negativeColor, Color.FromArgb (0)), BORDER_SIZE);
231 gfx.DrawRectangle (pen, this.Control.Bounds);
233 #endregion
236 #region Dragging
237 private bool _resizing = false;
240 public bool SetCursor (int x, int y)
242 bool modified = false;
244 if (!_resizing) {
245 GrabHandle handle = PointToGrabHandle (this.PointToClient (Control.MousePosition));
246 if (handle != GrabHandle.None)
247 modified = true;
249 if (handle == GrabHandle.TopLeft)
250 Cursor.Current = Cursors.SizeNWSE;
251 else if (handle == GrabHandle.TopMiddle)
252 Cursor.Current = Cursors.SizeNS;
253 else if (handle == GrabHandle.TopRight)
254 Cursor.Current = Cursors.SizeNESW;
255 else if (handle == GrabHandle.Right)
256 Cursor.Current = Cursors.SizeWE;
257 else if (handle == GrabHandle.BottomRight)
258 Cursor.Current = Cursors.SizeNWSE;
259 else if (handle == GrabHandle.BottomMiddle)
260 Cursor.Current = Cursors.SizeNS;
261 else if (handle == GrabHandle.BottomLeft)
262 Cursor.Current = Cursors.SizeNESW;
263 else if (handle == GrabHandle.Left)
264 Cursor.Current = Cursors.SizeWE;
265 else
266 Cursor.Current = Cursors.Default;
268 return modified;
271 // container coordinates
272 public void ResizeBegin (int x, int y)
274 this.GrabHandleSelected = PointToGrabHandle (this.PointToClient (this.Parent.PointToScreen (new Point (x, y))));
276 if (this.GrabHandleSelected != GrabHandle.None)
277 _resizing = true;
280 private bool CheckSelectionRules (SelectionRules rules, SelectionRules toCheck)
282 return ((rules & toCheck) == toCheck);
285 // container coordinates returns deltaBounds
286 public Rectangle ResizeContinue (int x, int y)
288 //Console.WriteLine ("ResizeContinue: " + x + " : " + y);
289 //Console.WriteLine ("GrabHandleSelected: " + GrabHandleSelected);
291 Rectangle bounds = (Rectangle)TypeDescriptor.GetProperties (_control)["Bounds"].GetValue (_control);
292 Rectangle deltaBounds = bounds;
293 Point pointerLocation = new Point (x, y);
294 SelectionRules rules = this.SelectionRules;
295 int top, height, left, width = 0;
297 if (_resizing && this.GrabHandleSelected != GrabHandle.None && rules != SelectionRules.Locked) {
298 if (this.GrabHandleSelected == GrabHandle.TopLeft &&
299 CheckSelectionRules (rules, SelectionRules.LeftSizeable | SelectionRules.TopSizeable)) {
301 top = _control.Top;
302 height = _control.Height;
303 left = _control.Left;
304 width = _control.Width;
306 if (pointerLocation.Y < _control.Bottom) {
307 top = pointerLocation.Y;
308 height = _control.Bottom - pointerLocation.Y;
310 if (pointerLocation.X < _control.Right) {
311 left = pointerLocation.X;
312 width = _control.Right - pointerLocation.X;
313 bounds = new Rectangle (left, top, width, height);
316 else if (this.GrabHandleSelected == GrabHandle.TopRight &&
317 CheckSelectionRules (rules, SelectionRules.TopSizeable | SelectionRules.RightSizeable)) {
319 top = _control.Top;
320 height = _control.Height;
321 width = _control.Width;
323 if (pointerLocation.Y < _control.Bottom) {
324 top = pointerLocation.Y;
325 height = _control.Bottom - pointerLocation.Y;
327 width = pointerLocation.X - _control.Left;
328 bounds = new Rectangle (_control.Left, top, width, height);
330 else if (GrabHandleSelected == GrabHandle.TopMiddle && CheckSelectionRules (rules, SelectionRules.TopSizeable)) {
331 if (pointerLocation.Y < _control.Bottom) {
332 top = pointerLocation.Y;
333 height = _control.Bottom - pointerLocation.Y;
334 bounds = new Rectangle (_control.Left, top, _control.Width, height);
337 else if (this.GrabHandleSelected == GrabHandle.Right && CheckSelectionRules (rules, SelectionRules.RightSizeable)) {
338 width = pointerLocation.X - _control.Left;
339 bounds = new Rectangle (_control.Left, _control.Top, width, _control.Height);
341 else if (this.GrabHandleSelected == GrabHandle.BottomRight &&
342 CheckSelectionRules (rules, SelectionRules.BottomSizeable | SelectionRules.RightSizeable)) {
344 width = pointerLocation.X - _control.Left;
345 height = pointerLocation.Y - _control.Top;
346 bounds = new Rectangle (_control.Left, _control.Top, width, height);
348 else if (GrabHandleSelected == GrabHandle.BottomMiddle && CheckSelectionRules (rules, SelectionRules.BottomSizeable)) {
349 height = pointerLocation.Y - _control.Top;
350 bounds = new Rectangle (_control.Left, _control.Top, _control.Width, height);
352 else if (GrabHandleSelected == GrabHandle.BottomLeft &&
353 CheckSelectionRules (rules, SelectionRules.BottomSizeable | SelectionRules.LeftSizeable)) {
355 height = _control.Height;
356 left = _control.Left;
357 width = _control.Width;
359 if (pointerLocation.X < _control.Right) {
360 left = pointerLocation.X;
361 width = _control.Right - pointerLocation.X;
363 height = pointerLocation.Y - _control.Top;
364 bounds = new Rectangle (left, _control.Top, width, height);
366 else if (GrabHandleSelected == GrabHandle.Left && CheckSelectionRules (rules, SelectionRules.LeftSizeable)) {
367 if (pointerLocation.X < _control.Right) {
368 left = pointerLocation.X;
369 width = _control.Right - pointerLocation.X;
370 bounds = new Rectangle (left, _control.Top, width, _control.Height);
374 //Console.WriteLine ("bounds: " + bounds.ToString ());
375 TypeDescriptor.GetProperties (_control)["Bounds"].SetValue (_control, bounds);
379 this.Parent.Refresh ();
380 deltaBounds.X = bounds.X - deltaBounds.X;
381 deltaBounds.Y = bounds.Y - deltaBounds.Y;
382 deltaBounds.Height = bounds.Height - deltaBounds.Height;
383 deltaBounds.Width = bounds.Width - deltaBounds.Width;
384 return deltaBounds;
388 public void ResizeEnd (bool cancel)
390 this.GrabHandleSelected = GrabHandle.None;
391 _resizing = false;
394 public void Resize (Rectangle deltaBounds)
396 SelectionRules rules = this.SelectionRules;
398 if (this.CheckSelectionRules (rules, SelectionRules.Locked) || !this.CheckSelectionRules (rules, SelectionRules.Moveable))
399 return;
401 Rectangle bounds = (Rectangle)TypeDescriptor.GetProperties (_control)["Bounds"].GetValue (_control);
403 if (CheckSelectionRules (rules, SelectionRules.LeftSizeable)) {
404 bounds.X += deltaBounds.X;
405 bounds.Width += deltaBounds.Width;
407 if (CheckSelectionRules (rules, SelectionRules.RightSizeable) && !CheckSelectionRules (rules, SelectionRules.LeftSizeable)) {
408 bounds.Y += deltaBounds.Y;
409 bounds.Width += deltaBounds.Width;
411 if (CheckSelectionRules (rules, SelectionRules.TopSizeable)) {
412 bounds.Y += deltaBounds.Y;
413 bounds.Height += deltaBounds.Height;
415 if (CheckSelectionRules (rules, SelectionRules.BottomSizeable) && !CheckSelectionRules (rules, SelectionRules.TopSizeable)) {
416 bounds.Height += deltaBounds.Height;
419 TypeDescriptor.GetProperties (_control)["Bounds"].SetValue (_control, bounds);
421 #endregion
424 #region Utility methods
426 public bool HitTest (int x, int y)
428 if (PointToGrabHandle (this.PointToClient (this.Parent.PointToScreen (new Point (x, y)))) != GrabHandle.None)
429 return true;
430 else
431 return false;
434 private GrabHandle PointToGrabHandle (Point pointerLocation)
436 GrabHandle result = GrabHandle.None;
438 if (IsCursorOnGrabHandle (pointerLocation, _handles[0]))
439 result = GrabHandle.TopLeft;
440 else if (IsCursorOnGrabHandle (pointerLocation, _handles[1]))
441 result = GrabHandle.TopMiddle;
442 else if (IsCursorOnGrabHandle (pointerLocation, _handles[2]))
443 result = GrabHandle.TopRight;
444 else if (IsCursorOnGrabHandle (pointerLocation, _handles[3]))
445 result = GrabHandle.Right;
446 else if (IsCursorOnGrabHandle (pointerLocation, _handles[4]))
447 result = GrabHandle.BottomRight;
448 else if (IsCursorOnGrabHandle (pointerLocation, _handles[5]))
449 result = GrabHandle.BottomMiddle;
450 else if (IsCursorOnGrabHandle (pointerLocation, _handles[6]))
451 result = GrabHandle.BottomLeft;
452 else if (IsCursorOnGrabHandle (pointerLocation, _handles[7]))
453 result = GrabHandle.Left;
454 else
455 result = GrabHandle.None;
457 return result;
460 private bool IsCursorOnGrabHandle (Point pointerLocation, Rectangle handleRectangle)
462 if (pointerLocation.X >= handleRectangle.X &&
463 pointerLocation.X <= handleRectangle.X + handleRectangle.Width &&
464 pointerLocation.Y >= handleRectangle.Y &&
465 pointerLocation.Y <= handleRectangle.Y + handleRectangle.Height) {
466 return true;
468 return false;
471 private Point PointToClient (Point screenPoint)
473 Point pointerLocation = this.Parent.PointToClient (screenPoint);
474 pointerLocation.X = pointerLocation.X - this.Bounds.X;
475 pointerLocation.Y = pointerLocation.Y - this.Bounds.Y;
476 return pointerLocation;
478 #endregion