2008-03-27 Carlos Alberto Cortez <calberto.cortez@gmail.com>
[mono.git] / mcs / class / Managed.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 #if NET_2_0     
30 using System.Drawing;
31 using System.Runtime.InteropServices;
32 using System.ComponentModel;
33 using System.Windows.Forms.Layout;
34 using System.Collections;
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                 void IDropTarget.OnDragDrop (DragEventArgs e)
430                 {
431                         throw new NotImplementedException ();
432                 }
433
434                 void IDropTarget.OnDragEnter (DragEventArgs e)
435                 {
436                         throw new NotImplementedException ();
437                 }
438
439                 void IDropTarget.OnDragLeave (EventArgs e)
440                 {
441                         throw new NotImplementedException ();
442                 }
443
444                 void IDropTarget.OnDragOver (DragEventArgs e)
445                 {
446                         throw new NotImplementedException ();
447                 }
448
449                 private void AddControlToRows (Control control)
450                 {
451                         if (this.rows.Count > 0)
452                                 if (this.rows[this.rows.Count - 1].CanMove ((ToolStrip)control)) {
453                                         this.rows[this.rows.Count - 1].OnControlAdded (control, 0);
454                                         return;
455                                 }
456
457                         ToolStripPanelRow new_row = new ToolStripPanelRow (this);
458                         
459                         if (this.Dock == DockStyle.Left || this.Dock == DockStyle.Right)
460                                 new_row.SetBounds (new Rectangle (0, 0, 25, this.Height));
461                         else
462                                 new_row.SetBounds (new Rectangle (0, 0, this.Width, 25));
463                                 
464                         this.rows.Add (new_row);
465                         new_row.OnControlAdded (control, 0);
466                 }
467                 /*
468                 private Region FindBackgroundRegion ()
469                 {
470                         Region r = new Region (this.Bounds);
471
472                         foreach (Control c in this.Controls)
473                                 r.Exclude (c.Bounds);
474
475                         return r;
476                 }
477                 */
478                 #endregion
479
480                 #region Nested Classes
481                 [ComVisible (false)]
482                 [ListBindable (false)]
483                 public class ToolStripPanelRowCollection : ArrangedElementCollection, IList, ICollection, IEnumerable
484                 {
485                         //private ToolStripPanel owner;
486                         
487                         public ToolStripPanelRowCollection (ToolStripPanel owner) : base ()
488                         {
489                                 //this.owner = owner;
490                         }
491                         
492                         public ToolStripPanelRowCollection (ToolStripPanel owner, ToolStripPanelRow[] value) : this (owner)
493                         {
494                                 if (value != null)
495                                         foreach (ToolStripPanelRow tspr in value)
496                                                 this.Add (tspr);
497                         }
498                         
499                         public new virtual ToolStripPanelRow this [int index] {
500                                 get { return (ToolStripPanelRow)base[index]; }
501                         }
502
503                         #region Public Methods
504                         public int Add (ToolStripPanelRow value)
505                         {
506                                 return base.Add (value);
507                         }
508                         
509                         public void AddRange (ToolStripPanelRowCollection value)
510                         {
511                                 if (value == null)
512                                         throw new ArgumentNullException ("value");
513
514                                 foreach (ToolStripPanelRow tspr in value)
515                                         this.Add (tspr);
516                         }
517                         
518                         public void AddRange (ToolStripPanelRow[] value)
519                         {
520                                 if (value == null)
521                                         throw new ArgumentNullException ("value");
522
523                                 foreach (ToolStripPanelRow tspr in value)
524                                         this.Add (tspr);
525                         }
526                         
527                         public new virtual void Clear ()
528                         {
529                                 base.Clear ();
530                         }
531                         
532                         public bool Contains (ToolStripPanelRow value)
533                         {
534                                 return base.Contains (value);
535                         }
536                         
537                         public void CopyTo (ToolStripPanelRow[] array, int index)
538                         {
539                                 base.CopyTo (array, index);
540                         }
541                         
542                         public int IndexOf (ToolStripPanelRow value)
543                         {
544                                 return base.IndexOf (value);
545                         }
546                         
547                         public void Insert (int index, ToolStripPanelRow value)
548                         {
549                                 base.Insert (index, value);
550                         }
551                         
552                         public void Remove (ToolStripPanelRow value)
553                         {
554                                 base.Remove (value);
555                         }
556                         
557                         public void RemoveAt (int index)
558                         {
559                                 base.InternalRemoveAt (index);
560                         }
561                         #endregion
562
563                         #region IList Members
564                         void IList.RemoveAt (int index)
565                         {
566                                 base.InternalRemoveAt (index);
567                         }
568                         #endregion
569                 }
570                 
571                 private class ToolStripPanelControlCollection : ControlCollection
572                 {
573                         public ToolStripPanelControlCollection (Control owner) : base (owner)
574                         {
575                         }
576                 }
577
578                 private class TabIndexComparer : IComparer
579                 {
580                         #region IComparer Members
581                         public int Compare (object x, object y)
582                         {
583                                 if (!(x is Control) || !(y is Control))
584                                         throw new ArgumentException ();
585
586                                 return (x as Control).TabIndex - (y as Control).TabIndex;
587                         }
588                         #endregion
589                 }
590                 #endregion
591         }
592 }
593 #endif