Move Mono.CompilerServices.SymbolWriter to build after 2.1 raw mscorlib
[mono.git] / mcs / class / System.Design / System.Windows.Forms.Design / ControlDesigner.cs
1 //
2 // System.Windows.Forms.Design.ControlDesigner
3 //
4 // Authors:
5 //        Ivan N. Zlatev (contact i-nZ.net)
6 //
7 // (C) 2006-2007 Ivan N. Zlatev
8
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:
17 //
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 //
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.
28 //
29
30
31 using System;
32 using System.ComponentModel;
33 using System.ComponentModel.Design;
34 using System.Runtime.InteropServices;
35 using System.Windows.Forms;
36 using System.Drawing;
37 using System.Drawing.Design;
38 using System.Collections;
39 #if NET_2_0
40 using System.Windows.Forms.Design.Behavior;
41 #endif
42
43 namespace System.Windows.Forms.Design
44 {
45         public class ControlDesigner : ComponentDesigner, IMessageReceiver
46         {
47                 
48
49                 private WndProcRouter _messageRouter;
50                 private bool _locked = false;
51                 private bool _mouseDown = false;
52                 private bool _mouseMoveAfterMouseDown = false;
53                 private bool _mouseDownFirstMove = false;
54                 private bool _firstMouseMoveInClient = true;
55
56                 public ControlDesigner ()
57                 {
58                 }
59
60 #region Initialization
61                 public override void Initialize (IComponent component)
62                 {
63                         base.Initialize (component);
64
65                         if (!(component is Control))
66                                 throw new ArgumentException ("Component is not a Control.");
67
68                         Control.Text = component.Site.Name;
69                         _messageRouter = new WndProcRouter ((Control) component, (IMessageReceiver) this);
70                         Control.WindowTarget = _messageRouter;
71
72                         // DT properties
73                         //
74                         this.Visible = true;
75                         this.Enabled = true;
76                         this.Locked = false;
77                         this.AllowDrop = false;
78                         //
79                         // The control properties
80                         //
81                         Control.Enabled = true;
82                         Control.Visible = true;
83                         Control.AllowDrop = false;
84
85                         this.Control.DragDrop += new DragEventHandler (OnDragDrop);
86                         this.Control.DragEnter += new DragEventHandler (OnDragEnter);
87                         this.Control.DragLeave += new EventHandler (OnDragLeave);
88                         this.Control.DragOver += new DragEventHandler (OnDragOver);
89
90                         // XXX: The control already has a handle?
91                         //
92                         if (Control.IsHandleCreated)
93                                 OnCreateHandle ();
94
95                 }
96
97                 // The default implementation of this method sets the component's Text property to
98                 // its name (Component.Site.Name), if the property field is of type string.
99                 //
100                 public override void OnSetComponentDefaults ()
101                 {
102                         if (this.Component != null && this.Component.Site != null) {
103                                 PropertyDescriptor propertyDescriptor = TypeDescriptor.GetProperties (this.Component)["Text"];
104                                 if (propertyDescriptor != null && !propertyDescriptor.IsReadOnly &&
105                                         propertyDescriptor.PropertyType == typeof (string)) {
106                                         propertyDescriptor.SetValue (Component, Component.Site.Name);
107                                 }
108                         }
109                 }
110 #endregion
111
112
113 #region Properties and Fields - AccessabilityObject Left
114                 protected static readonly Point InvalidPoint = new Point (int.MinValue, int.MinValue);
115
116 #if NET_2_0
117                 protected internal BehaviorService BehaviorService {
118                         get { throw new NotImplementedException (); }
119                 }
120 #endif
121
122                 public virtual Control Control {
123                         get { return (Control) base.Component; }
124                 }
125
126                 protected virtual bool EnableDragRect {
127                         get { return true; }
128                 }
129
130                 public virtual SelectionRules SelectionRules {
131                         get {
132                                 if (this.Control == null)
133                                         return SelectionRules.None;
134
135                                 // all controls on the surface are visible
136                                 //
137                                 SelectionRules selectionRules = SelectionRules.Visible;
138
139                                 if ((bool)GetValue (this.Component, "Locked") == true) {
140                                         selectionRules |= SelectionRules.Locked;
141                                 }
142                                 else {
143                                         DockStyle dockStyle = (DockStyle) this.GetValue (base.Component, "Dock", typeof (DockStyle));
144
145                                         switch (dockStyle) {
146                                                 case DockStyle.Top:
147                                                         selectionRules |= SelectionRules.BottomSizeable;
148                                                         break;
149                                                 case DockStyle.Left:
150                                                         selectionRules |= SelectionRules.RightSizeable;
151                                                         break;
152                                                 case DockStyle.Right:
153                                                         selectionRules |= SelectionRules.LeftSizeable;
154                                                         break;
155                                                 case DockStyle.Bottom:
156                                                         selectionRules |= SelectionRules.TopSizeable;
157                                                         break;
158                                                 case DockStyle.Fill:
159                                                         break;
160                                                 default:
161                                                         selectionRules |= SelectionRules.Moveable;
162                                                         selectionRules |= SelectionRules.AllSizeable;
163                                                         break;
164                                         }
165                                 }
166
167                                 return selectionRules;
168                         }
169                 }
170
171                 public override ICollection AssociatedComponents {
172                         get {
173                                 ArrayList components = new ArrayList ();
174                                 foreach (Control c in this.Control.Controls)
175                                         if (c.Site != null)
176                                                 components.Add (c);
177                                 return components;
178                         }
179                 }
180
181 #if NET_2_0
182                 protected override IComponent ParentComponent {
183                         get { return this.GetValue (this.Control,  "Parent") as Control;}
184                 }
185 #endif
186                 // TODO: implement ControlDesigner.ControlAccessabilityObject
187                 //
188                 public virtual AccessibleObject AccessibilityObject {
189                         get {
190                                 if (accessibilityObj == null)
191                                         accessibilityObj = new AccessibleObject ();
192
193                                 return accessibilityObj;
194                         }
195                 }
196                 protected AccessibleObject accessibilityObj;
197
198 #endregion
199
200
201 #region WndProc
202         
203                 protected void DefWndProc (ref Message m)
204                 {
205                         _messageRouter.ToControl (ref m);
206                 }
207                 
208                 protected void BaseWndProc (ref Message m)
209                 {
210                         _messageRouter.ToSystem (ref m);
211                 }
212                 
213                 void IMessageReceiver.WndProc (ref Message m)
214                 {
215                         this.WndProc (ref m);
216                 }
217                 
218                 // Keep in mind that messages are recieved for the child controls if routed
219                 //
220                 protected virtual void WndProc (ref Message m)
221                 {
222                         // Filter out kb input
223                         //
224                         if ((Native.Msg) m.Msg >= Native.Msg.WM_KEYFIRST &&  (Native.Msg) m.Msg <= Native.Msg.WM_KEYLAST)
225                                 return;
226
227                         // Mouse messages should be routed the control, if GetHitTest (virtual) returns true.
228                         //
229                         if (IsMouseMessage ((Native.Msg) m.Msg) &&
230                             this.GetHitTest (new Point (Native.LoWord((int) m.LParam), Native.HiWord (((int) m.LParam))))) {
231                                 
232                                 this.DefWndProc (ref m);
233                                 return;
234                         }
235
236                         switch ((Native.Msg) m.Msg) {
237                                 case Native.Msg.WM_CREATE:
238                                         this.DefWndProc (ref m);
239                                         if (m.HWnd == this.Control.Handle)
240                                                 OnCreateHandle ();
241                                         break;
242
243                                 case Native.Msg.WM_CONTEXTMENU:
244                                         OnContextMenu (Native.LoWord ((int) m.LParam), Native.HiWord ((int) m.LParam));
245                                         break;
246
247                                 case Native.Msg.WM_SETCURSOR:
248                                         if (this.GetHitTest (new Point (Native.LoWord ((int) m.LParam), Native.HiWord ((int) m.LParam))))
249                                                 this.DefWndProc (ref m);
250                                         else
251                                                 OnSetCursor ();
252                                         break;
253
254                                 case Native.Msg.WM_SETFOCUS:
255                                         this.DefWndProc (ref m);
256                                         break;
257                                 
258                                 case Native.Msg.WM_PAINT:
259                                         // Wait for control's WM_PAINT to complete first.
260                                         //
261                                         this.DefWndProc (ref m);
262
263                                         Graphics gfx = Graphics.FromHwnd (m.HWnd);
264                                         PaintEventArgs args = new PaintEventArgs (gfx, this.Control.Bounds);
265                                         OnPaintAdornments (args);
266                                         gfx.Dispose ();
267                                         args.Dispose ();
268                                         break;
269
270                                 case Native.Msg.WM_NCRBUTTONDOWN:
271                                 case Native.Msg.WM_NCLBUTTONDOWN:
272                                 case Native.Msg.WM_NCMBUTTONDOWN:
273                                 case Native.Msg.WM_NCLBUTTONDBLCLK:
274                                 case Native.Msg.WM_NCRBUTTONDBLCLK:
275                                         break;
276
277                                 case Native.Msg.WM_LBUTTONDBLCLK:
278                                 case Native.Msg.WM_RBUTTONDBLCLK:
279                                 case Native.Msg.WM_MBUTTONDBLCLK:
280                                         if ((Native.Msg)m.Msg == Native.Msg.WM_LBUTTONDBLCLK)
281                                                 _mouseButtonDown = MouseButtons.Left;
282                                         else if ((Native.Msg)m.Msg == Native.Msg.WM_RBUTTONDBLCLK)
283                                                 _mouseButtonDown = MouseButtons.Right;
284                                         else if ((Native.Msg)m.Msg == Native.Msg.WM_MBUTTONDBLCLK)
285                                                 _mouseButtonDown = MouseButtons.Middle;
286                                         OnMouseDoubleClick ();
287                                         this.BaseWndProc (ref m);
288                                         break;
289
290                                 case Native.Msg.WM_MOUSEHOVER:
291                                         OnMouseHover ();
292                                         break;
293                                 
294                                 case Native.Msg.WM_LBUTTONDOWN:
295                                 case Native.Msg.WM_RBUTTONDOWN:          
296                                 case Native.Msg.WM_MBUTTONDOWN:
297                                         _mouseMoveAfterMouseDown = true;
298                                         if ((Native.Msg)m.Msg == Native.Msg.WM_LBUTTONDOWN)
299                                                 _mouseButtonDown = MouseButtons.Left;
300                                         else if ((Native.Msg)m.Msg == Native.Msg.WM_RBUTTONDOWN)
301                                                 _mouseButtonDown = MouseButtons.Right;
302                                         else if ((Native.Msg)m.Msg == Native.Msg.WM_MBUTTONDOWN)
303                                                 _mouseButtonDown = MouseButtons.Middle;
304                                 
305                                         if (_firstMouseMoveInClient) {
306                                                 OnMouseEnter ();
307                                                 _firstMouseMoveInClient = false;
308                                         }
309                                         this.OnMouseDown (Native.LoWord ((int)m.LParam), Native.HiWord ((int)m.LParam));
310                                         this.BaseWndProc (ref m);
311                                         break;
312
313                                 case Native.Msg.WM_MOUSELEAVE:
314                                         _firstMouseMoveInClient = false;
315                                         OnMouseLeave ();
316                                         this.BaseWndProc (ref m);
317                                         break;
318
319                                 // The WM_CANCELMODE message is sent to cancel certain modes, such as mouse capture.
320                                 // For example, the system sends this message to the active window when a dialog box
321                                 // or message box is displayed. Certain functions also send this message explicitly to
322                                 // the specified window regardless of whether it is the active window. For example,
323                                 // the EnableWindow function sends this message when disabling the specified window.
324                                 //
325                                 case Native.Msg.WM_CANCELMODE:
326                                         OnMouseDragEnd (true);
327                                         this.DefWndProc (ref m);
328                                         break;
329
330                                 case Native.Msg.WM_LBUTTONUP:
331                                 case Native.Msg.WM_RBUTTONUP:
332                                 case Native.Msg.WM_NCLBUTTONUP:
333                                 case Native.Msg.WM_NCRBUTTONUP:
334                                 case Native.Msg.WM_MBUTTONUP:  
335                                 case Native.Msg.WM_NCMBUTTONUP:
336                                         _mouseMoveAfterMouseDown = false; // just in case
337                                         this.OnMouseUp ();
338                                         this.BaseWndProc (ref m);
339                                         break;
340
341                                 // // MWF Specific msg! - must reach control
342                                 // //
343                                 // case Native.Msg.WM_MOUSE_ENTER:
344                                 //      _firstMouseMoveInClient = false; // just so that nothing will get fired in WM_MOUSEMOVE
345                                 //      OnMouseEnter ();
346                                 //      this.DefWndProc (ref m);
347                                 //      break;
348
349                                 // FIXME: The first MOUSEMOVE after WM_MOUSEDOWN should be ingored
350                                 //
351                                 case Native.Msg.WM_MOUSEMOVE:
352                                         if (_mouseMoveAfterMouseDown) { // mousemove is send after each mousedown so ignore that
353                                                 _mouseMoveAfterMouseDown = false;
354                                                 this.BaseWndProc (ref m);
355                                                 return;
356                                         }
357                                         // If selection is in progress pass the mouse move msg to the primary selection.
358                                         // If resizing is in progress pass to the parent of the primary selection (remmember that the selection
359                                         // frame is not a control and is drawn in the parent of the primary selection).
360                                         //
361                                         // Required in order for those 2 operations to continue when the mouse is moving over a control covering
362                                         // the one where the action takes place.
363                                         // 
364                                         IUISelectionService uiSelectionServ = this.GetService (typeof (IUISelectionService)) as IUISelectionService;
365                                         ISelectionService selectionServ = this.GetService (typeof (ISelectionService)) as ISelectionService;
366                                         IDesignerHost host = this.GetService (typeof (IDesignerHost)) as IDesignerHost;
367                                         
368
369                                         if (uiSelectionServ != null && selectionServ != null && host != null) {
370                                                 Control primarySelection = selectionServ.PrimarySelection as Control;
371                                                 Point location = new Point (Native.LoWord ((int)m.LParam), Native.HiWord ((int)m.LParam));
372
373                                                 if (uiSelectionServ.SelectionInProgress &&
374                                                         this.Component != host.RootComponent && 
375                                                         this.Component != selectionServ.PrimarySelection) {
376
377                                                         location = primarySelection.PointToClient (this.Control.PointToScreen (location));
378                                                         Native.SendMessage (primarySelection.Handle, (Native.Msg)m.Msg, m.WParam, Native.LParam (location.X, location.Y));
379                                                 }
380                                                 else if (uiSelectionServ.ResizeInProgress && 
381                                                    // this.Component != host.RootComponent && 
382                                                         this.Control.Parent == ((Control)selectionServ.PrimarySelection).Parent) {
383
384                                                         location = this.Control.Parent.PointToClient (this.Control.PointToScreen (location));
385                                                         Native.SendMessage (this.Control.Parent.Handle, (Native.Msg)m.Msg, m.WParam, Native.LParam (location.X, location.Y));
386                                                 }
387                                                 else {
388                                                         this.OnMouseMove (location.X, location.Y);
389                                                 }
390                                         }
391                                         else {
392                                                 this.OnMouseMove (Native.LoWord ((int)m.LParam), Native.HiWord ((int)m.LParam));
393                                         }
394                                         this.BaseWndProc (ref m);
395                                         break;
396
397                                 default:
398                                         // Pass everything else to the control and return
399                                         //
400                                         this.DefWndProc (ref m);
401                                         break;
402                         }
403                 }
404                 
405                 // Indicates whether a mouse click at the specified point should be handled by the control.
406                 //
407                 protected virtual bool GetHitTest (Point point)
408                 {
409                         return false;
410                 }
411
412                 private bool IsMouseMessage (Native.Msg msg)
413                 {
414                         if (msg >= Native.Msg.WM_MOUSEFIRST && msg <= Native.Msg.WM_MOUSELAST)
415                                 return true;
416                         else if (msg >= Native.Msg.WM_NCLBUTTONDOWN && msg <= Native.Msg.WM_NCMBUTTONDBLCLK)
417                                 return true;
418                         else if (msg == Native.Msg.WM_MOUSEHOVER || msg == Native.Msg.WM_MOUSELEAVE)
419                                 return true;
420                         else
421                                 return false;
422                 }
423 #endregion
424
425
426 #region WndProc Message Handlers
427
428                 protected virtual void OnSetCursor ()
429                 {
430                 }
431
432                 // Raises the DoDefaultAction.
433                 //
434                 private void OnMouseDoubleClick ()
435                 {
436                         try {
437                                 base.DoDefaultAction ();
438                         }
439                         catch (Exception e) {
440                                 this.DisplayError (e);
441                         }
442                 }
443
444                 internal virtual void OnMouseDown (int x, int y)
445                 {
446                         _mouseDown = true;
447                         _mouseDownFirstMove = true;
448                         IUISelectionService uiSelection = this.GetService (typeof (IUISelectionService)) as IUISelectionService;
449                         if (uiSelection != null && uiSelection.AdornmentsHitTest (this.Control, x, y)) {
450                                 // 1) prevent primary selection from being changed at this point.
451                                 // 2) delegate behaviour in the future to the IUISelectionService
452                         }
453                         else {
454                                 ISelectionService selectionService = this.GetService (typeof (ISelectionService)) as ISelectionService;
455                                 if (selectionService != null) {
456                                         selectionService.SetSelectedComponents (new IComponent[] { this.Component });
457                                 }
458                         }
459                 }
460
461                 // Note that this is a pure WM_MOUSEMOVE acceptor
462                 //
463                 internal virtual void OnMouseMove (int x, int y)
464                 {
465                         if (_mouseDown) {
466                                 if (_mouseDownFirstMove) {
467                                         OnMouseDragBegin (x, y);
468                                         _mouseDownFirstMove = false;
469                                 }
470                                 else {
471                                         OnMouseDragMove (x, y);
472                                 }
473                         }
474
475                 }
476
477                 internal virtual void OnMouseUp ()
478                 {
479                         IUISelectionService uiSelection = this.GetService (typeof (IUISelectionService)) as IUISelectionService;
480
481                         if (_mouseDown) {
482                                 if (uiSelection != null && (uiSelection.SelectionInProgress || uiSelection.ResizeInProgress)) {
483                                         uiSelection.MouseDragEnd (false);
484                                 }
485                                 this.OnMouseDragEnd (false);
486                                 _mouseDown = false;
487                         }
488                         else {                    
489                                 if (uiSelection != null && (uiSelection.SelectionInProgress || uiSelection.ResizeInProgress)) { 
490                                         // If the mouse up happens over the a control which is not defacto participating in 
491                                         // the selection or resizing in progress, then inform the IUISelectionService of that event
492                                         //
493                                         uiSelection.MouseDragEnd (false);
494                                 }
495                         }
496                 }
497
498                 protected virtual void OnContextMenu (int x, int y)
499                 {
500                         IMenuCommandService service = this.GetService (typeof(IMenuCommandService)) as IMenuCommandService;
501                         if (service != null) {
502                                 service.ShowContextMenu (MenuCommands.SelectionMenu, x, y);
503                         }
504                 }
505
506                 protected virtual void OnMouseEnter ()
507                 {
508                 }
509
510                 protected virtual void OnMouseHover ()
511                 {
512                 }
513
514                 protected virtual void OnMouseLeave ()
515                 {
516                 }
517
518                 // Provides an opportunity to perform additional processing immediately
519                 // after the control handle has been created.
520                 //
521                 protected virtual void OnCreateHandle ()
522                 {
523                 }
524
525                 // Called after the control is done with the painting so that the designer host
526                 // can paint stuff over it.
527                 //
528                 protected virtual void OnPaintAdornments (PaintEventArgs pe)
529                 {
530                 }
531 #endregion
532
533
534 #region Mouse Dragging
535
536                 MouseButtons _mouseButtonDown;
537
538                 internal MouseButtons MouseButtonDown {
539                         get { return _mouseButtonDown;  }
540                 }
541
542                 protected virtual void OnMouseDragBegin (int x, int y)
543                 {
544                         IUISelectionService selectionServ = this.GetService (typeof (IUISelectionService)) as IUISelectionService;
545                         if (selectionServ != null && ((this.SelectionRules & SelectionRules.Moveable) == SelectionRules.Moveable)) {
546                                 // once this is fired the parent control (parentcontroldesigner) will start getting dragover events.
547                                 //
548                                 selectionServ.DragBegin ();
549                         }
550                 }
551
552                 protected virtual void OnMouseDragMove (int x, int y)
553                 {
554                 }
555                 
556                 protected virtual void OnMouseDragEnd (bool cancel)
557                 {
558                 }
559 #endregion
560
561                 
562 #region Parenting
563                 protected void HookChildControls (Control firstControl)
564                 {
565                         if (firstControl != null) {
566                                 foreach (Control control in firstControl.Controls) {
567                                         control.WindowTarget = (IWindowTarget) new WndProcRouter (control, (IMessageReceiver) this);
568                                 }
569                         }
570                 }
571
572                 protected void UnhookChildControls (Control firstControl)
573                 {
574                         if (firstControl != null) {
575                                 foreach (Control control in firstControl.Controls) {
576                                         if (control.WindowTarget is WndProcRouter)
577                                                 ((WndProcRouter) control.WindowTarget).Dispose ();
578                                 }
579                         }
580                 }
581
582                 // Someone please tell me why the hell is this method here?
583                 // What about having ParentControlDesigner.CanParent(...) ?
584                 // 
585                 public virtual bool CanBeParentedTo (IDesigner parentDesigner)
586                 {
587                         IDesignerHost host = this.GetService (typeof (IDesignerHost)) as IDesignerHost;
588
589                         if (parentDesigner is ParentControlDesigner &&
590                                 this.Component != host.RootComponent &&
591                                 !this.Control.Controls.Contains (((ParentControlDesigner)parentDesigner).Control)) {
592                                         return true;
593                         } else {
594                                 return false;
595                         }
596                 }
597 #endregion
598
599                 protected void DisplayError (Exception e)
600                 {
601                         if (e != null) {
602                                 IUIService uiService = GetService (typeof (IUIService)) as IUIService;
603                                 if (uiService != null) {
604                                         uiService.ShowError (e);
605                                 }
606                                 else {
607                                         string errorText = e.Message;
608                                         if (errorText == null ||  errorText == String.Empty)
609                                                 errorText = e.ToString ();
610                                         MessageBox.Show (Control, errorText, "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
611                                 }
612                         }
613                 }
614
615 #region Drag and Drop handling
616
617                 // Enables or disables Drag and Drop
618                 //
619                 protected void EnableDragDrop(bool value)
620                 {
621                         if (this.Control != null) {
622                                 if (value) {
623                                         Control.DragDrop += new DragEventHandler (OnDragDrop);
624                                         Control.DragOver += new DragEventHandler (OnDragOver);
625                                         Control.DragEnter += new DragEventHandler (OnDragEnter);
626                                         Control.DragLeave += new EventHandler (OnDragLeave);
627                                         Control.GiveFeedback += new GiveFeedbackEventHandler (OnGiveFeedback);
628                                         Control.AllowDrop = true;
629                                 }
630                                 else {
631                                         Control.DragDrop -= new DragEventHandler (OnDragDrop);
632                                         Control.DragOver -= new DragEventHandler (OnDragOver);
633                                         Control.DragEnter -= new DragEventHandler (OnDragEnter);
634                                         Control.DragLeave -= new EventHandler (OnDragLeave);
635                                         Control.GiveFeedback -= new GiveFeedbackEventHandler (OnGiveFeedback);
636                                         Control.AllowDrop = false;
637                                 }
638                         }
639                 }
640
641                 private void OnGiveFeedback (object sender, GiveFeedbackEventArgs e)
642                 {
643                         OnGiveFeedback (e);
644                 }
645
646                 private void OnDragDrop (object sender, DragEventArgs e)
647                 {
648                         OnDragDrop (e);
649                 }
650
651                 private void OnDragEnter (object sender, DragEventArgs e)
652                 {
653                         OnDragEnter (e);
654                 }
655
656                 private void OnDragLeave (object sender, EventArgs e)
657                 {
658                         OnDragLeave (e);
659                 }
660
661                 private void OnDragOver (object sender, DragEventArgs e)
662                 {
663                         OnDragOver (e);
664                 }
665
666                 protected virtual void OnGiveFeedback (GiveFeedbackEventArgs e)
667                 {
668                         e.UseDefaultCursors = false;
669                 }
670
671                 protected virtual void OnDragDrop (DragEventArgs e)
672                 {
673                 }
674
675                 protected virtual void OnDragEnter (DragEventArgs e)
676                 {
677                 }
678
679                 protected virtual void OnDragLeave (EventArgs e)
680                 {
681                 }
682
683                 protected virtual void OnDragOver (DragEventArgs e)
684                 {
685                 }
686 #endregion
687
688
689 #region Redirected Properties
690
691                 // This IDesignerFilter interface method override adds a set of properties
692                 // to this designer's component at design time. This method adds the following
693                 // browsable properties: "Visible", "Enabled", "ContextMenu", "AllowDrop", "Location",
694                 // "Name", "Controls", and "Locked".
695                 //
696                 // XXX: We aren't redirecting Controls
697                 // 
698                 protected override void PreFilterProperties (IDictionary properties)
699                 {
700                         base.PreFilterProperties (properties);
701
702                         string[] newProperties = {
703                                 "Visible", "Enabled", "ContextMenu", "AllowDrop", "Location", "Name",
704                         };
705
706                         Attribute[][] attributes = { 
707                                 new Attribute[] { new DefaultValueAttribute (true) },
708                                 new Attribute[] { new DefaultValueAttribute (true) },
709                                 new Attribute[] { new DefaultValueAttribute (null) },
710                                 new Attribute[] { new DefaultValueAttribute (false) },
711                                 new Attribute[] { new DefaultValueAttribute (typeof (Point), "0, 0") },
712                                 new Attribute[] {}
713                          };
714                         
715                         PropertyDescriptor propertyDescriptor = null;
716
717                         // If existing redirect each property to the ControlDesigner.
718                         //
719                         for (int i=0; i < newProperties.Length; i++) {
720                                 propertyDescriptor = properties[newProperties[i]] as PropertyDescriptor;
721                                 if (propertyDescriptor != null)
722                                         properties[newProperties[i]] = TypeDescriptor.CreateProperty (typeof (ControlDesigner),
723                                                                                                       propertyDescriptor,
724                                                                                                       attributes[i]);
725                         }
726
727                         // This one is a must to have.
728                         //
729                         properties["Locked"] = TypeDescriptor.CreateProperty (typeof (ControlDesigner), "Locked",
730                                                                                   typeof(bool),
731                                                                                   new Attribute[] {
732                                                                                           DesignOnlyAttribute.Yes,
733                                                                                           BrowsableAttribute.Yes,
734                                                                                           CategoryAttribute.Design,
735                                                                                           new DefaultValueAttribute (false),
736                                                                                           new DescriptionAttribute("The Locked property determines if we can move or resize the control.")
737                                                                                   });
738
739                 }
740
741                 // ShadowProperties returns the real property value if there is no "shadow" one set
742                 // Welcome to the land of shadows... :-)
743                 //
744                 private bool Visible {
745                         get { return (bool) base.ShadowProperties["Visible"]; }
746                         set { base.ShadowProperties["Visible"] = value; }
747                 }
748
749                 private bool Enabled {
750                         get { return (bool) base.ShadowProperties["Enabled"]; }
751                         set { base.ShadowProperties["Enabled"] = value; }
752                 }
753
754                 private bool Locked {
755                         get { return _locked; }
756                         set { _locked = value; }
757                 }
758
759                 private bool AllowDrop {
760                         get { return (bool)base.ShadowProperties["AllowDrop"]; }
761                         set { base.ShadowProperties["AllowDrop"] = value; }
762                 }
763
764                 private string Name {
765                         get { return base.Component.Site.Name; }
766                         set { base.Component.Site.Name = value; }
767                 }
768
769                 private ContextMenu ContextMenu {
770                         get { return (ContextMenu) base.ShadowProperties["ContextMenu"]; }
771                         set { base.ShadowProperties["ContextMenu"] = value; }
772                 }
773
774                 private Point Location {
775                         get { return this.Control.Location; }
776                         set { this.Control.Location = value; }
777                 }
778 #endregion
779
780
781 #region Utility methods
782                 internal object GetValue (object component, string propertyName)
783                 {
784                    return this.GetValue (component, propertyName, null);
785                 }
786                 
787                 internal object GetValue (object component, string propertyName, Type propertyType)
788                 {
789                         PropertyDescriptor prop = TypeDescriptor.GetProperties (component)[propertyName] as PropertyDescriptor;
790                         if (prop == null)
791                                 throw new InvalidOperationException ("Property \"" + propertyName + "\" is missing on " + 
792                                                                                                          component.GetType().AssemblyQualifiedName);
793                         if (propertyType != null && !propertyType.IsAssignableFrom (prop.PropertyType))
794                                         throw new InvalidOperationException ("Types do not match: " + prop.PropertyType.AssemblyQualifiedName +
795                                                                                                                  " : " + propertyType.AssemblyQualifiedName);
796                         return prop.GetValue (component);
797                 }
798
799                 internal void SetValue (object component, string propertyName, object value)
800                 {
801                         PropertyDescriptor prop = TypeDescriptor.GetProperties (component)[propertyName] as PropertyDescriptor;
802
803                         if (prop == null)
804                                         throw new InvalidOperationException ("Property \"" + propertyName + "\" is missing on " + 
805                                                                                                                  component.GetType().AssemblyQualifiedName);
806                         if (!prop.PropertyType.IsAssignableFrom (value.GetType ()))
807                                         throw new InvalidOperationException ("Types do not match: " + value.GetType ().AssemblyQualifiedName +
808                                                                                                                  " : " + prop.PropertyType.AssemblyQualifiedName);
809                         if (!prop.IsReadOnly)
810                                 prop.SetValue (component, value);
811                 }
812 #endregion
813
814                 protected override void Dispose (bool disposing)
815                 {
816                         if (disposing) {
817                                 if (this.Control != null) {
818                                         UnhookChildControls (Control);
819                                         OnMouseDragEnd (true);
820                                         _messageRouter.Dispose ();
821                                         this.Control.DragDrop -= new DragEventHandler (OnDragDrop);
822                                         this.Control.DragEnter -= new DragEventHandler (OnDragEnter);
823                                         this.Control.DragLeave -= new EventHandler (OnDragLeave);
824                                         this.Control.DragOver -= new DragEventHandler (OnDragOver);
825                                 }
826                         }
827                         base.Dispose (true);
828                 }
829
830
831
832 #if NET_2_0
833                 public virtual ControlDesigner InternalControlDesigner (int internalControlIndex)
834                 {
835                         return null;
836                 }
837
838                 public virtual int NumberOfInternalControlDesigners ()
839                 {
840                         return 0;
841                 }
842
843                 protected bool EnableDesignMode (Control child, string name)
844                 {
845                         if (name == null)
846                                 throw new ArgumentNullException ("name");
847                         if (child == null)
848                                 throw new ArgumentNullException ("child");
849
850                         bool success = false;
851                         INestedContainer nestedContainer = this.GetService (typeof (INestedContainer)) as INestedContainer;
852                         if (nestedContainer != null) {
853                                 nestedContainer.Add (child, name);
854                                 success = true;
855                         }
856                         return success;
857                 }
858
859 #region NET_2_0 Stubs
860
861                 [ComVisible (true)]
862                 public class ControlDesignerAccessibleObject : AccessibleObject
863                 {
864                         [MonoTODO]
865                         public ControlDesignerAccessibleObject (ControlDesigner designer, Control control)
866                         {
867                                 throw new NotImplementedException ();
868                         }
869
870                         [MonoTODO]
871                         public override AccessibleObject GetChild (int index)
872                         {
873                                 throw new NotImplementedException ();
874                         }
875
876                         [MonoTODO]
877                         public override int GetChildCount ()
878                         {
879                                 throw new NotImplementedException ();
880                         }
881
882                         [MonoTODO]
883                         public override AccessibleObject GetFocused ()
884                         {
885                                 throw new NotImplementedException ();
886                         }
887
888                         [MonoTODO]
889                         public override AccessibleObject GetSelected ()
890                         {
891                                 throw new NotImplementedException ();
892                         }
893
894                         [MonoTODO]
895                         public override AccessibleObject HitTest (int x, int y)
896                         {
897                                 throw new NotImplementedException ();
898                         }
899
900                         [MonoTODO]
901                         public override Rectangle Bounds {
902                                 get { throw new NotImplementedException (); }
903                         }
904
905                         [MonoTODO]
906                         public override string DefaultAction {
907                                 get { throw new NotImplementedException (); }
908                         }
909
910                         [MonoTODO]
911                         public override string Description {
912                                 get { throw new NotImplementedException (); }
913                         }
914
915                         [MonoTODO]
916                         public override string Name {
917                                 get { throw new NotImplementedException (); }
918                         }
919
920                         [MonoTODO]
921                         public override AccessibleObject Parent {
922                                 get { throw new NotImplementedException (); }
923                         }
924
925                         [MonoTODO]
926                         public override AccessibleRole Role {
927                                 get { throw new NotImplementedException (); }
928                         }
929
930                         [MonoTODO]
931                         public override AccessibleStates State {
932                                 get { throw new NotImplementedException (); }
933                         }
934
935                         [MonoTODO]
936                         public override string Value {
937                                 get { throw new NotImplementedException (); }
938                         }
939                 }
940
941                 [MonoTODO]
942                 protected virtual ControlBodyGlyph GetControlGlyph (GlyphSelectionType selectionType)
943                 {
944                         throw new NotImplementedException ();
945                 }
946
947                 [MonoTODO]
948                 public virtual GlyphCollection GetGlyphs (GlyphSelectionType selectionType)
949                 {
950                         throw new NotImplementedException ();
951                 }
952
953                 [MonoTODO]
954                 public override void InitializeExistingComponent (IDictionary defaultValues)
955                 {
956                         throw new NotImplementedException ();
957                 }
958
959                 [MonoTODO]
960                 public override void InitializeNewComponent (IDictionary defaultValues)
961                 {
962                         throw new NotImplementedException ();
963                 }
964
965                 [MonoTODO]
966                 protected virtual void OnDragComplete (DragEventArgs de)
967                 {
968                         throw new NotImplementedException ();
969                 }
970
971                 [MonoTODO]
972                 protected override InheritanceAttribute InheritanceAttribute {
973                         get { throw new NotImplementedException (); }
974                 }
975
976                 [MonoTODO]
977                 public virtual IList SnapLines {
978                         get { throw new NotImplementedException (); }
979                 }
980
981                 [MonoTODO]
982                 public virtual bool ParticipatesWithSnapLines {
983                         get { throw new NotImplementedException (); }
984                 }
985
986                 [MonoTODO]
987                 public bool AutoResizeHandles {
988                         get { throw new NotImplementedException (); }
989                         set { throw new NotImplementedException (); }
990                 }
991 #endregion
992 #endif
993
994
995         }
996 }