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.Runtime.InteropServices;
32 using System.ComponentModel;
33 using System.Windows.Forms.Layout;
34 using System.Collections;
36 namespace System.Windows.Forms
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
44 private bool done_first_layout;
45 private LayoutEngine layout_engine;
47 private Orientation orientation;
48 private ToolStripRenderer renderer;
49 private ToolStripRenderMode render_mode;
50 private Padding row_margin;
51 private ToolStripPanelRowCollection rows;
53 public ToolStripPanel () : base ()
58 this.render_mode = ToolStripRenderMode.ManagerRenderMode;
59 this.row_margin = new Padding (3, 0, 0, 0);
60 this.rows = new ToolStripPanelRowCollection (this);
63 #region Public Properties
65 [EditorBrowsable (EditorBrowsableState.Never)]
66 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
67 public override bool AllowDrop {
68 get { return base.AllowDrop; }
69 set { base.AllowDrop = value; }
73 [EditorBrowsable (EditorBrowsableState.Never)]
74 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
75 public override bool AutoScroll {
76 get { return base.AutoScroll; }
77 set { base.AutoScroll = value; }
81 [EditorBrowsable (EditorBrowsableState.Never)]
82 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
83 public new Size AutoScrollMargin {
84 get { return base.AutoScrollMargin; }
85 set { base.AutoScrollMargin = value; }
89 [EditorBrowsable (EditorBrowsableState.Never)]
90 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
91 public new Size AutoScrollMinSize {
92 get { return base.AutoScrollMinSize; }
93 set { base.AutoScrollMinSize = value; }
97 [DesignerSerializationVisibility (DesignerSerializationVisibility.Visible)]
98 public override bool AutoSize {
99 get { return base.AutoSize; }
100 set { base.AutoSize = value; }
103 public override DockStyle Dock {
104 get { return base.Dock; }
110 case DockStyle.Bottom:
112 this.orientation = Orientation.Horizontal;
115 case DockStyle.Right:
116 this.orientation = Orientation.Vertical;
122 public override LayoutEngine LayoutEngine {
124 if (this.layout_engine == null)
125 this.layout_engine = new FlowLayout ();
127 return this.layout_engine;
132 [DefaultValue (false)]
133 [EditorBrowsable (EditorBrowsableState.Advanced)]
135 get { return this.locked; }
136 set { this.locked = value; }
139 public Orientation Orientation {
140 get { return this.orientation; }
141 set { this.orientation = value; }
145 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
146 public ToolStripRenderer Renderer {
148 if (this.render_mode == ToolStripRenderMode.ManagerRenderMode)
149 return ToolStripManager.Renderer;
151 return this.renderer;
154 if (this.renderer != value) {
155 this.renderer = value;
156 this.render_mode = ToolStripRenderMode.Custom;
157 this.OnRendererChanged (EventArgs.Empty);
162 public ToolStripRenderMode RenderMode {
163 get { return this.render_mode; }
165 if (!Enum.IsDefined (typeof (ToolStripRenderMode), value))
166 throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for ToolStripRenderMode", value));
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 ();
173 this.render_mode = value;
177 public Padding RowMargin {
178 get { return this.row_margin; }
179 set { this.row_margin = value; }
183 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
184 public ToolStripPanelRow[] Rows {
186 ToolStripPanelRow[] retval = new ToolStripPanelRow [this.rows.Count];
187 this.rows.CopyTo (retval, 0);
193 [EditorBrowsable (EditorBrowsableState.Never)]
194 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
195 public new int TabIndex {
196 get { return base.TabIndex; }
197 set { base.TabIndex = value; }
201 [EditorBrowsable (EditorBrowsableState.Never)]
202 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
203 public new bool TabStop {
204 get { return base.TabStop; }
205 set { base.TabStop = value; }
209 [EditorBrowsable (EditorBrowsableState.Never)]
210 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
211 public override string Text {
212 get { return base.Text; }
213 set { base.Text = value; }
217 #region Protected Properties
218 protected override Padding DefaultMargin {
219 get { return new Padding (0); }
222 protected override Padding DefaultPadding {
223 get { return new Padding (0); }
227 #region Public Methods
228 public void BeginInit ()
232 public void EndInit ()
236 [MonoTODO("Not implemented")]
237 public void Join (ToolStrip toolStripToDrag)
239 if (!Contains (toolStripToDrag))
240 Controls.Add (toolStripToDrag);
243 [MonoTODO("Not implemented")]
244 public void Join (ToolStrip toolStripToDrag, int row)
246 Join (toolStripToDrag);
249 [MonoTODO("Not implemented")]
250 public void Join (ToolStrip toolStripToDrag, Point location)
252 Join (toolStripToDrag);
255 [MonoTODO("Not implemented")]
256 public void Join (ToolStrip toolStripToDrag, int x, int y)
258 Join (toolStripToDrag);
261 public ToolStripPanelRow PointToRow (Point clientLocation)
263 foreach (ToolStripPanelRow row in this.rows)
264 if (row.Bounds.Contains (clientLocation))
271 #region Protected Methods
272 protected override ControlCollection CreateControlsInstance ()
274 return new ToolStripPanelControlCollection (this);
277 protected override void Dispose (bool disposing)
279 base.Dispose (disposing);
282 protected override void OnControlAdded (ControlEventArgs e)
284 if (this.Dock == DockStyle.Left || this.Dock == DockStyle.Right)
285 (e.Control as ToolStrip).LayoutStyle = ToolStripLayoutStyle.VerticalStackWithOverflow;
287 (e.Control as ToolStrip).LayoutStyle = ToolStripLayoutStyle.HorizontalStackWithOverflow;
289 if (done_first_layout && e.Control is ToolStrip)
290 this.AddControlToRows (e.Control);
292 base.OnControlAdded (e);
295 protected override void OnControlRemoved (ControlEventArgs e)
297 base.OnControlRemoved (e);
299 foreach (ToolStripPanelRow row in this.rows)
300 if (row.controls.Contains (e.Control))
301 row.OnControlRemoved (e.Control, 0);
304 protected override void OnDockChanged (EventArgs e)
306 base.OnDockChanged (e);
309 protected override void OnLayout (LayoutEventArgs e)
311 // Don't see any reason to layout if we aren't created
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 ());
321 foreach (ToolStrip ts in al)
322 this.AddControlToRows (ts);
324 done_first_layout = true;
327 // Lay out all the rows
328 Point position = this.DisplayRectangle.Location;
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)));
334 position.X += row.Bounds.Width;
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;
341 if (last_row_right != this.Width)
342 this.SetBounds (bounds.X, bounds.Y, last_row_right, bounds.Bottom);
345 foreach (ToolStripPanelRow row in this.rows) {
346 row.SetBounds (new Rectangle (position, new Size (this.Width, row.Bounds.Height)));
348 position.Y += row.Bounds.Height;
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;
355 if (last_row_bottom != this.Height)
356 this.SetBounds (bounds.X, bounds.Y, bounds.Width, last_row_bottom);
365 [EditorBrowsable (EditorBrowsableState.Advanced)]
366 protected override void OnPaintBackground (PaintEventArgs e)
368 base.OnPaintBackground (e);
370 this.Renderer.DrawToolStripPanelBackground (new ToolStripPanelRenderEventArgs (e.Graphics, this));
373 protected override void OnParentChanged (EventArgs e)
375 base.OnParentChanged (e);
378 protected virtual void OnRendererChanged (EventArgs e)
380 EventHandler eh = (EventHandler)(Events [RendererChangedEvent]);
385 protected override void OnRightToLeftChanged (EventArgs e)
387 base.OnRightToLeftChanged (e);
391 #region Public Events
392 static object RendererChangedEvent = new object ();
395 [EditorBrowsable (EditorBrowsableState.Always)]
396 public new event EventHandler AutoSizeChanged {
397 add { base.AutoSizeChanged += value; }
398 remove { base.AutoSizeChanged -= value; }
401 public event EventHandler RendererChanged {
402 add { Events.AddHandler (RendererChangedEvent, value); }
403 remove { Events.RemoveHandler (RendererChangedEvent, value); }
407 [EditorBrowsable (EditorBrowsableState.Never)]
408 public new event EventHandler TabIndexChanged {
409 add { base.TabIndexChanged += value; }
410 remove { base.TabIndexChanged -= value; }
414 [EditorBrowsable (EditorBrowsableState.Never)]
415 public new event EventHandler TabStopChanged {
416 add { base.TabStopChanged += value; }
417 remove { base.TabStopChanged -= value; }
421 [EditorBrowsable (EditorBrowsableState.Never)]
422 public new event EventHandler TextChanged {
423 add { base.TextChanged += value; }
424 remove { base.TextChanged -= value; }
428 #region Private Methods
429 void IDropTarget.OnDragDrop (DragEventArgs e)
431 throw new NotImplementedException ();
434 void IDropTarget.OnDragEnter (DragEventArgs e)
436 throw new NotImplementedException ();
439 void IDropTarget.OnDragLeave (EventArgs e)
441 throw new NotImplementedException ();
444 void IDropTarget.OnDragOver (DragEventArgs e)
446 throw new NotImplementedException ();
449 private void AddControlToRows (Control control)
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);
457 ToolStripPanelRow new_row = new ToolStripPanelRow (this);
459 if (this.Dock == DockStyle.Left || this.Dock == DockStyle.Right)
460 new_row.SetBounds (new Rectangle (0, 0, 25, this.Height));
462 new_row.SetBounds (new Rectangle (0, 0, this.Width, 25));
464 this.rows.Add (new_row);
465 new_row.OnControlAdded (control, 0);
468 private Region FindBackgroundRegion ()
470 Region r = new Region (this.Bounds);
472 foreach (Control c in this.Controls)
473 r.Exclude (c.Bounds);
480 #region Nested Classes
482 [ListBindable (false)]
483 public class ToolStripPanelRowCollection : ArrangedElementCollection, IList, ICollection, IEnumerable
485 //private ToolStripPanel owner;
487 public ToolStripPanelRowCollection (ToolStripPanel owner) : base ()
489 //this.owner = owner;
492 public ToolStripPanelRowCollection (ToolStripPanel owner, ToolStripPanelRow[] value) : this (owner)
495 foreach (ToolStripPanelRow tspr in value)
499 public new virtual ToolStripPanelRow this [int index] {
500 get { return (ToolStripPanelRow)base[index]; }
503 #region Public Methods
504 public int Add (ToolStripPanelRow value)
506 return base.Add (value);
509 public void AddRange (ToolStripPanelRowCollection value)
512 throw new ArgumentNullException ("value");
514 foreach (ToolStripPanelRow tspr in value)
518 public void AddRange (ToolStripPanelRow[] value)
521 throw new ArgumentNullException ("value");
523 foreach (ToolStripPanelRow tspr in value)
527 public new virtual void Clear ()
532 public bool Contains (ToolStripPanelRow value)
534 return base.Contains (value);
537 public void CopyTo (ToolStripPanelRow[] array, int index)
539 base.CopyTo (array, index);
542 public int IndexOf (ToolStripPanelRow value)
544 return base.IndexOf (value);
547 public void Insert (int index, ToolStripPanelRow value)
549 base.Insert (index, value);
552 public void Remove (ToolStripPanelRow value)
557 public void RemoveAt (int index)
559 base.InternalRemoveAt (index);
563 #region IList Members
564 void IList.RemoveAt (int index)
566 base.InternalRemoveAt (index);
571 private class ToolStripPanelControlCollection : ControlCollection
573 public ToolStripPanelControlCollection (Control owner) : base (owner)
578 private class TabIndexComparer : IComparer
580 #region IComparer Members
581 public int Compare (object x, object y)
583 if (!(x is Control) || !(y is Control))
584 throw new ArgumentException ();
586 return (x as Control).TabIndex - (y as Control).TabIndex;