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