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:
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
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.
23 // Copyright (c) 2006 Jonathan Pobst
26 // Jonathan Pobst (monkey@jpobst.com)
31 using System.Collections;
32 using System.ComponentModel;
34 using System.Runtime.InteropServices;
35 using System.Windows.Forms.Layout;
37 namespace System.Windows.Forms
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
45 private bool done_first_layout;
46 private LayoutEngine layout_engine;
48 private Orientation orientation;
49 private ToolStripRenderer renderer;
50 private ToolStripRenderMode render_mode;
51 private Padding row_margin;
52 private ToolStripPanelRowCollection rows;
54 public ToolStripPanel () : base ()
59 this.render_mode = ToolStripRenderMode.ManagerRenderMode;
60 this.row_margin = new Padding (3, 0, 0, 0);
61 this.rows = new ToolStripPanelRowCollection (this);
64 #region Public Properties
66 [EditorBrowsable (EditorBrowsableState.Never)]
67 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
68 public override bool AllowDrop {
69 get { return base.AllowDrop; }
70 set { base.AllowDrop = value; }
74 [EditorBrowsable (EditorBrowsableState.Never)]
75 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
76 public override bool AutoScroll {
77 get { return base.AutoScroll; }
78 set { base.AutoScroll = value; }
82 [EditorBrowsable (EditorBrowsableState.Never)]
83 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
84 public new Size AutoScrollMargin {
85 get { return base.AutoScrollMargin; }
86 set { base.AutoScrollMargin = value; }
90 [EditorBrowsable (EditorBrowsableState.Never)]
91 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
92 public new Size AutoScrollMinSize {
93 get { return base.AutoScrollMinSize; }
94 set { base.AutoScrollMinSize = value; }
98 [DesignerSerializationVisibility (DesignerSerializationVisibility.Visible)]
99 public override bool AutoSize {
100 get { return base.AutoSize; }
101 set { base.AutoSize = value; }
104 public override DockStyle Dock {
105 get { return base.Dock; }
111 case DockStyle.Bottom:
113 this.orientation = Orientation.Horizontal;
116 case DockStyle.Right:
117 this.orientation = Orientation.Vertical;
123 public override LayoutEngine LayoutEngine {
125 if (this.layout_engine == null)
126 this.layout_engine = new FlowLayout ();
128 return this.layout_engine;
133 [DefaultValue (false)]
134 [EditorBrowsable (EditorBrowsableState.Advanced)]
136 get { return this.locked; }
137 set { this.locked = value; }
140 public Orientation Orientation {
141 get { return this.orientation; }
142 set { this.orientation = value; }
146 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
147 public ToolStripRenderer Renderer {
149 if (this.render_mode == ToolStripRenderMode.ManagerRenderMode)
150 return ToolStripManager.Renderer;
152 return this.renderer;
155 if (this.renderer != value) {
156 this.renderer = value;
157 this.render_mode = ToolStripRenderMode.Custom;
158 this.OnRendererChanged (EventArgs.Empty);
163 public ToolStripRenderMode RenderMode {
164 get { return this.render_mode; }
166 if (!Enum.IsDefined (typeof (ToolStripRenderMode), value))
167 throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ToolStripRenderMode", value));
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 ();
174 this.render_mode = value;
178 public Padding RowMargin {
179 get { return this.row_margin; }
180 set { this.row_margin = value; }
184 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
185 public ToolStripPanelRow[] Rows {
187 ToolStripPanelRow[] retval = new ToolStripPanelRow [this.rows.Count];
188 this.rows.CopyTo (retval, 0);
194 [EditorBrowsable (EditorBrowsableState.Never)]
195 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
196 public new int TabIndex {
197 get { return base.TabIndex; }
198 set { base.TabIndex = value; }
202 [EditorBrowsable (EditorBrowsableState.Never)]
203 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
204 public new bool TabStop {
205 get { return base.TabStop; }
206 set { base.TabStop = value; }
210 [EditorBrowsable (EditorBrowsableState.Never)]
211 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
212 public override string Text {
213 get { return base.Text; }
214 set { base.Text = value; }
218 #region Protected Properties
219 protected override Padding DefaultMargin {
220 get { return new Padding (0); }
223 protected override Padding DefaultPadding {
224 get { return new Padding (0); }
228 #region Public Methods
229 public void BeginInit ()
233 public void EndInit ()
237 [MonoTODO("Not implemented")]
238 public void Join (ToolStrip toolStripToDrag)
240 if (!Contains (toolStripToDrag))
241 Controls.Add (toolStripToDrag);
244 [MonoTODO("Not implemented")]
245 public void Join (ToolStrip toolStripToDrag, int row)
247 Join (toolStripToDrag);
250 [MonoTODO("Not implemented")]
251 public void Join (ToolStrip toolStripToDrag, Point location)
253 Join (toolStripToDrag);
256 [MonoTODO("Not implemented")]
257 public void Join (ToolStrip toolStripToDrag, int x, int y)
259 Join (toolStripToDrag);
262 public ToolStripPanelRow PointToRow (Point clientLocation)
264 foreach (ToolStripPanelRow row in this.rows)
265 if (row.Bounds.Contains (clientLocation))
272 #region Protected Methods
273 protected override ControlCollection CreateControlsInstance ()
275 return new ToolStripPanelControlCollection (this);
278 protected override void Dispose (bool disposing)
280 base.Dispose (disposing);
283 protected override void OnControlAdded (ControlEventArgs e)
285 if (this.Dock == DockStyle.Left || this.Dock == DockStyle.Right)
286 (e.Control as ToolStrip).LayoutStyle = ToolStripLayoutStyle.VerticalStackWithOverflow;
288 (e.Control as ToolStrip).LayoutStyle = ToolStripLayoutStyle.HorizontalStackWithOverflow;
290 if (done_first_layout && e.Control is ToolStrip)
291 this.AddControlToRows (e.Control);
293 base.OnControlAdded (e);
296 protected override void OnControlRemoved (ControlEventArgs e)
298 base.OnControlRemoved (e);
300 foreach (ToolStripPanelRow row in this.rows)
301 if (row.controls.Contains (e.Control))
302 row.OnControlRemoved (e.Control, 0);
305 protected override void OnDockChanged (EventArgs e)
307 base.OnDockChanged (e);
310 protected override void OnLayout (LayoutEventArgs e)
312 // Don't see any reason to layout if we aren't created
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 ());
322 foreach (ToolStrip ts in al)
323 this.AddControlToRows (ts);
325 done_first_layout = true;
328 // Lay out all the rows
329 Point position = this.DisplayRectangle.Location;
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)));
335 position.X += row.Bounds.Width;
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;
342 if (last_row_right != this.Width)
343 this.SetBounds (bounds.X, bounds.Y, last_row_right, bounds.Bottom);
346 foreach (ToolStripPanelRow row in this.rows) {
347 row.SetBounds (new Rectangle (position, new Size (this.Width, row.Bounds.Height)));
349 position.Y += row.Bounds.Height;
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;
356 if (last_row_bottom != this.Height)
357 this.SetBounds (bounds.X, bounds.Y, bounds.Width, last_row_bottom);
366 [EditorBrowsable (EditorBrowsableState.Advanced)]
367 protected override void OnPaintBackground (PaintEventArgs e)
369 base.OnPaintBackground (e);
371 this.Renderer.DrawToolStripPanelBackground (new ToolStripPanelRenderEventArgs (e.Graphics, this));
374 protected override void OnParentChanged (EventArgs e)
376 base.OnParentChanged (e);
379 protected virtual void OnRendererChanged (EventArgs e)
381 EventHandler eh = (EventHandler)(Events [RendererChangedEvent]);
386 protected override void OnRightToLeftChanged (EventArgs e)
388 base.OnRightToLeftChanged (e);
392 #region Public Events
393 static object RendererChangedEvent = new object ();
396 [EditorBrowsable (EditorBrowsableState.Always)]
397 public new event EventHandler AutoSizeChanged {
398 add { base.AutoSizeChanged += value; }
399 remove { base.AutoSizeChanged -= value; }
402 public event EventHandler RendererChanged {
403 add { Events.AddHandler (RendererChangedEvent, value); }
404 remove { Events.RemoveHandler (RendererChangedEvent, value); }
408 [EditorBrowsable (EditorBrowsableState.Never)]
409 public new event EventHandler TabIndexChanged {
410 add { base.TabIndexChanged += value; }
411 remove { base.TabIndexChanged -= value; }
415 [EditorBrowsable (EditorBrowsableState.Never)]
416 public new event EventHandler TabStopChanged {
417 add { base.TabStopChanged += value; }
418 remove { base.TabStopChanged -= value; }
422 [EditorBrowsable (EditorBrowsableState.Never)]
423 public new event EventHandler TextChanged {
424 add { base.TextChanged += value; }
425 remove { base.TextChanged -= value; }
429 #region Private Methods
431 private void AddControlToRows (Control control)
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);
439 ToolStripPanelRow new_row = new ToolStripPanelRow (this);
441 if (this.Dock == DockStyle.Left || this.Dock == DockStyle.Right)
442 new_row.SetBounds (new Rectangle (0, 0, 25, this.Height));
444 new_row.SetBounds (new Rectangle (0, 0, this.Width, 25));
446 this.rows.Add (new_row);
447 new_row.OnControlAdded (control, 0);
450 private Region FindBackgroundRegion ()
452 Region r = new Region (this.Bounds);
454 foreach (Control c in this.Controls)
455 r.Exclude (c.Bounds);
462 #region Nested Classes
464 [ListBindable (false)]
465 public class ToolStripPanelRowCollection : ArrangedElementCollection, IList, ICollection, IEnumerable
467 //private ToolStripPanel owner;
469 public ToolStripPanelRowCollection (ToolStripPanel owner) : base ()
471 //this.owner = owner;
474 public ToolStripPanelRowCollection (ToolStripPanel owner, ToolStripPanelRow[] value) : this (owner)
477 foreach (ToolStripPanelRow tspr in value)
481 public new virtual ToolStripPanelRow this [int index] {
482 get { return (ToolStripPanelRow)base[index]; }
485 #region Public Methods
486 public int Add (ToolStripPanelRow value)
488 return base.Add (value);
491 public void AddRange (ToolStripPanelRowCollection value)
494 throw new ArgumentNullException ("value");
496 foreach (ToolStripPanelRow tspr in value)
500 public void AddRange (ToolStripPanelRow[] value)
503 throw new ArgumentNullException ("value");
505 foreach (ToolStripPanelRow tspr in value)
509 public new virtual void Clear ()
514 public bool Contains (ToolStripPanelRow value)
516 return base.Contains (value);
519 public void CopyTo (ToolStripPanelRow[] array, int index)
521 base.CopyTo (array, index);
524 public int IndexOf (ToolStripPanelRow value)
526 return base.IndexOf (value);
529 public void Insert (int index, ToolStripPanelRow value)
531 base.Insert (index, value);
534 public void Remove (ToolStripPanelRow value)
539 public void RemoveAt (int index)
541 base.InternalRemoveAt (index);
545 #region IList Members
546 object IList.this [int index] {
547 get { return this [index]; }
548 [MonoTODO ("Stub, does nothing")]
552 bool IList.IsFixedSize {
553 get { return IsFixedSize; }
556 bool IList.IsReadOnly {
557 get { return IsReadOnly; }
560 int IList.Add (object value)
562 return Add (value as ToolStripPanelRow);
570 bool IList.Contains (object value)
572 return Contains (value as ToolStripPanelRow);
575 int IList.IndexOf (object value)
577 return IndexOf (value as ToolStripPanelRow);
580 void IList.Insert (int index, object value)
582 Insert (index, value as ToolStripPanelRow);
585 void IList.Remove (object value)
587 Remove (value as ToolStripPanelRow);
590 void IList.RemoveAt (int index)
592 base.InternalRemoveAt (index);
597 private class ToolStripPanelControlCollection : ControlCollection
599 public ToolStripPanelControlCollection (Control owner) : base (owner)
604 private class TabIndexComparer : IComparer
606 #region IComparer Members
607 public int Compare (object x, object y)
609 if (!(x is Control) || !(y is Control))
610 throw new ArgumentException ();
612 return (x as Control).TabIndex - (y as Control).TabIndex;