[LoongArch64] Part-5:add loongarch support in some files for LoongArch64. (#21769)
[mono-project.git] / mcs / class / System.Design / System.Windows.Forms.Design / ParentControlDesigner.cs
blobeb53ae4bc538cd074508188feb7dd603ac73e507
1 //
2 // System.Windows.Forms.Design.ParentControlDesigner
3 //
4 // Authors:
5 // Ivan N. Zlatev (contact i-nZ.net)
6 //
7 // (C) 2006 Ivan N. Zlatev
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 using System;
31 using System.ComponentModel;
32 using System.ComponentModel.Design;
33 using System.Windows.Forms;
34 using System.Drawing;
35 using System.Drawing.Drawing2D;
36 using System.Drawing.Design;
37 using System.Collections;
38 using System.Windows.Forms.Design.Behavior;
40 namespace System.Windows.Forms.Design
44 public class ParentControlDesigner : ControlDesigner
47 public ParentControlDesigner ()
52 #region Initialization
53 // Settings paths taken from the example at:
54 // http://msdn2.microsoft.com/en-us/library/system.componentmodel.design.idesigneroptionservice.aspx
56 public override void Initialize (IComponent component)
58 base.Initialize (component);
60 this.Control.AllowDrop = true;
62 // Initialize the default values of the Design-Time properties.
64 _defaultDrawGrid = true;
65 _defaultSnapToGrid = true;
66 _defaultGridSize = new Size (8, 8);
68 // If the parent Control of the designed one has a ParentDesigner then inherit the values
69 // from it's designer.
71 if (this.Control.Parent != null) {
72 ParentControlDesigner parentDesigner = GetParentControlDesignerOf (Control.Parent);
73 if (parentDesigner != null) {
74 _defaultDrawGrid = (bool) GetValue (parentDesigner.Component, "DrawGrid");
75 _defaultSnapToGrid = (bool) GetValue (parentDesigner.Component, "SnapToGrid");
76 _defaultGridSize = (Size) GetValue (parentDesigner.Component, "GridSize");
79 else {
80 // Else retrieve them through the IDesignerOptionService (if available)
82 IDesignerOptionService options = GetService (typeof (IDesignerOptionService)) as
83 IDesignerOptionService;
84 if (options != null) {
85 object value = null;
86 value = options.GetOptionValue (@"WindowsFormsDesigner\General", "DrawGrid");
87 if (value is bool)
88 _defaultDrawGrid = (bool) value;
90 value = options.GetOptionValue (@"WindowsFormsDesigner\General", "SnapToGrid");
91 if (value is bool)
92 _defaultSnapToGrid = (bool) value;
94 value = options.GetOptionValue (@"WindowsFormsDesigner\General", "GridSize");
95 if (value is Size)
96 _defaultGridSize = (Size) value;
100 IComponentChangeService componentChangeSvc = GetService (typeof (IComponentChangeService)) as IComponentChangeService;
101 if (componentChangeSvc != null) {
102 componentChangeSvc.ComponentRemoving += new ComponentEventHandler (OnComponentRemoving);
103 componentChangeSvc.ComponentRemoved += new ComponentEventHandler (OnComponentRemoved);
106 // At the end set whatever we've managed to get
108 _drawGrid = _defaultDrawGrid;
109 _snapToGrid = _defaultSnapToGrid;
110 _gridSize = _defaultGridSize;
113 protected override void Dispose (bool disposing)
115 if (disposing) {
116 EnableDragDrop (false);
117 OnMouseDragEnd (true);
119 base.Dispose (disposing);
121 #endregion
124 #region IToolboxService Related
126 // This is the code that is executed when you drop a tool from the Toolbox in the designer.
129 protected static void InvokeCreateTool (ParentControlDesigner toInvoke, ToolboxItem tool)
131 if (toInvoke != null)
132 toInvoke.CreateTool (tool);
135 protected void CreateTool (ToolboxItem tool)
137 CreateToolCore (tool, DefaultControlLocation.X, DefaultControlLocation.Y, 0, 0, true, false);
140 protected void CreateTool (ToolboxItem tool, Point location)
142 CreateToolCore (tool, location.X, location.Y, 0, 0, true, false);
145 protected void CreateTool (ToolboxItem tool, Rectangle bounds)
147 CreateToolCore (tool, bounds.X, bounds.Y, bounds.Width, bounds.Width, true, true);
150 // Creates a component from a ToolboxItem, sets its location and size if available and snaps it's
151 // location to the grid.
153 protected virtual IComponent[] CreateToolCore (ToolboxItem tool, int x, int y, int width, int height,
154 bool hasLocation, bool hasSize)
156 if (tool == null)
157 throw new ArgumentNullException ("tool");
159 IDesignerHost host = GetService (typeof (IDesignerHost)) as IDesignerHost;
160 DesignerTransaction transaction = host.CreateTransaction ("Create components in tool '" + tool.DisplayName + "'");
161 IComponent[] components = tool.CreateComponents (host);
163 foreach (IComponent component in components)
165 ControlDesigner controlDesigner = host.GetDesigner (component) as ControlDesigner;
166 if (controlDesigner == null) { // not a Control, but e.g. a plain Component
167 continue;
168 } else if (!this.CanParent (controlDesigner)) {
169 host.DestroyComponent (component);
170 continue;
173 Control control = component as Control;
174 if (control != null) {
175 this.Control.SuspendLayout ();
176 // set parent instead of controls.Add so that it gets serialized for Undo/Redo
177 TypeDescriptor.GetProperties (control)["Parent"].SetValue (control, this.Control);
178 this.Control.SuspendLayout ();
180 if (hasLocation)
181 base.SetValue (component, "Location", this.SnapPointToGrid (new Point (x, y)));
182 else
183 base.SetValue (component, "Location", this.SnapPointToGrid (this.DefaultControlLocation));
185 if (hasSize)
186 base.SetValue (component, "Size", new Size (width, height));
188 this.Control.Refresh ();
191 ISelectionService selectionServ = this.GetService (typeof (ISelectionService)) as ISelectionService;
192 if (selectionServ != null)
193 selectionServ.SetSelectedComponents (components, SelectionTypes.Replace);
194 transaction.Commit ();
195 return components;
198 #endregion
201 #region Drag and Drop
203 // If the control is not already parented return true
205 public virtual bool CanParent (Control control)
207 if (control != null)
208 return !control.Contains (this.Control);
210 return false;
213 public virtual bool CanParent (ControlDesigner controlDesigner)
215 return CanParent (controlDesigner.Control);
218 protected override void OnDragDrop (DragEventArgs de)
220 IUISelectionService selectionServ = this.GetService (typeof (IUISelectionService)) as IUISelectionService;
221 if (selectionServ != null) {
222 // once this is fired the parent control (parentcontroldesigner) will start getting dragover events.
224 Point location = this.SnapPointToGrid (this.Control.PointToClient (new Point (de.X, de.Y)));
225 selectionServ.DragDrop (false, this.Control, location.X, location.Y);
229 protected override void OnDragEnter (DragEventArgs de)
231 this.Control.Refresh ();
234 protected override void OnDragLeave (EventArgs e)
236 this.Control.Refresh ();
239 protected override void OnDragOver (DragEventArgs de)
241 IUISelectionService selectionServ = this.GetService (typeof (IUISelectionService)) as IUISelectionService;
242 if (selectionServ != null) {
243 // once ControlDesigner.MouseDragBegin is called this will start getting dragover events.
245 Point location = this.SnapPointToGrid (this.Control.PointToClient (new Point (de.X, de.Y)));
246 selectionServ.DragOver (this.Control, location.X, location.Y);
248 de.Effect = DragDropEffects.Move;
250 #endregion
253 #region Properties
254 // The default location where a control is placed, when added to the designer
256 protected virtual Point DefaultControlLocation {
257 get { return new Point (0, 0); }
261 protected override bool EnableDragRect {
262 get { return true; }
264 #endregion
266 #region ComponentChange
268 private void OnComponentRemoving (object sender, ComponentEventArgs args)
270 IComponentChangeService componentChangeSvc = GetService (typeof (IComponentChangeService)) as IComponentChangeService;
271 Control control = args.Component as Control;
272 if (control != null && control.Parent == this.Control && componentChangeSvc != null)
273 componentChangeSvc.OnComponentChanging (args.Component, TypeDescriptor.GetProperties (args.Component)["Parent"]);
276 private void OnComponentRemoved (object sender, ComponentEventArgs args)
278 IComponentChangeService componentChangeSvc = GetService (typeof (IComponentChangeService)) as IComponentChangeService;
279 Control control = args.Component as Control;
280 if (control != null && control.Parent == this.Control && componentChangeSvc != null) {
281 control.Parent = null;
282 componentChangeSvc.OnComponentChanged (args.Component,
283 TypeDescriptor.GetProperties (args.Component)["Parent"],
284 this.Control, null);
287 #endregion
289 #region Design-Time Properties
291 private bool _defaultDrawGrid;
292 private bool _defaultSnapToGrid;
293 private Size _defaultGridSize;
294 private bool _drawGrid;
295 private bool _snapToGrid;
296 private Size _gridSize;
298 //This method adds the following design-time browsable properties:
299 // "DrawGrid", "SnapToGrid", and "GridSize".
301 protected override void PreFilterProperties (IDictionary properties)
303 base.PreFilterProperties (properties);
305 properties["DrawGrid"] = TypeDescriptor.CreateProperty (typeof (ParentControlDesigner),
306 "DrawGrid",
307 typeof (bool),
308 new Attribute[] {
309 BrowsableAttribute.Yes,
310 DesignOnlyAttribute.Yes,
311 new DescriptionAttribute (
312 "Indicates whether or not to draw the positioning grid."),
313 CategoryAttribute.Design
316 properties["SnapToGrid"] = TypeDescriptor.CreateProperty (typeof (ParentControlDesigner),
317 "SnapToGrid",
318 typeof (bool),
319 new Attribute[] {
320 BrowsableAttribute.Yes,
321 DesignOnlyAttribute.Yes,
322 new DescriptionAttribute (
323 "Determines if controls should snap to the positioning grid."),
324 CategoryAttribute.Design
327 properties["GridSize"] = TypeDescriptor.CreateProperty (typeof (ParentControlDesigner),
328 "GridSize",
329 typeof (Size),
330 new Attribute[] {
331 BrowsableAttribute.Yes,
332 DesignOnlyAttribute.Yes,
333 new DescriptionAttribute (
334 "Determines the size of the positioning grid."),
335 CategoryAttribute.Design
341 // Informs all children controls' ParentControlDesigners that the grid properties
342 // have changed and passes them
344 private void PopulateGridProperties ()
346 // Control.Invalidate (true) will redraw the control and it's children
347 // this will cause a WM_PAINT message to be send and the ControlDesigenr will raise
348 // the OnPaintAdornments, where the grid drawing takes place.
350 // Note that this should be called *after* the grid properties have changed :-)
352 this.Control.Invalidate (false);
354 if (this.Control != null) {
355 ParentControlDesigner designer = null;
356 foreach (Control control in this.Control.Controls) {
357 designer = this.GetParentControlDesignerOf (control);
358 if (designer != null)
359 designer.OnParentGridPropertiesChanged (this);
364 // Called by the parent ParentControlDesigner when it is populating the grid-related
365 // design-time properties changes
367 private void OnParentGridPropertiesChanged (ParentControlDesigner parentDesigner)
369 SetValue (this.Component, "DrawGrid", (bool) GetValue (parentDesigner.Component, "DrawGrid"));
370 SetValue (this.Component, "SnapToGrid", (bool) GetValue (parentDesigner.Component, "SnapToGrid"));
371 SetValue (this.Component, "GridSize", (Size) GetValue (parentDesigner.Component, "GridSize"));
373 // Set also the default values to be those, because we should
374 // match the parent ParentControlDesigner values.
375 // called recursivly, so I will rather go for slower, but no stack-overflowable code
377 _defaultDrawGrid = (bool) GetValue (parentDesigner.Component, "DrawGrid");
378 _defaultSnapToGrid = (bool) GetValue (parentDesigner.Component, "SnapToGrid");
379 _defaultGridSize = (Size) GetValue (parentDesigner.Component, "GridSize");
381 this.PopulateGridProperties ();
385 // Retrieves the ParentControlDesigner of the specified control if available,
386 // else returns null.
388 private ParentControlDesigner GetParentControlDesignerOf (Control control)
390 if (control != null) {
391 IDesignerHost designerHost = GetService (typeof (IDesignerHost)) as IDesignerHost;
392 if (designerHost != null) {
393 ParentControlDesigner designer = null;
394 designer = designerHost.GetDesigner (this.Control.Parent) as ParentControlDesigner;
395 if (designer != null)
396 return designer;
399 return null;
402 protected virtual bool DrawGrid {
403 get { return _drawGrid; }
404 set {
405 _drawGrid = value;
407 if (value == false)
408 SetValue (this.Component, "SnapToGrid", false);
410 PopulateGridProperties ();
414 private bool SnapToGrid {
415 get { return _snapToGrid; }
416 set {
417 _snapToGrid = value;
418 PopulateGridProperties ();
422 protected Size GridSize {
423 get { return _gridSize; }
424 set {
425 _gridSize = value;
426 PopulateGridProperties ();
430 // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconshouldpersistresetmethods.asp
432 // The ShouldSerializerPROPERTYNAME determines whether a property has changed from
433 // the default value and should get serialized.
435 // The ResetPROPERTYNAME resets the property to it's default value (used when
436 // one right clicks on a property in the property grid and clicks on "Reset".
439 private bool ShouldSerializeDrawGrid ()
441 return DrawGrid != _defaultDrawGrid;
444 private void ResetDrawGrid ()
446 this.DrawGrid = _defaultDrawGrid;
449 private bool ShouldSerializeSnapToGrid ()
451 return _drawGrid != _defaultDrawGrid;
454 private void ResetSnapToGrid ()
456 this.SnapToGrid = _defaultSnapToGrid;
459 private bool ShouldSerializeGridSize ()
461 return GridSize != _defaultGridSize;
464 private void ResetGridSize ()
466 this.GridSize = _defaultGridSize;
468 #endregion
471 #region Design-Time Mouse Drag and Drop
472 protected override void OnMouseDragBegin (int x, int y)
474 // do not call base here because the behaviour is specific for the ControlDesgner (does IUISelectionService.DragBegin)
477 IUISelectionService selectionServ = this.GetService (typeof (IUISelectionService)) as IUISelectionService;
478 if (selectionServ != null) {
479 // once ControlDesigner.MouseDragBegin is fired this will start getting dragover events.
481 Point location = new Point (x, y);
482 IDesignerHost host = GetService (typeof (IDesignerHost)) as IDesignerHost;
483 if (base.MouseButtonDown == MouseButtons.Middle && host != null && host.RootComponent != this.Control) {
484 location = this.Control.Parent.PointToClient (this.Control.PointToScreen (new Point (x, y)));
485 // I have to do this, because I get DragOver events fired for the control I am actually dragging
487 this.Control.AllowDrop = false;
488 selectionServ.DragBegin ();
490 else {
491 selectionServ.MouseDragBegin (this.Control, location.X, location.Y);
496 protected override void OnMouseDragMove (int x, int y)
498 IUISelectionService selectionServ = this.GetService (typeof (IUISelectionService)) as IUISelectionService;
499 if (selectionServ != null) {
500 Point location = new Point (x, y);
501 if (!selectionServ.SelectionInProgress)
502 location = this.SnapPointToGrid (new Point (x, y));
504 selectionServ.MouseDragMove (location.X, location.Y);
508 protected override void OnMouseDragEnd (bool cancel)
510 IUISelectionService selectionServ = this.GetService (typeof (IUISelectionService)) as IUISelectionService;
511 if (selectionServ != null) {
512 // If there is a Toolbox component seleted then create it instead of finishing the selection
513 IToolboxService toolBoxService = this.GetService (typeof (IToolboxService)) as IToolboxService;
514 if (!cancel && toolBoxService != null && toolBoxService.GetSelectedToolboxItem () != null) {
515 if (selectionServ.SelectionInProgress) {
516 bool hasSize = selectionServ.SelectionBounds.Width > 0 &&
517 selectionServ.SelectionBounds.Height > 0;
518 CreateToolCore (toolBoxService.GetSelectedToolboxItem (),
519 selectionServ.SelectionBounds.X,
520 selectionServ.SelectionBounds.Y,
521 selectionServ.SelectionBounds.Width,
522 selectionServ.SelectionBounds.Height,
523 true, hasSize);
524 toolBoxService.SelectedToolboxItemUsed ();
525 cancel = true;
526 } else if (!selectionServ.SelectionInProgress &&
527 !selectionServ.ResizeInProgress && !selectionServ.DragDropInProgress){
528 CreateTool (toolBoxService.GetSelectedToolboxItem (), _mouseDownPoint);
529 toolBoxService.SelectedToolboxItemUsed ();
530 cancel = true;
534 if (selectionServ.SelectionInProgress || selectionServ.ResizeInProgress)
535 selectionServ.MouseDragEnd (cancel);
539 protected override void OnDragComplete (DragEventArgs de)
541 base.OnDragComplete (de);
544 Point _mouseDownPoint = Point.Empty;
546 internal override void OnMouseDown (int x, int y)
548 _mouseDownPoint.X = x;
549 _mouseDownPoint.Y = y;
550 base.OnMouseDown (x, y);
553 internal override void OnMouseUp ()
555 base.OnMouseUp ();
556 if (!this.Control.AllowDrop) // check MouseDragBegin for the reason of having this
557 this.Control.AllowDrop = true;
558 _mouseDownPoint = Point.Empty;
561 internal override void OnMouseMove (int x, int y)
563 IUISelectionService uiSelection = this.GetService (typeof (IUISelectionService)) as IUISelectionService;
564 if (uiSelection != null)
565 uiSelection.SetCursor (x, y);
567 base.OnMouseMove (x, y);
570 // Align the point to the grid
572 private Point SnapPointToGrid (Point location)
574 Rectangle gridSurface = this.Control.Bounds;
575 Size gridSize = (Size)GetValue (this.Component, "GridSize");
577 if ((bool)GetValue (this.Component, "SnapToGrid")) {
578 int x = location.X + (gridSize.Width - (location.X % gridSize.Width));
579 if (x > gridSurface.Width)
580 x = gridSurface.Width - gridSize.Width;
582 location.X = x;
584 int y = location.Y + (gridSize.Height - (location.Y % gridSize.Height));
585 if (y > gridSurface.Height)
586 y = gridSurface.Height - gridSize.Height;
588 location.Y = y;
590 return location;
593 #endregion
596 #region WndProc and Misc Message Handlers
598 protected override void OnSetCursor ()
600 if (this.Control != null) {
601 IToolboxService tbService = GetService (typeof (IToolboxService)) as IToolboxService;
602 if (tbService != null)
603 tbService.SetCursor ();
604 else
605 base.OnSetCursor ();
609 // Draws the design-time grid if DrawGrid == true
611 protected override void OnPaintAdornments (PaintEventArgs pe)
613 base.OnPaintAdornments (pe);
615 bool drawGrid;
616 Size gridSize;
618 // in case WM_PAINT is received before the IDesignerFilter is invoked to add
619 // those properties.
620 try {
621 drawGrid = (bool)GetValue (this.Component, "DrawGrid");
622 } catch {
623 drawGrid = this.DrawGrid;
625 try {
626 gridSize = (Size)GetValue (this.Component, "GridSize");
627 } catch {
628 gridSize = this.GridSize;
631 if (drawGrid) {
632 GraphicsState state = pe.Graphics.Save ();
633 pe.Graphics.TranslateTransform (this.Control.ClientRectangle.X,
634 this.Control.ClientRectangle.Y);
635 ControlPaint.DrawGrid (pe.Graphics, this.Control.ClientRectangle, gridSize, this.Control.BackColor);
636 pe.Graphics.Restore (state);
639 IUISelectionService selection = this.GetService (typeof (IUISelectionService)) as IUISelectionService;
640 if (selection != null)
641 selection.PaintAdornments (this.Control, pe.Graphics);
644 #endregion
647 protected Control GetControl (object component)
649 IComponent comp = component as IComponent;
651 if (comp != null && comp.Site != null) {
652 IDesignerHost host = comp.Site.GetService (typeof (IDesignerHost)) as IDesignerHost;
653 if (host != null) {
654 ControlDesigner designer = host.GetDesigner (comp) as ControlDesigner;
655 if (designer != null)
656 return designer.Control;
659 return null;
662 #region NET_2_0 Stubs
663 [MonoTODO]
664 protected virtual bool AllowControlLasso {
665 get { return false; }
668 [MonoTODO]
669 protected virtual bool AllowGenericDragBox {
670 get { return false; }
673 [MonoTODO]
674 protected internal virtual bool AllowSetChildIndexOnDrop {
675 get { return false; }
678 [MonoTODO]
679 public override IList SnapLines {
680 get { return new object [0]; }
683 [MonoTODO]
684 protected ToolboxItem MouseDragTool {
685 get { return null; }
688 [MonoTODO]
689 public override void InitializeNewComponent (IDictionary defaultValues)
691 base.InitializeNewComponent (defaultValues);
694 [MonoTODO]
695 protected void AddPaddingSnapLines (ref ArrayList snapLines)
697 throw new NotImplementedException ();
700 [MonoTODO]
701 protected virtual Control GetParentForComponent (IComponent component)
703 throw new NotImplementedException ();
706 [MonoTODO]
707 protected override ControlBodyGlyph GetControlGlyph (GlyphSelectionType selectionType)
709 return base.GetControlGlyph (selectionType);
712 [MonoTODO]
713 public override GlyphCollection GetGlyphs (GlyphSelectionType selectionType)
715 return base.GetGlyphs (selectionType);
718 [MonoTODO]
719 protected Rectangle GetUpdatedRect (Rectangle originalRect, Rectangle dragRect, bool updateSize)
721 throw new NotImplementedException ();
723 #endregion