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