Merge pull request #1407 from chrisvire/bug-24587
[mono.git] / mcs / class / System.Design / System.Windows.Forms.Design / DocumentDesigner.cs
1 //
2 // System.Windows.Forms.Design.DocumentDesigner
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 using System;
31 using System.ComponentModel;
32 using System.ComponentModel.Design;
33 using System.Windows.Forms;
34 using System.Drawing;
35 using System.Drawing.Design;
36 using System.Collections;
37 #if NET_2_0
38 using System.Windows.Forms.Design.Behavior;
39 #endif
40
41 namespace System.Windows.Forms.Design
42 {
43 #if NET_2_0
44         [ToolboxItemFilter ("System.Windows.Forms")]
45 #endif
46         public class DocumentDesigner : ScrollableControlDesigner, IRootDesigner, IToolboxUser
47         {
48
49                 // This is what you *see*
50                 /*
51                         .-------------------------------------.
52                         | Panel to host the designed Control  |
53                         |--------------Splitter---------------|
54                         |         Panel with a ComponentTray     |
55                         |_____________________________________|
56
57                 */
58                 //
59 #region DesignerViewFrame
60                 public class DesignerViewFrame : System.Windows.Forms.UserControl
61                 {
62                         private System.Windows.Forms.Panel DesignerPanel;
63                         private System.Windows.Forms.Splitter splitter1;
64                         private System.Windows.Forms.Panel ComponentTrayPanel;
65                         private ComponentTray _componentTray;
66                         private Control _designedControl;
67
68                         public DesignerViewFrame (Control designedControl, ComponentTray tray)
69                         {
70                                 if (designedControl == null) {
71                                         throw new ArgumentNullException ("designedControl");
72                                 }
73                                 if (tray == null) {
74                                         throw new ArgumentNullException ("tray");
75                                 }
76                                 //
77                                 // The InitializeComponent() call is required for Windows Forms designer support.
78                                 //
79                                 InitializeComponent();
80
81                                 _designedControl = designedControl;
82                                 this.SuspendLayout ();
83                                 this.DesignerPanel.Controls.Add (designedControl);
84                                 this.ResumeLayout ();
85
86                                 this.ComponentTray = tray;
87                         }
88
89 #region Windows Forms Designer generated code
90                         /// <summary>
91                         /// This method is required for Windows Forms designer support.
92                         /// Do not change the method contents inside the source code editor. The Forms designer might
93                         /// not be able to load this method if it was changed manually.
94                         /// </summary>
95                         private void InitializeComponent() {
96                                 this.ComponentTrayPanel = new System.Windows.Forms.Panel();
97                                 this.splitter1 = new System.Windows.Forms.Splitter();
98                                 this.DesignerPanel = new System.Windows.Forms.Panel();
99                                 this.SuspendLayout();
100                                 // 
101                                 // ComponentTrayPanel
102                                 // 
103                                 this.ComponentTrayPanel.BackColor = System.Drawing.Color.LemonChiffon;
104                                 this.ComponentTrayPanel.Dock = System.Windows.Forms.DockStyle.Bottom;
105                                 this.ComponentTrayPanel.Location = new System.Drawing.Point(0, 194);
106                                 this.ComponentTrayPanel.Name = "ComponentTrayPanel";
107                                 this.ComponentTrayPanel.Size = new System.Drawing.Size(292, 72);
108                                 this.ComponentTrayPanel.TabIndex = 1;
109                                 this.ComponentTrayPanel.Visible = false;
110                                 // 
111                                 // splitter1
112                                 // 
113                                 this.splitter1.Dock = System.Windows.Forms.DockStyle.Bottom;
114                                 this.splitter1.Location = new System.Drawing.Point(0, 186);
115                                 this.splitter1.Name = "splitter1";
116                                 this.splitter1.Size = new System.Drawing.Size(292, 8);
117                                 this.splitter1.TabIndex = 2;
118                                 this.splitter1.TabStop = false;
119                                 this.splitter1.Visible = false;
120                                 // 
121                                 // DesignerPanel
122                                 // 
123                                 this.DesignerPanel.AutoScroll = true;
124                                 this.DesignerPanel.BackColor = System.Drawing.Color.White;
125                                 this.DesignerPanel.Dock = System.Windows.Forms.DockStyle.Fill;
126                                 this.DesignerPanel.Location = new System.Drawing.Point(0, 0);
127                                 this.DesignerPanel.Name = "DesignerPanel";
128                                 this.DesignerPanel.Size = new System.Drawing.Size(292, 266);
129                                 this.DesignerPanel.TabIndex = 0;
130                                 this.DesignerPanel.MouseUp += new System.Windows.Forms.MouseEventHandler(this.DesignerPanel_MouseUp);
131                                 this.DesignerPanel.MouseMove += new System.Windows.Forms.MouseEventHandler(this.DesignerPanel_MouseMove);
132                                 this.DesignerPanel.MouseDown += new System.Windows.Forms.MouseEventHandler(this.DesignerPanel_MouseDown);
133                                 this.DesignerPanel.Paint += new PaintEventHandler (DesignerPanel_Paint);
134                                 // 
135                                 // DesignerViewFrame
136                                 // 
137                                 this.Controls.Add(this.splitter1);
138                                 this.Controls.Add(this.ComponentTrayPanel);
139                                 this.Controls.Add(this.DesignerPanel);
140                                 this.Name = "UserControl1";
141                                 this.Size = new System.Drawing.Size(292, 266);
142                                 this.Dock = DockStyle.Fill;
143                                 this.ResumeLayout(false);
144                         }
145
146 #endregion
147                         
148                         private bool _mouseDown = false;
149                         private bool _firstMove = false;
150
151                         void DesignerPanel_Paint (object sender, PaintEventArgs e)
152                         {
153                                 IUISelectionService selectionServ = this.DesignedControl.Site.GetService (typeof (IUISelectionService)) as IUISelectionService;
154                                 if (selectionServ != null)
155                                         selectionServ.PaintAdornments (this.DesignerPanel, e.Graphics);
156                         }
157
158                         void DesignerPanel_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
159                         {
160                                 _mouseDown = true;
161                                 _firstMove = true;
162                         }
163
164                         void DesignerPanel_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
165                         {
166                                 IUISelectionService selectionServ = this.DesignedControl.Site.GetService (typeof (IUISelectionService)) as IUISelectionService;
167                                 if (selectionServ == null)
168                                         return;
169                                 
170                                 selectionServ.SetCursor (e.X, e.Y);
171                                 if (_mouseDown) {
172                                         if (_firstMove) {
173                                                 selectionServ.MouseDragBegin (this.DesignerPanel, e.X, e.Y);
174                                                 _firstMove = false;
175                                         }
176                                         else {
177                                                 selectionServ.MouseDragMove (e.X, e.Y);
178                                         }
179                                 }
180                                 else if (selectionServ.SelectionInProgress) {
181                                         selectionServ.MouseDragMove (e.X, e.Y);
182                                 }
183                         }
184
185                         void DesignerPanel_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
186                         {
187                                 IUISelectionService selectionServ = this.DesignedControl.Site.GetService (typeof (IUISelectionService)) as IUISelectionService;
188                                 if (_mouseDown) {
189                                         if (selectionServ != null)
190                                                 selectionServ.MouseDragEnd (false);
191                                         _mouseDown = false;
192                                 }
193                                 else if (selectionServ.SelectionInProgress) {
194                                         selectionServ.MouseDragEnd (false);
195                                 }
196                         }
197
198                         // by default the component tray is hidden and essentially should be shown once there
199                         // is a component added to it
200                         //
201                         public void ShowComponentTray ()
202                         {
203                                 if (!this.ComponentTray.Visible) {
204                                         this.ComponentTrayPanel.Visible = true;
205                                         this.ComponentTray.Visible = true;
206                                         this.splitter1.Visible = true;
207                                 }
208                         }
209                         
210                         public void HideComponentTray ()
211                         {
212                                 if (!this.ComponentTray.Visible) {
213                                         this.ComponentTrayPanel.Visible = true;
214                                         this.ComponentTray.Visible = true;
215                                         this.splitter1.Visible = true;
216                                 }
217                         }
218
219                         public ComponentTray ComponentTray {
220                                 get { return _componentTray; }
221                                 set {
222                                         this.SuspendLayout ();
223                                         this.ComponentTrayPanel.Controls.Remove (_componentTray);
224                                         this.ComponentTrayPanel.Controls.Add (value);
225                                         this.ResumeLayout ();
226                                         _componentTray = value;
227                                         _componentTray.Visible = false;
228                                 }
229                         }
230
231                         public Control DesignedControl {
232                                 get { return _designedControl; }
233                                 set { 
234                                 }
235                         }
236
237                         protected override void Dispose (bool disposing)
238                         {
239                                 if (_designedControl != null) {
240                                         this.DesignerPanel.Controls.Remove (_designedControl);
241                                         _designedControl = null;
242                                 }
243                                 
244                                 if (_componentTray != null) {
245                                         this.ComponentTrayPanel.Controls.Remove (_componentTray);
246                                         _componentTray.Dispose ();
247                                         _componentTray = null;
248                                 }
249                                 
250                                 base.Dispose (disposing);
251                         }
252                 }               
253 #endregion         
254                 
255                 
256                 
257                 
258                 private DesignerViewFrame _designerViewFrame;
259
260                 public DocumentDesigner ()
261                 {
262                 }
263
264                 private DesignerViewFrame View {
265                         get { return _designerViewFrame; }
266                 }
267
268 #region Initialization
269                 public override void Initialize (IComponent component)
270                 {
271                         base.Initialize (component);
272
273                         _designerViewFrame = new DesignerViewFrame (this.Control, new ComponentTray (this, component.Site));
274                         _designerViewFrame.DesignedControl.Location = new Point (15, 15);
275                         SetValue (this.Component,  "Location", new Point (0, 0));
276
277                         IComponentChangeService componentChangeSvc = GetService (typeof (IComponentChangeService)) as IComponentChangeService;
278                         if (componentChangeSvc != null) {
279                                 componentChangeSvc.ComponentAdded += new ComponentEventHandler (OnComponentAdded);
280                                 componentChangeSvc.ComponentRemoved += new ComponentEventHandler (OnComponentRemoved);
281                         }
282
283                         IMenuCommandService menuCommands = GetService (typeof (IMenuCommandService)) as IMenuCommandService;
284                         IServiceContainer serviceContainer = this.GetService (typeof (IServiceContainer)) as IServiceContainer;
285                         if (menuCommands != null && serviceContainer != null)
286                                 new DefaultMenuCommands (serviceContainer).AddTo (menuCommands);
287                         InitializeSelectionService ();
288                 }
289
290                 private void InitializeSelectionService ()
291                 {
292                         IUISelectionService guiSelectionService = this.GetService (typeof (IUISelectionService)) as IUISelectionService;
293                         if (guiSelectionService == null) {
294                                 IServiceContainer serviceContainer = this.GetService (typeof (IServiceContainer)) as IServiceContainer;
295                                 serviceContainer.AddService (typeof (IUISelectionService), (IUISelectionService) new UISelectionService (serviceContainer));
296                         }
297
298                         ISelectionService selectionService = this.GetService (typeof (ISelectionService)) as ISelectionService;
299                         selectionService.SetSelectedComponents (new IComponent[] { this.Component });
300                 }
301
302 #if !NET_2_0
303                 // MSDN says overriden
304                 // 
305                 public override void OnSetComponentDefaults ()
306                 {
307                         base.OnSetComponentDefaults ();
308                 }
309 #endif
310
311                 protected override void Dispose (bool disposing)
312                 {
313                         if (disposing) {
314                                 if (_designerViewFrame != null) {
315                                         _designerViewFrame.Dispose ();
316                                         _designerViewFrame = null;
317                                         
318                                 }
319                                 IComponentChangeService componentChangeSvc = GetService (typeof (IComponentChangeService)) as IComponentChangeService;
320                                 if (componentChangeSvc != null) {
321                                         componentChangeSvc.ComponentAdded -= new ComponentEventHandler (OnComponentAdded);
322                                         componentChangeSvc.ComponentRemoved -= new ComponentEventHandler (OnComponentRemoved);
323                                 }
324                         }
325                         base.Dispose (disposing);
326                 }
327 #endregion
328
329
330 #region MSDN says overriden
331
332 #if NET_2_0
333                 public override GlyphCollection GetGlyphs (GlyphSelectionType selectionType)
334                 {
335                         return base.GetGlyphs (selectionType);
336                 }
337 #endif
338
339                 protected override void WndProc (ref Message m)
340                 {
341                         base.WndProc (ref m);
342                 }
343
344                 protected override void OnContextMenu (int x, int y)
345                 {
346                         base.OnContextMenu (x, y);
347                 }
348
349                 protected override void OnCreateHandle ()
350                 {
351                         base.OnCreateHandle ();
352                 }
353                 
354 #endregion
355
356
357 #region Components and ComponentTray
358
359                 private void OnComponentAdded (object sender, ComponentEventArgs args)
360                 {
361                         if (!(args.Component is Control)) {
362                                 this.View.ComponentTray.AddComponent (args.Component);
363                                 if (this.View.ComponentTray.ComponentCount > 0) {
364                                         if (!this.View.ComponentTray.Visible)
365                                                 this.View.ShowComponentTray ();
366                                 }
367                         }
368                 }
369
370                 private void OnComponentRemoved (object sender, ComponentEventArgs args)
371                 {
372                         if (!(args.Component is Control)) {
373                                 this.View.ComponentTray.RemoveComponent (args.Component);
374                                 if (this.View.ComponentTray.ComponentCount == 0) {
375                                         if (this.View.ComponentTray.Visible)
376                                                 this.View.HideComponentTray ();
377                                 }
378                         }
379                 }
380 #endregion
381
382
383 #region IRootDesigner
384
385                 object IRootDesigner.GetView (ViewTechnology technology)
386                 {
387 #if NET_2_0
388                         if (technology != ViewTechnology.Default)
389                                 throw new ArgumentException ("Only ViewTechnology.WindowsForms is supported.");
390 #else
391                         if (technology != ViewTechnology.WindowsForms)
392                                 throw new ArgumentException ("Only ViewTechnology.WindowsForms is supported.");
393 #endif
394                         return _designerViewFrame;
395                 }
396
397                 ViewTechnology[] IRootDesigner.SupportedTechnologies {
398                         get {
399 #if NET_2_0
400                                 return new ViewTechnology[] { ViewTechnology.Default };
401 #else
402                                 return new ViewTechnology[] { ViewTechnology.WindowsForms };
403 #endif  
404                         }
405                 }
406 #endregion
407
408
409 #region IToolBoxUser
410
411                 // Indicates whether the specified tool is supported by the designer.
412                 // If it is not the tool is disabled in the toolbox.
413                 //
414                 // Used for subclasses, e.g the FormDocumentDesigner won't accept a Form?
415                 //
416                 bool IToolboxUser.GetToolSupported (ToolboxItem tool)
417                 {
418                         return this.GetToolSupported (tool);
419                 }
420
421                 protected virtual bool GetToolSupported (ToolboxItem tool)
422                 {
423                         return true;
424                 }
425
426
427                 // Handles the behavior that occurs when a user double-clicks a toolbox item.
428                 //
429                 void IToolboxUser.ToolPicked (ToolboxItem tool)
430                 {
431                         this.ToolPicked (tool);
432                 }
433
434                 // ToolPicked is called when the user double-clicks on a toolbox item. 
435                 // The document designer should create a component for the specified tool. 
436                 // Only tools that are enabled in the toolbox will be passed to this method.
437                 //
438                 // I create the component in the parent container of the primary selection.
439                 // If not available I create it in the rootcomponent (this essentially :-) )
440                 //
441                 protected virtual void ToolPicked (ToolboxItem tool)
442                 {
443                         ISelectionService selectionSvc = GetService (typeof (ISelectionService)) as ISelectionService;
444                         IDesignerHost host = GetService (typeof (IDesignerHost)) as IDesignerHost;
445                         if (selectionSvc != null && host != null) {
446                                 IDesigner designer = host.GetDesigner ((IComponent) selectionSvc.PrimarySelection);
447                                 if (designer is ParentControlDesigner)
448                                         ParentControlDesigner.InvokeCreateTool ((ParentControlDesigner) designer, tool);
449                                 else
450                                         this.CreateTool (tool);
451                         }
452                         else {
453                                 this.CreateTool (tool);
454                         }
455                         IToolboxService tbServ = this.GetService (typeof (IToolboxService)) as IToolboxService;
456                         tbServ.SelectedToolboxItemUsed ();
457                 }
458 #endregion
459
460
461 #region Properties
462                 // A root designer can be resized to the bottom and to the right.
463                 //
464                 public override SelectionRules SelectionRules {
465                         get {
466                                 return (SelectionRules.RightSizeable | SelectionRules.BottomSizeable | SelectionRules.Visible);
467                         }
468                 }
469 #endregion
470
471
472 #region Metadata filtering and Design-Time properties
473
474                 // MSDN says that this adds the "BackColor" and "Location" browsable design-time propeties.
475                 // 
476                 // The reason for overwriting the Location property created by the ControDesigner is that
477                 // the root component is not draggable (e.g a form has a static location in the DesignerViewFrame)
478                 //
479                 protected override void PreFilterProperties (IDictionary properties)
480                 {
481                         base.PreFilterProperties (properties);
482
483                         PropertyDescriptor propertyDescriptor = properties["BackColor"] as PropertyDescriptor;
484                         if (propertyDescriptor != null) {
485                                 properties["BackColor"] = TypeDescriptor.CreateProperty (typeof (DocumentDesigner),
486                                                 propertyDescriptor,
487                                                 new Attribute[] { new DefaultValueAttribute (System.Drawing.SystemColors.Control) });
488                         }
489                         
490                         propertyDescriptor = properties["Location"] as PropertyDescriptor;
491                         if (propertyDescriptor != null) {
492                                 properties["Location"] = TypeDescriptor.CreateProperty (typeof (DocumentDesigner),
493                                                 propertyDescriptor,
494                                                 new Attribute[] { new DefaultValueAttribute (typeof (Point), "0, 0") });
495                         }
496                 }
497
498                 private Color BackColor {
499                         get { return (Color) ShadowProperties["BackColor"]; }
500                         set {
501                                 ShadowProperties["BackColor"] = value;
502                                 this.Control.BackColor = value;
503                         }
504                 }
505                 
506                 private Point Location {
507                         get { return (Point) ShadowProperties["Location"]; }
508                         set { ShadowProperties["Location"] = value; }
509                 }
510 #endregion
511
512
513 #region Misc
514                 protected IMenuEditorService menuEditorService;
515
516                 // Checks for the existence of a menu editor service and creates one if one does not already exist.
517                 // component - The IComponent to ensure has a context menu service.
518                 // XXX: Not sure exactly what this should do...
519                 //
520                 protected virtual void EnsureMenuEditorService (IComponent component)
521                 {
522                         if (this.menuEditorService == null && component is ContextMenu)
523                                 menuEditorService = (IMenuEditorService) GetService (typeof (IMenuEditorService));
524                 }
525 #endregion
526
527         }
528 }