Merge pull request #2057 from directhex/monolite-on-jenkins
[mono.git] / mcs / class / System.Windows.Forms / System.Windows.Forms / ToolStripPanel.cs
1 //
2 // ToolStripPanel.cs
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the
6 // "Software"), to deal in the Software without restriction, including
7 // without limitation the rights to use, copy, modify, merge, publish,
8 // distribute, sublicense, and/or sell copies of the Software, and to
9 // permit persons to whom the Software is furnished to do so, subject to
10 // the following conditions:
11 // 
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
14 // 
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 //
23 // Copyright (c) 2006 Jonathan Pobst
24 //
25 // Authors:
26 //      Jonathan Pobst (monkey@jpobst.com)
27 //
28
29
30 using System.Collections;
31 using System.ComponentModel;
32 using System.Drawing;
33 using System.Runtime.InteropServices;
34 using System.Windows.Forms.Layout;
35
36 namespace System.Windows.Forms
37 {
38         [ComVisible (true)]
39         [ToolboxBitmap ("")]
40         [ClassInterface (ClassInterfaceType.AutoDispatch)]
41         [Designer ("System.Windows.Forms.Design.ToolStripPanelDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
42         public class ToolStripPanel : ContainerControl, IComponent, IDisposable, IBindableComponent, IDropTarget
43         {
44                 private bool done_first_layout;
45                 private LayoutEngine layout_engine;
46                 private bool locked;
47                 private Orientation orientation;
48                 private ToolStripRenderer renderer;
49                 private ToolStripRenderMode render_mode;
50                 private Padding row_margin;
51                 private ToolStripPanelRowCollection rows;
52                 
53                 public ToolStripPanel () : base ()
54                 {
55                         base.AutoSize = true;
56                         this.locked = false;
57                         this.renderer = null;
58                         this.render_mode = ToolStripRenderMode.ManagerRenderMode;
59                         this.row_margin = new Padding (3, 0, 0, 0);
60                         this.rows = new ToolStripPanelRowCollection (this);
61                 }
62
63                 #region Public Properties
64                 [Browsable (false)]
65                 [EditorBrowsable (EditorBrowsableState.Never)]
66                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
67                 public override bool AllowDrop {
68                         get { return base.AllowDrop; }
69                         set { base.AllowDrop = value; }
70                 }
71                 
72                 [Browsable (false)]
73                 [EditorBrowsable (EditorBrowsableState.Never)]
74                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
75                 public override bool AutoScroll {
76                         get { return base.AutoScroll; }
77                         set { base.AutoScroll = value; }
78                 }
79                 
80                 [Browsable (false)]
81                 [EditorBrowsable (EditorBrowsableState.Never)]
82                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
83                 public new Size AutoScrollMargin {
84                         get { return base.AutoScrollMargin; }
85                         set { base.AutoScrollMargin = value; }
86                 }
87
88                 [Browsable (false)]
89                 [EditorBrowsable (EditorBrowsableState.Never)]
90                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
91                 public new Size AutoScrollMinSize {
92                         get { return base.AutoScrollMinSize; }
93                         set { base.AutoScrollMinSize = value; }
94                 }
95
96                 [DefaultValue (true)]
97                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Visible)]
98                 public override bool AutoSize {
99                         get { return base.AutoSize; }
100                         set { base.AutoSize = value; }
101                 }
102
103                 public override DockStyle Dock {
104                         get { return base.Dock; }
105                         set {
106                                 base.Dock = value;
107
108                                 switch (value) {
109                                         case DockStyle.Top:
110                                         case DockStyle.Bottom:
111                                         case DockStyle.None:
112                                                 this.orientation = Orientation.Horizontal;
113                                                 break;
114                                         case DockStyle.Left:
115                                         case DockStyle.Right:
116                                                 this.orientation = Orientation.Vertical;
117                                                 break;
118                                 }
119                         }
120                 }
121
122                 public override LayoutEngine LayoutEngine {
123                         get { 
124                                 if (this.layout_engine == null)
125                                         this.layout_engine = new FlowLayout ();
126                                         
127                                 return this.layout_engine;
128                         }
129                 }
130
131                 [Browsable (false)]
132                 [DefaultValue (false)]
133                 [EditorBrowsable (EditorBrowsableState.Advanced)]
134                 public bool Locked {
135                         get { return this.locked; }
136                         set { this.locked = value; }
137                 }
138
139                 public Orientation Orientation {
140                         get { return this.orientation; }
141                         set { this.orientation = value; }
142                 }
143
144                 [Browsable (false)]
145                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
146                 public ToolStripRenderer Renderer {
147                         get {
148                                 if (this.render_mode == ToolStripRenderMode.ManagerRenderMode)
149                                         return ToolStripManager.Renderer;
150
151                                 return this.renderer;
152                         }
153                         set {
154                                 if (this.renderer != value) {
155                                         this.renderer = value;
156                                         this.render_mode = ToolStripRenderMode.Custom;
157                                         this.OnRendererChanged (EventArgs.Empty);
158                                 }
159                         }
160                 }
161
162                 public ToolStripRenderMode RenderMode {
163                         get { return this.render_mode; }
164                         set {
165                                 if (!Enum.IsDefined (typeof (ToolStripRenderMode), value))
166                                         throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ToolStripRenderMode", value));
167
168                                 if (value == ToolStripRenderMode.Custom && this.renderer == null)
169                                         throw new NotSupportedException ("Must set Renderer property before setting RenderMode to Custom");
170                                 if (value == ToolStripRenderMode.Professional || value == ToolStripRenderMode.System)
171                                         this.Renderer = new ToolStripProfessionalRenderer ();
172
173                                 this.render_mode = value;
174                         }
175                 }
176                 
177                 public Padding RowMargin {
178                         get { return this.row_margin; }
179                         set { this.row_margin = value; }
180                 }
181
182                 [Browsable (false)]
183                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
184                 public ToolStripPanelRow[] Rows {
185                         get { 
186                                 ToolStripPanelRow[] retval = new ToolStripPanelRow [this.rows.Count];
187                                 this.rows.CopyTo (retval, 0); 
188                                 return retval;  
189                         }
190                 }
191
192                 [Browsable (false)]
193                 [EditorBrowsable (EditorBrowsableState.Never)]
194                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
195                 public new int TabIndex {
196                         get { return base.TabIndex; }
197                         set { base.TabIndex = value; }
198                 }
199
200                 [Browsable (false)]
201                 [EditorBrowsable (EditorBrowsableState.Never)]
202                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
203                 public new bool TabStop {
204                         get { return base.TabStop; }
205                         set { base.TabStop = value; }
206                 }
207
208                 [Browsable (false)]
209                 [EditorBrowsable (EditorBrowsableState.Never)]
210                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
211                 public override string Text {
212                         get { return base.Text; }
213                         set { base.Text = value; }
214                 }
215                 #endregion
216
217                 #region Protected Properties
218                 protected override Padding DefaultMargin {
219                         get { return new Padding (0); }
220                 }
221
222                 protected override Padding DefaultPadding {
223                         get { return new Padding (0); }
224                 }
225                 #endregion
226
227                 #region Public Methods
228                 public void BeginInit ()
229                 {
230                 }
231                 
232                 public void EndInit ()
233                 {
234                 }
235
236                 [MonoTODO("Not implemented")]
237                 public void Join (ToolStrip toolStripToDrag)
238                 {
239                         if (!Contains (toolStripToDrag))
240                                 Controls.Add (toolStripToDrag);
241                 }
242
243                 [MonoTODO("Not implemented")]
244                 public void Join (ToolStrip toolStripToDrag, int row)
245                 {
246                         Join (toolStripToDrag);
247                 }
248
249                 [MonoTODO("Not implemented")]
250                 public void Join (ToolStrip toolStripToDrag, Point location)
251                 {
252                         Join (toolStripToDrag);
253                 }
254
255                 [MonoTODO("Not implemented")]
256                 public void Join (ToolStrip toolStripToDrag, int x, int y)
257                 {
258                         Join (toolStripToDrag);
259                 }
260                 
261                 public ToolStripPanelRow PointToRow (Point clientLocation)
262                 {
263                         foreach (ToolStripPanelRow row in this.rows)
264                                 if (row.Bounds.Contains (clientLocation))
265                                         return row;
266                                         
267                         return null;
268                 }
269                 #endregion
270
271                 #region Protected Methods
272                 protected override ControlCollection CreateControlsInstance ()
273                 {
274                         return new ToolStripPanelControlCollection (this);
275                 }
276                 
277                 protected override void Dispose (bool disposing)
278                 {
279                         base.Dispose (disposing);
280                 }
281
282                 protected override void OnControlAdded (ControlEventArgs e)
283                 {
284                         if (this.Dock == DockStyle.Left || this.Dock == DockStyle.Right)
285                                 (e.Control as ToolStrip).LayoutStyle = ToolStripLayoutStyle.VerticalStackWithOverflow;
286                         else
287                                 (e.Control as ToolStrip).LayoutStyle = ToolStripLayoutStyle.HorizontalStackWithOverflow;
288                         
289                         if (done_first_layout && e.Control is ToolStrip)
290                                 this.AddControlToRows (e.Control);
291                         
292                         base.OnControlAdded (e);
293                 }
294
295                 protected override void OnControlRemoved (ControlEventArgs e)
296                 {
297                         base.OnControlRemoved (e);
298                         
299                         foreach (ToolStripPanelRow row in this.rows)
300                                 if (row.controls.Contains (e.Control))
301                                         row.OnControlRemoved (e.Control, 0);
302                 }
303
304                 protected override void OnDockChanged (EventArgs e)
305                 {
306                         base.OnDockChanged (e);
307                 }
308                 
309                 protected override void OnLayout (LayoutEventArgs e)
310                 {
311                         // Don't see any reason to layout if we aren't created
312                         if (!this.Created)
313                                 return;
314                                 
315                         // The first time through, we have to layout everything where it belongs.
316                         // The key is that when we resize and stuff, we don't resize or move toolstrips.
317                         if (!done_first_layout) {
318                                 ArrayList al = new ArrayList (this.Controls);
319                                 al.Sort (new TabIndexComparer ());
320                                 
321                                 foreach (ToolStrip ts in al)
322                                         this.AddControlToRows (ts);
323                                         
324                                 done_first_layout = true;
325                         }
326                         
327                         // Lay out all the rows
328                         Point position = this.DisplayRectangle.Location;
329
330                         if (this.Dock == DockStyle.Left || this.Dock == DockStyle.Right) {
331                                 foreach (ToolStripPanelRow row in this.rows) {
332                                         row.SetBounds (new Rectangle (position, new Size (row.Bounds.Width, this.Height)));
333
334                                         position.X += row.Bounds.Width;
335                                 }
336
337                                 // Find how big we are so we can autosize ourself
338                                 if (this.rows.Count > 0) {
339                                         int last_row_right = this.rows[this.rows.Count - 1].Bounds.Right;
340
341                                         if (last_row_right != this.Width)
342                                                 this.SetBounds (bounds.X, bounds.Y, last_row_right, bounds.Bottom);
343                                 }
344                         } else {
345                                 foreach (ToolStripPanelRow row in this.rows) {
346                                         row.SetBounds (new Rectangle (position, new Size (this.Width, row.Bounds.Height)));
347
348                                         position.Y += row.Bounds.Height;
349                                 }
350
351                                 // Find how big we are so we can autosize ourself
352                                 if (this.rows.Count > 0) {
353                                         int last_row_bottom = this.rows[this.rows.Count - 1].Bounds.Bottom;
354                                 
355                                         if (last_row_bottom != this.Height)
356                                                 this.SetBounds (bounds.X, bounds.Y, bounds.Width, last_row_bottom);
357                                 }
358                         }
359                         
360                         this.Invalidate ();
361                         
362                         return;
363                 }
364
365                 [EditorBrowsable (EditorBrowsableState.Advanced)]
366                 protected override void OnPaintBackground (PaintEventArgs e)
367                 {
368                         base.OnPaintBackground (e);
369
370                         this.Renderer.DrawToolStripPanelBackground (new ToolStripPanelRenderEventArgs (e.Graphics, this));
371                 }
372
373                 protected override void OnParentChanged (EventArgs e)
374                 {
375                         base.OnParentChanged (e);
376                 }
377                 
378                 protected virtual void OnRendererChanged (EventArgs e)
379                 {
380                         EventHandler eh = (EventHandler)(Events [RendererChangedEvent]);
381                         if (eh != null)
382                                 eh (this, e);
383                 }
384
385                 protected override void OnRightToLeftChanged (EventArgs e)
386                 {
387                         base.OnRightToLeftChanged (e);
388                 }
389                 #endregion
390
391                 #region Public Events
392                 static object RendererChangedEvent = new object ();
393
394                 [Browsable (true)]
395                 [EditorBrowsable (EditorBrowsableState.Always)]
396                 public new event EventHandler AutoSizeChanged {
397                         add { base.AutoSizeChanged += value; }
398                         remove { base.AutoSizeChanged -= value; }
399                 }
400
401                 public event EventHandler RendererChanged {
402                         add { Events.AddHandler (RendererChangedEvent, value); }
403                         remove { Events.RemoveHandler (RendererChangedEvent, value); }
404                 }
405
406                 [Browsable (false)]
407                 [EditorBrowsable (EditorBrowsableState.Never)]
408                 public new event EventHandler TabIndexChanged {
409                         add { base.TabIndexChanged += value; }
410                         remove { base.TabIndexChanged -= value; }
411                 }
412
413                 [Browsable (false)]
414                 [EditorBrowsable (EditorBrowsableState.Never)]
415                 public new event EventHandler TabStopChanged {
416                         add { base.TabStopChanged += value; }
417                         remove { base.TabStopChanged -= value; }
418                 }
419
420                 [Browsable (false)]
421                 [EditorBrowsable (EditorBrowsableState.Never)]
422                 public new event EventHandler TextChanged {
423                         add { base.TextChanged += value; }
424                         remove { base.TextChanged -= value; }
425                 }
426                 #endregion
427
428                 #region Private Methods
429
430                 private void AddControlToRows (Control control)
431                 {
432                         if (this.rows.Count > 0)
433                                 if (this.rows[this.rows.Count - 1].CanMove ((ToolStrip)control)) {
434                                         this.rows[this.rows.Count - 1].OnControlAdded (control, 0);
435                                         return;
436                                 }
437
438                         ToolStripPanelRow new_row = new ToolStripPanelRow (this);
439                         
440                         if (this.Dock == DockStyle.Left || this.Dock == DockStyle.Right)
441                                 new_row.SetBounds (new Rectangle (0, 0, 25, this.Height));
442                         else
443                                 new_row.SetBounds (new Rectangle (0, 0, this.Width, 25));
444                                 
445                         this.rows.Add (new_row);
446                         new_row.OnControlAdded (control, 0);
447                 }
448                 /*
449                 private Region FindBackgroundRegion ()
450                 {
451                         Region r = new Region (this.Bounds);
452
453                         foreach (Control c in this.Controls)
454                                 r.Exclude (c.Bounds);
455
456                         return r;
457                 }
458                 */
459                 #endregion
460
461                 #region Nested Classes
462                 [ComVisible (false)]
463                 [ListBindable (false)]
464                 public class ToolStripPanelRowCollection : ArrangedElementCollection, IList, ICollection, IEnumerable
465                 {
466                         //private ToolStripPanel owner;
467                         
468                         public ToolStripPanelRowCollection (ToolStripPanel owner) : base ()
469                         {
470                                 //this.owner = owner;
471                         }
472                         
473                         public ToolStripPanelRowCollection (ToolStripPanel owner, ToolStripPanelRow[] value) : this (owner)
474                         {
475                                 if (value != null)
476                                         foreach (ToolStripPanelRow tspr in value)
477                                                 this.Add (tspr);
478                         }
479                         
480                         public new virtual ToolStripPanelRow this [int index] {
481                                 get { return (ToolStripPanelRow)base[index]; }
482                         }
483
484                         #region Public Methods
485                         public int Add (ToolStripPanelRow value)
486                         {
487                                 return base.Add (value);
488                         }
489                         
490                         public void AddRange (ToolStripPanelRowCollection value)
491                         {
492                                 if (value == null)
493                                         throw new ArgumentNullException ("value");
494
495                                 foreach (ToolStripPanelRow tspr in value)
496                                         this.Add (tspr);
497                         }
498                         
499                         public void AddRange (ToolStripPanelRow[] value)
500                         {
501                                 if (value == null)
502                                         throw new ArgumentNullException ("value");
503
504                                 foreach (ToolStripPanelRow tspr in value)
505                                         this.Add (tspr);
506                         }
507                         
508                         public new virtual void Clear ()
509                         {
510                                 base.Clear ();
511                         }
512                         
513                         public bool Contains (ToolStripPanelRow value)
514                         {
515                                 return base.Contains (value);
516                         }
517                         
518                         public void CopyTo (ToolStripPanelRow[] array, int index)
519                         {
520                                 base.CopyTo (array, index);
521                         }
522                         
523                         public int IndexOf (ToolStripPanelRow value)
524                         {
525                                 return base.IndexOf (value);
526                         }
527                         
528                         public void Insert (int index, ToolStripPanelRow value)
529                         {
530                                 base.Insert (index, value);
531                         }
532                         
533                         public void Remove (ToolStripPanelRow value)
534                         {
535                                 base.Remove (value);
536                         }
537                         
538                         public void RemoveAt (int index)
539                         {
540                                 base.InternalRemoveAt (index);
541                         }
542                         #endregion
543
544                         #region IList Members
545                         object IList.this [int index] {
546                                 get { return this [index]; }
547                                 [MonoTODO ("Stub, does nothing")]
548                                 set { }
549                         }
550
551                         bool IList.IsFixedSize {
552                                 get { return IsFixedSize; }
553                         }
554
555                         bool IList.IsReadOnly {
556                                 get { return IsReadOnly; }
557                         }
558
559                         int IList.Add (object value)
560                         {
561                                 return Add (value as ToolStripPanelRow);
562                         }
563
564                         void IList.Clear ()
565                         {
566                                 Clear ();
567                         }
568
569                         bool IList.Contains (object value)
570                         {
571                                 return Contains (value as ToolStripPanelRow);
572                         }
573
574                         int IList.IndexOf (object value)
575                         {
576                                 return IndexOf (value as ToolStripPanelRow);
577                         }
578
579                         void IList.Insert (int index, object value)
580                         {
581                                 Insert (index, value as ToolStripPanelRow);
582                         }
583
584                         void IList.Remove (object value)
585                         {
586                                 Remove (value as ToolStripPanelRow);
587                         }
588
589                         void IList.RemoveAt (int index)
590                         {
591                                 base.InternalRemoveAt (index);
592                         }
593                         #endregion
594                 }
595                 
596                 private class ToolStripPanelControlCollection : ControlCollection
597                 {
598                         public ToolStripPanelControlCollection (Control owner) : base (owner)
599                         {
600                         }
601                 }
602
603                 private class TabIndexComparer : IComparer
604                 {
605                         #region IComparer Members
606                         public int Compare (object x, object y)
607                         {
608                                 if (!(x is Control) || !(y is Control))
609                                         throw new ArgumentException ();
610
611                                 return (x as Control).TabIndex - (y as Control).TabIndex;
612                         }
613                         #endregion
614                 }
615                 #endregion
616         }
617 }