2007-08-28 Jonathan Pobst <monkey@jpobst.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 { base.Dock = value; }
106                 }
107
108                 public override LayoutEngine LayoutEngine {
109                         get { 
110                                 if (this.layout_engine == null)
111                                         this.layout_engine = new FlowLayout ();
112                                         
113                                 return this.layout_engine;
114                         }
115                 }
116
117                 [Browsable (false)]
118                 [DefaultValue (false)]
119                 [EditorBrowsable (EditorBrowsableState.Advanced)]
120                 public bool Locked {
121                         get { return this.locked; }
122                         set { this.locked = value; }
123                 }
124
125                 public Orientation Orientation {
126                         get { return this.orientation; }
127                         set { this.orientation = value; }
128                 }
129
130                 [Browsable (false)]
131                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
132                 public ToolStripRenderer Renderer {
133                         get {
134                                 if (this.render_mode == ToolStripRenderMode.ManagerRenderMode)
135                                         return ToolStripManager.Renderer;
136
137                                 return this.renderer;
138                         }
139                         set {
140                                 if (this.renderer != value) {
141                                         this.renderer = value;
142                                         this.render_mode = ToolStripRenderMode.Custom;
143                                         this.OnRendererChanged (EventArgs.Empty);
144                                 }
145                         }
146                 }
147
148                 public ToolStripRenderMode RenderMode {
149                         get { return this.render_mode; }
150                         set {
151                                 if (!Enum.IsDefined (typeof (ToolStripRenderMode), value))
152                                         throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ToolStripRenderMode", value));
153
154                                 if (value == ToolStripRenderMode.Custom && this.renderer == null)
155                                         throw new NotSupportedException ("Must set Renderer property before setting RenderMode to Custom");
156                                 if (value == ToolStripRenderMode.Professional || value == ToolStripRenderMode.System)
157                                         this.Renderer = new ToolStripProfessionalRenderer ();
158
159                                 this.render_mode = value;
160                         }
161                 }
162                 
163                 public Padding RowMargin {
164                         get { return this.row_margin; }
165                         set { this.row_margin = value; }
166                 }
167
168                 [Browsable (false)]
169                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
170                 public ToolStripPanelRow[] Rows {
171                         get { 
172                                 ToolStripPanelRow[] retval = new ToolStripPanelRow [this.rows.Count];
173                                 this.rows.CopyTo (retval, 0); 
174                                 return retval;  
175                         }
176                 }
177
178                 [Browsable (false)]
179                 [EditorBrowsable (EditorBrowsableState.Never)]
180                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
181                 public new int TabIndex {
182                         get { return base.TabIndex; }
183                         set { base.TabIndex = value; }
184                 }
185
186                 [Browsable (false)]
187                 [EditorBrowsable (EditorBrowsableState.Never)]
188                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
189                 public new bool TabStop {
190                         get { return base.TabStop; }
191                         set { base.TabStop = value; }
192                 }
193
194                 [Browsable (false)]
195                 [EditorBrowsable (EditorBrowsableState.Never)]
196                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
197                 public override string Text {
198                         get { return base.Text; }
199                         set { base.Text = value; }
200                 }
201                 #endregion
202
203                 #region Protected Properties
204                 protected override Padding DefaultMargin {
205                         get { return new Padding (0); }
206                 }
207
208                 protected override Padding DefaultPadding {
209                         get { return new Padding (0); }
210                 }
211                 #endregion
212
213                 #region Public Methods
214                 public void BeginInit ()
215                 {
216                 }
217                 
218                 public void EndInit ()
219                 {
220                 }
221
222                 [MonoTODO("Not implemented")]
223                 public void Join (ToolStrip toolStripToDrag)
224                 {
225                 }
226
227                 [MonoTODO("Not implemented")]
228                 public void Join (ToolStrip toolStripToDrag, int row)
229                 {
230                 }
231
232                 [MonoTODO("Not implemented")]
233                 public void Join (ToolStrip toolStripToDrag, Point location)
234                 {
235                 }
236
237                 [MonoTODO("Not implemented")]
238                 public void Join (ToolStrip toolStripToDrag, int x, int y)
239                 {
240                 }
241                 
242                 public ToolStripPanelRow PointToRow (Point clientLocation)
243                 {
244                         foreach (ToolStripPanelRow row in this.rows)
245                                 if (row.Bounds.Contains (clientLocation))
246                                         return row;
247                                         
248                         return null;
249                 }
250                 #endregion
251
252                 #region Protected Methods
253                 protected override ControlCollection CreateControlsInstance ()
254                 {
255                         return new ToolStripPanelControlCollection (this);
256                 }
257                 
258                 protected override void Dispose (bool disposing)
259                 {
260                         base.Dispose (disposing);
261                 }
262
263                 protected override void OnControlAdded (ControlEventArgs e)
264                 {
265                         if (done_first_layout && e.Control is ToolStrip)
266                                 this.AddControlToRows (e.Control);
267                         
268                         base.OnControlAdded (e);
269                 }
270
271                 protected override void OnControlRemoved (ControlEventArgs e)
272                 {
273                         base.OnControlRemoved (e);
274                         
275                         foreach (ToolStripPanelRow row in this.rows)
276                                 if (row.controls.Contains (e.Control))
277                                         row.OnControlRemoved (e.Control, 0);
278                 }
279
280                 protected override void OnDockChanged (EventArgs e)
281                 {
282                         base.OnDockChanged (e);
283                 }
284                 
285                 protected override void OnLayout (LayoutEventArgs levent)
286                 {
287                         // Don't see any reason to layout if we aren't created
288                         if (!this.Created)
289                                 return;
290                                 
291                         // The first time through, we have to layout everything where it belongs.
292                         // The key is that when we resize and stuff, we don't resize or move toolstrips.
293                         if (!done_first_layout) {
294                                 ArrayList al = new ArrayList (this.Controls);
295                                 al.Sort (new TabIndexComparer ());
296                                 
297                                 foreach (ToolStrip ts in al)
298                                         this.AddControlToRows (ts);
299                                         
300                                 done_first_layout = true;                       
301                         }
302                         
303                         // Lay out all the rows
304                         Point position = this.DisplayRectangle.Location;
305
306                         foreach (ToolStripPanelRow row in this.rows) {
307                                 row.SetBounds (new Rectangle (position, new Size (this.Width, row.Bounds.Height)));
308
309                                 position.Y += row.Bounds.Height;
310                         }
311
312                         // Find how big we are so we can autosize ourself
313                         if (this.rows.Count > 0) {
314                                 int last_row_bottom = this.rows[this.rows.Count - 1].Bounds.Bottom;
315                         
316                                 if (last_row_bottom != this.Height)
317                                         this.SetBounds (bounds.X, bounds.Y, bounds.Width, last_row_bottom);
318                         }
319                         
320                         this.Invalidate ();
321                         
322                         return;
323                 }
324
325                 [EditorBrowsable (EditorBrowsableState.Advanced)]
326                 protected override void OnPaintBackground (PaintEventArgs pevent)
327                 {
328                         base.OnPaintBackground (pevent);
329
330                         this.Renderer.DrawToolStripPanelBackground (new ToolStripPanelRenderEventArgs (pevent.Graphics, this));
331                 }
332
333                 protected override void OnParentChanged (EventArgs e)
334                 {
335                         base.OnParentChanged (e);
336                 }
337                 
338                 protected virtual void OnRendererChanged (EventArgs e)
339                 {
340                         EventHandler eh = (EventHandler)(Events [RendererChangedEvent]);
341                         if (eh != null)
342                                 eh (this, e);
343                 }
344
345                 protected override void OnRightToLeftChanged (EventArgs e)
346                 {
347                         base.OnRightToLeftChanged (e);
348                 }
349                 #endregion
350                 
351                 #region Public Events
352                 static object RendererChangedEvent = new object ();
353
354                 [Browsable (true)]
355                 [EditorBrowsable (EditorBrowsableState.Always)]
356                 public new event EventHandler AutoSizeChanged {
357                         add { base.AutoSizeChanged += value; }
358                         remove { base.AutoSizeChanged -= value; }
359                 }
360
361                 public event EventHandler RendererChanged {
362                         add { Events.AddHandler (RendererChangedEvent, value); }
363                         remove { Events.RemoveHandler (RendererChangedEvent, value); }
364                 }
365
366                 [Browsable (false)]
367                 [EditorBrowsable (EditorBrowsableState.Never)]
368                 public new event EventHandler TabIndexChanged {
369                         add { base.TabIndexChanged += value; }
370                         remove { base.TabIndexChanged -= value; }
371                 }
372
373                 [Browsable (false)]
374                 [EditorBrowsable (EditorBrowsableState.Never)]
375                 public new event EventHandler TabStopChanged {
376                         add { base.TabStopChanged += value; }
377                         remove { base.TabStopChanged -= value; }
378                 }
379
380                 [Browsable (false)]
381                 [EditorBrowsable (EditorBrowsableState.Never)]
382                 public new event EventHandler TextChanged {
383                         add { base.TextChanged += value; }
384                         remove { base.TextChanged -= value; }
385                 }
386                 #endregion
387
388                 #region Private Methods
389                 void IDropTarget.OnDragDrop (DragEventArgs e)
390                 {
391                         throw new NotImplementedException ();
392                 }
393
394                 void IDropTarget.OnDragEnter (DragEventArgs e)
395                 {
396                         throw new NotImplementedException ();
397                 }
398
399                 void IDropTarget.OnDragLeave (EventArgs e)
400                 {
401                         throw new NotImplementedException ();
402                 }
403
404                 void IDropTarget.OnDragOver (DragEventArgs e)
405                 {
406                         throw new NotImplementedException ();
407                 }
408
409                 private void AddControlToRows (Control control)
410                 {
411                         if (this.rows.Count > 0)
412                                 if (this.rows[this.rows.Count - 1].CanMove ((ToolStrip)control)) {
413                                         this.rows[this.rows.Count - 1].OnControlAdded (control, 0);
414                                         return;
415                                 }
416
417                         ToolStripPanelRow new_row = new ToolStripPanelRow (this);
418                         new_row.SetBounds (new Rectangle (0, 0, this.Width, 25));
419                         this.rows.Add (new_row);
420                         new_row.OnControlAdded (control, 0);
421                 }
422                 /*
423                 private Region FindBackgroundRegion ()
424                 {
425                         Region r = new Region (this.Bounds);
426
427                         foreach (Control c in this.Controls)
428                                 r.Exclude (c.Bounds);
429
430                         return r;
431                 }
432                 */
433                 #endregion
434
435                 #region Nested Classes
436                 [ComVisible (false)]
437                 [ListBindable (false)]
438                 public class ToolStripPanelRowCollection : ArrangedElementCollection, IList, ICollection, IEnumerable
439                 {
440                         //private ToolStripPanel owner;
441                         
442                         public ToolStripPanelRowCollection (ToolStripPanel owner) : base ()
443                         {
444                                 //this.owner = owner;
445                         }
446                         
447                         public ToolStripPanelRowCollection (ToolStripPanel owner, ToolStripPanelRow[] value) : this (owner)
448                         {
449                                 if (value != null)
450                                         foreach (ToolStripPanelRow tspr in value)
451                                                 this.Add (tspr);
452                         }
453                         
454                         public new virtual ToolStripPanelRow this [int index] {
455                                 get { return (ToolStripPanelRow)base[index]; }
456                         }
457
458                         #region Public Methods
459                         public int Add (ToolStripPanelRow value)
460                         {
461                                 return base.Add (value);
462                         }
463                         
464                         public void AddRange (ToolStripPanelRowCollection value)
465                         {
466                                 if (value == null)
467                                         throw new ArgumentNullException ("value");
468
469                                 foreach (ToolStripPanelRow tspr in value)
470                                         this.Add (tspr);
471                         }
472                         
473                         public void AddRange (ToolStripPanelRow[] value)
474                         {
475                                 if (value == null)
476                                         throw new ArgumentNullException ("value");
477
478                                 foreach (ToolStripPanelRow tspr in value)
479                                         this.Add (tspr);
480                         }
481                         
482                         public new virtual void Clear ()
483                         {
484                                 base.Clear ();
485                         }
486                         
487                         public bool Contains (ToolStripPanelRow value)
488                         {
489                                 return base.Contains (value);
490                         }
491                         
492                         public void CopyTo (ToolStripPanelRow[] array, int index)
493                         {
494                                 base.CopyTo (array, index);
495                         }
496                         
497                         public int IndexOf (ToolStripPanelRow value)
498                         {
499                                 return base.IndexOf (value);
500                         }
501                         
502                         public void Insert (int index, ToolStripPanelRow value)
503                         {
504                                 base.Insert (index, value);
505                         }
506                         
507                         public void Remove (ToolStripPanelRow value)
508                         {
509                                 base.Remove (value);
510                         }
511                         
512                         public void RemoveAt (int index)
513                         {
514                                 base.InternalRemoveAt (index);
515                         }
516                         #endregion
517
518                         #region IList Members
519                         void IList.RemoveAt (int index)
520                         {
521                                 base.InternalRemoveAt (index);
522                         }
523                         #endregion
524                 }
525                 
526                 private class ToolStripPanelControlCollection : ControlCollection
527                 {
528                         public ToolStripPanelControlCollection (Control owner) : base (owner)
529                         {
530                         }
531                 }
532
533                 private class TabIndexComparer : IComparer
534                 {
535                         #region IComparer Members
536                         public int Compare (object x, object y)
537                         {
538                                 if (!(x is Control) || !(y is Control))
539                                         throw new ArgumentException ();
540
541                                 return (x as Control).TabIndex - (y as Control).TabIndex;
542                         }
543                         #endregion
544                 }
545                 #endregion
546         }
547 }
548 #endif