1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
8 //
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 //
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 //
20 // Copyright (c) 2004-2005 Novell, Inc.
21 //
22 // Authors:
23 //	Jackson Harper (jackson@ximian.com)
24 
25 //
26 // TODO:
27 //  - Change cursor when mouse is over grip
28 //
29 
30 using System.Collections;
31 using System.ComponentModel;
32 using System.ComponentModel.Design;
33 using System.Drawing;
34 using System.Drawing.Text;
35 using System.Drawing.Imaging;
36 using System.Runtime.InteropServices;
37 
38 namespace System.Windows.Forms {
39 	[ComVisible (true)]
40 	[ClassInterface (ClassInterfaceType.AutoDispatch)]
41 	[DefaultEvent("PanelClick")]
42 	[Designer("System.Windows.Forms.Design.StatusBarDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
43 	[DefaultProperty("Text")]
44 	public class StatusBar : Control {
45 		#region Fields
46 		private StatusBarPanelCollection panels;
47 
48 		private bool show_panels = false;
49 		private bool sizing_grip = true;
50 
51 		// Stuff for panel Tooltips
52 		private Timer tooltip_timer;
53 		private ToolTip tooltip_window;
54 		private StatusBarPanel tooltip_currently_showing;
55 		#endregion	// Fields
56 
57 		#region Public Constructors
StatusBar()58 		public StatusBar ()
59 		{
60 			Dock = DockStyle.Bottom;
61 			this.TabStop = false;
62 			this.SetStyle(ControlStyles.UserPaint | ControlStyles.Selectable, false);
63 
64 			// For displaying/hiding tooltips
65 			MouseMove += new MouseEventHandler (StatusBar_MouseMove);
66 			MouseLeave += new EventHandler (StatusBar_MouseLeave);
67 		}
68 		#endregion	// Public Constructors
69 
70 		#region	Public Instance Properties
71 		[Browsable(false)]
72 		[EditorBrowsable(EditorBrowsableState.Never)]
73 		public override Color BackColor {
74 			get { return base.BackColor; }
75 			set { base.BackColor = value; }
76 		}
77 
78 		[Browsable(false)]
79 		[EditorBrowsable(EditorBrowsableState.Never)]
80 		public override Image BackgroundImage {
81 			get { return base.BackgroundImage; }
82 			set { base.BackgroundImage = value; }
83 		}
84 
85 		[Browsable (false)]
86 		[EditorBrowsable (EditorBrowsableState.Never)]
87 		public override ImageLayout BackgroundImageLayout {
88 			get {
89 				return base.BackgroundImageLayout;
90 			}
91 			set {
92 				base.BackgroundImageLayout = value;
93 			}
94 		}
95 
96 		[Localizable(true)]
97 		[DefaultValue(DockStyle.Bottom)]
98 		public override DockStyle Dock {
99 			get { return base.Dock; }
100 			set { base.Dock = value; }
101 		}
102 
103 		[EditorBrowsable (EditorBrowsableState.Never)]
104 		protected override bool DoubleBuffered {
105 			get {
106 				return base.DoubleBuffered;
107 			}
108 			set {
109 				base.DoubleBuffered = value;
110 			}
111 		}
112 
113 		[Localizable(true)]
114 		public override Font Font {
115 			get { return base.Font; }
116 			set {
117 				if (value == Font)
118 					return;
119 				base.Font = value;
120 				UpdateStatusBar ();
121 			}
122 		}
123 
124 		[Browsable(false)]
125 		[EditorBrowsable(EditorBrowsableState.Never)]
126 		public override Color ForeColor {
127 			get { return base.ForeColor; }
128 			set { base.ForeColor = value; }
129 		}
130 
131 		[Browsable(false)]
132 		[EditorBrowsable(EditorBrowsableState.Never)]
133 		public new ImeMode ImeMode {
134 			get { return base.ImeMode; }
135 			set { base.ImeMode = value; }
136 		}
137 
138 		[MergableProperty(false)]
139 		[Localizable(true)]
140 		[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
141 		public StatusBarPanelCollection Panels {
142 			get {
143 				if (panels == null)
144 					panels = new StatusBarPanelCollection (this);
145 				return panels;
146 			}
147 		}
148 
149 		[DefaultValue(false)]
150 		public bool ShowPanels {
151 			get { return show_panels; }
152 			set {
153 				if (show_panels == value)
154 					return;
155 				show_panels = value;
156 				UpdateStatusBar ();
157 			}
158 		}
159 
160 		[DefaultValue(true)]
161 		public bool SizingGrip {
162 			get { return sizing_grip; }
163 			set {
164 				if (sizing_grip == value)
165 					return;
166 				sizing_grip = value;
167 				UpdateStatusBar ();
168 			}
169 		}
170 
171 		[DefaultValue(false)]
172 		public new bool TabStop {
173 			get { return base.TabStop; }
174 			set { base.TabStop = value; }
175 		}
176 
177 		[Localizable(true)]
178 		public override string Text {
179 			get { return base.Text; }
180 			set {
181 				if (value == Text)
182 					return;
183 				base.Text = value;
184 				UpdateStatusBar ();
185 			}
186 
187 		}
188 
189 		#endregion Public Instance Properties
190 
191 		#region Protected Instance Properties
192 		protected override CreateParams CreateParams {
193 			get {
194 				return base.CreateParams;
195 			}
196 		}
197 
198 		protected override ImeMode DefaultImeMode {
199 			get { return ImeMode.Disable; }
200 		}
201 
202 		protected override Size DefaultSize {
203 			get { return ThemeEngine.Current.StatusBarDefaultSize; }
204 		}
205 
206 		#endregion	// Protected Instance Properties
207 
208 		#region Public Instance Methods
ToString()209 		public override string ToString () {
210 			return base.ToString () + ", Panels.Count: " + Panels.Count +
211 				(Panels.Count > 0 ? ", Panels[0]: " + Panels [0] : String.Empty);
212 		}
213 
214 		#endregion	// Public Instance Methods
215 
216 		#region Protected Instance Methods
CreateHandle()217 		protected override void CreateHandle ()
218 		{
219 			base.CreateHandle ();
220 		}
221 
Dispose(bool disposing)222 		protected override void Dispose (bool disposing) {
223 			base.Dispose (disposing);
224 		}
225 
OnDrawItem(StatusBarDrawItemEventArgs sbdievent)226 		protected virtual void OnDrawItem (StatusBarDrawItemEventArgs sbdievent) {
227 			StatusBarDrawItemEventHandler eh = (StatusBarDrawItemEventHandler)(Events [DrawItemEvent]);
228 			if (eh != null)
229 				eh (this, sbdievent);
230 		}
231 
OnHandleCreated(EventArgs e)232 		protected override void OnHandleCreated (EventArgs e) {
233 			base.OnHandleCreated (e);
234 			CalcPanelSizes ();
235 		}
236 
OnHandleDestroyed(EventArgs e)237 		protected override void OnHandleDestroyed (EventArgs e) {
238 			base.OnHandleDestroyed (e);
239 		}
240 
OnLayout(LayoutEventArgs levent)241 		protected override void OnLayout (LayoutEventArgs levent) {
242 			base.OnLayout (levent);
243 		}
244 
OnMouseDown(MouseEventArgs e)245 		protected override void OnMouseDown (MouseEventArgs e) {
246 			if (panels == null)
247 				return;
248 
249 			float prev_x = 0;
250 			float gap = ThemeEngine.Current.StatusBarHorzGapWidth;
251 			for (int i = 0; i < panels.Count; i++) {
252 				float x = panels [i].Width + prev_x + (i == panels.Count - 1 ? gap : gap / 2);
253 				if (e.X >= prev_x && e.X <= x) {
254 					OnPanelClick (new StatusBarPanelClickEventArgs (panels [i],
255 						e.Button, e.Clicks, e.X, e.Y));
256 					break;
257 				}
258 				prev_x = x;
259 			}
260 
261 			base.OnMouseDown (e);
262 		}
263 
OnPanelClick(StatusBarPanelClickEventArgs e)264 		protected virtual void OnPanelClick (StatusBarPanelClickEventArgs e) {
265 			StatusBarPanelClickEventHandler eh = (StatusBarPanelClickEventHandler)(Events [PanelClickEvent]);
266 			if (eh != null)
267 				eh (this, e);
268 		}
269 
OnResize(EventArgs e)270 		protected override void OnResize (EventArgs e)
271 		{
272 			base.OnResize (e);
273 
274 			if (Width <= 0 || Height <= 0)
275 				return;
276 
277 			UpdateStatusBar ();
278 		}
279 
WndProc(ref Message m)280 		protected override void WndProc(ref Message m) {
281 			base.WndProc (ref m);
282 		}
283 
284 		#endregion	// Methods
285 
286 
287 		#region Internal Methods
OnDrawItemInternal(StatusBarDrawItemEventArgs e)288 		internal void OnDrawItemInternal (StatusBarDrawItemEventArgs e)
289 		{
290 			OnDrawItem (e);
291 		}
292 
UpdatePanel(StatusBarPanel panel)293 		internal void UpdatePanel (StatusBarPanel panel)
294 		{
295 			if (panel.AutoSize == StatusBarPanelAutoSize.Contents) {
296 				UpdateStatusBar ();
297 				return;
298 			}
299 
300 			UpdateStatusBar ();
301 		}
302 
UpdatePanelContents(StatusBarPanel panel)303 		internal void UpdatePanelContents (StatusBarPanel panel)
304 		{
305 			if (panel.AutoSize == StatusBarPanelAutoSize.Contents) {
306 				UpdateStatusBar ();
307 				Invalidate ();
308 				return;
309 			}
310 
311 			Invalidate (new Rectangle (panel.X + 2, 2, panel.Width - 4, bounds.Height - 4));
312 		}
313 
UpdateStatusBar()314 		void UpdateStatusBar ()
315 		{
316 			CalcPanelSizes ();
317 			Refresh ();
318 		}
319 
OnPaintInternal(PaintEventArgs pevent)320 		internal override void OnPaintInternal (PaintEventArgs pevent)
321 		{
322 			Draw (pevent.Graphics, pevent.ClipRectangle);
323 		}
324 
CalcPanelSizes()325 		private void CalcPanelSizes ()
326 		{
327 			if (panels == null || !show_panels)
328 				return;
329 
330 			if (Width == 0 || Height == 0)
331 				return;
332 
333 			int border = 2;
334 			int gap = ThemeEngine.Current.StatusBarHorzGapWidth;
335 			int taken = 0;
336 			ArrayList springs = null;
337 
338 			taken = border;
339 			for (int i = 0; i < panels.Count; i++) {
340 				StatusBarPanel p = panels [i];
341 
342 				if (p.AutoSize == StatusBarPanelAutoSize.None) {
343 					taken += p.Width;
344 					taken += gap;
345 					continue;
346 				}
347 				if (p.AutoSize == StatusBarPanelAutoSize.Contents) {
348 					int len = (int)(TextRenderer.MeasureString (p.Text, Font).Width + 0.5F);
349 					if (p.Icon != null) {
350 						len += 21;
351 					}
352 					p.SetWidth (len + 8);
353 					taken += p.Width;
354 					taken += gap;
355 					continue;
356 				}
357 				if (p.AutoSize == StatusBarPanelAutoSize.Spring) {
358 					if (springs == null)
359 						springs = new ArrayList ();
360 					springs.Add (p);
361 					taken += gap;
362 					continue;
363 				}
364 			}
365 
366 			if (springs != null) {
367 				int spring_total = springs.Count;
368 				int total_width = Width - taken - (SizingGrip ? ThemeEngine.Current.StatusBarSizeGripWidth : 0);
369 				for (int i = 0; i < spring_total; i++) {
370 					StatusBarPanel p = (StatusBarPanel)springs[i];
371 					int width = total_width / spring_total;
372 					p.SetWidth(width >= p.MinWidth ? width : p.MinWidth);
373 				}
374 			}
375 
376 			taken = border;
377 			for (int i = 0; i < panels.Count; i++) {
378 				StatusBarPanel p = panels [i];
379 				p.X = taken;
380 				taken += p.Width + gap;
381 			}
382 		}
383 
Draw(Graphics dc, Rectangle clip)384 		private void Draw (Graphics dc, Rectangle clip)
385 		{
386 			ThemeEngine.Current.DrawStatusBar (dc, clip, this);
387 
388 		}
389 		#endregion	// Internal Methods
390 
391 		#region Stuff for ToolTips
StatusBar_MouseMove(object sender, MouseEventArgs e)392 		private void StatusBar_MouseMove (object sender, MouseEventArgs e)
393 		{
394 			if (!show_panels)
395 				return;
396 
397 			StatusBarPanel p = GetPanelAtPoint (e.Location);
398 
399 			if (p != tooltip_currently_showing)
400 				MouseLeftPanel (tooltip_currently_showing);
401 
402 			if (p != null && tooltip_currently_showing == null)
403 				MouseEnteredPanel (p);
404 		}
405 
StatusBar_MouseLeave(object sender, EventArgs e)406 		private void StatusBar_MouseLeave (object sender, EventArgs e)
407 		{
408 			if (tooltip_currently_showing != null)
409 				MouseLeftPanel (tooltip_currently_showing);
410 		}
411 
GetPanelAtPoint(Point point)412 		private StatusBarPanel GetPanelAtPoint (Point point)
413 		{
414 			foreach (StatusBarPanel p in Panels)
415 				if (point.X >= p.X && point.X <= (p.X + p.Width))
416 					return p;
417 
418 			return null;
419 		}
420 
MouseEnteredPanel(StatusBarPanel item)421 		private void MouseEnteredPanel (StatusBarPanel item)
422 		{
423 			tooltip_currently_showing = item;
424 			ToolTipTimer.Start ();
425 		}
426 
MouseLeftPanel(StatusBarPanel item)427 		private void MouseLeftPanel (StatusBarPanel item)
428 		{
429 			ToolTipTimer.Stop ();
430 			ToolTipWindow.Hide (this);
431 			tooltip_currently_showing = null;
432 		}
433 
434 		private Timer ToolTipTimer {
435 			get {
436 				if (tooltip_timer == null) {
437 					tooltip_timer = new Timer ();
438 					tooltip_timer.Enabled = false;
439 					tooltip_timer.Interval = 500;
440 					tooltip_timer.Tick += new EventHandler (ToolTipTimer_Tick);
441 				}
442 
443 				return tooltip_timer;
444 			}
445 		}
446 
447 		private ToolTip ToolTipWindow {
448 			get {
449 				if (tooltip_window == null)
450 					tooltip_window = new ToolTip ();
451 
452 				return tooltip_window;
453 			}
454 		}
455 
ToolTipTimer_Tick(object o, EventArgs args)456 		private void ToolTipTimer_Tick (object o, EventArgs args)
457 		{
458 			string tooltip = tooltip_currently_showing.ToolTipText;
459 
460 			if (tooltip != null && tooltip.Length > 0)
461 				ToolTipWindow.Present (this, tooltip);
462 
463 			ToolTipTimer.Stop ();
464 		}
465 		#endregion
466 
467 		#region Events
468 		[Browsable(false)]
469 		[EditorBrowsable(EditorBrowsableState.Never)]
470 		public new event EventHandler BackColorChanged {
471 			add { base.BackColorChanged += value; }
472 			remove { base.BackColorChanged -= value; }
473 		}
474 
475 		[Browsable(false)]
476 		[EditorBrowsable(EditorBrowsableState.Never)]
477 		public new event EventHandler BackgroundImageChanged {
478 			add { base.BackgroundImageChanged += value; }
479 			remove { base.BackgroundImageChanged -= value; }
480 		}
481 
482 		[Browsable (false)]
483 		[EditorBrowsable (EditorBrowsableState.Never)]
484 		public new event EventHandler BackgroundImageLayoutChanged
485 		{
486 			add { base.BackgroundImageLayoutChanged += value; }
487 			remove { base.BackgroundImageLayoutChanged -= value; }
488 		}
489 
490 		[Browsable(false)]
491 		[EditorBrowsable(EditorBrowsableState.Never)]
492 		public new event EventHandler ForeColorChanged {
493 			add { base.ForeColorChanged += value; }
494 			remove { base.ForeColorChanged -= value; }
495 		}
496 
497 		[Browsable(false)]
498 		[EditorBrowsable(EditorBrowsableState.Never)]
499 		public new event EventHandler ImeModeChanged {
500 			add { base.ImeModeChanged += value; }
501 			remove { base.ImeModeChanged -= value; }
502 		}
503 
504 		[Browsable(false)]
505 		[EditorBrowsable(EditorBrowsableState.Never)]
506 		public new event PaintEventHandler Paint {
507 			add { base.Paint += value; }
508 			remove { base.Paint -= value; }
509 		}
510 
511 		static object DrawItemEvent = new object ();
512 		static object PanelClickEvent = new object ();
513 
514 		public event StatusBarDrawItemEventHandler DrawItem {
515 			add { Events.AddHandler (DrawItemEvent, value); }
516 			remove { Events.RemoveHandler (DrawItemEvent, value); }
517 		}
518 
519 		public event StatusBarPanelClickEventHandler PanelClick {
520 			add { Events.AddHandler (PanelClickEvent, value); }
521 			remove { Events.RemoveHandler (PanelClickEvent, value); }
522 		}
523 		#endregion	// Events
524 
525 
526 		#region Subclass StatusBarPanelCollection
527 		[ListBindable (false)]
528 		public class StatusBarPanelCollection :	 IList, ICollection, IEnumerable {
529 			#region Fields
530 			private StatusBar owner;
531 			private ArrayList panels = new ArrayList ();
532 			private int last_index_by_key;
533 			#endregion	// Fields
534 
535 			#region UIA Framework Events
536 			static object UIACollectionChangedEvent = new object ();
537 
538 			internal event CollectionChangeEventHandler UIACollectionChanged {
539 				add { owner.Events.AddHandler (UIACollectionChangedEvent, value); }
540 				remove { owner.Events.RemoveHandler (UIACollectionChangedEvent, value); }
541 			}
542 
OnUIACollectionChanged(CollectionChangeEventArgs e)543 			internal void OnUIACollectionChanged (CollectionChangeEventArgs e)
544 			{
545 				CollectionChangeEventHandler eh
546 					= (CollectionChangeEventHandler) owner.Events [UIACollectionChangedEvent];
547 				if (eh != null)
548 					eh (owner, e);
549 			}
550 			#endregion
551 
552 			#region Public Constructors
StatusBarPanelCollection(StatusBar owner)553 			public StatusBarPanelCollection (StatusBar owner)
554 			{
555 				this.owner = owner;
556 			}
557 
558 			#endregion	// Public Constructors
559 
560 			#region Private & Internal Methods
AddInternal(StatusBarPanel p, bool refresh)561 			private int AddInternal (StatusBarPanel p, bool refresh) {
562 				if (p == null)
563 					throw new ArgumentNullException ("value");
564 
565 				p.SetParent (owner);
566 				int res = panels.Add (p);
567 
568 				if (refresh) {
569 					owner.CalcPanelSizes ();
570 					owner.Refresh ();
571 				}
572 
573 				// UIA Framework Event: Panel Added
574 				OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Add, res));
575 
576 				return res;
577 			}
578 
579 			#endregion	// Private & Internal Methods
580 
581 			#region Public Instance Properties
582 			[Browsable(false)]
583 			[EditorBrowsable(EditorBrowsableState.Never)]
584 			public int Count {
585 				get { return panels.Count; }
586 			}
587 
588 			public bool IsReadOnly {
589 				get { return false; }
590 			}
591 
592 			public virtual StatusBarPanel this [int index] {
593 				get {
594 					if (index < 0 || index >= Count)
595 						throw new ArgumentOutOfRangeException ("index");
596 					return (StatusBarPanel) panels [index];
597 				}
598 				set {
599 					if (value == null)
600 						throw new ArgumentNullException ("index");
601 					if (index < 0 || index >= Count)
602 						throw new ArgumentOutOfRangeException ("index");
603 
604 					// UIA Framework Event: Panel Removed
605 					OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Remove, index));
606 
607 					value.SetParent (owner);
608 
609 					panels [index] = value;
610 
611 					// UIA Framework Event: Panel Added
612 					OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Add, index));
613 				}
614 			}
615 
616 			public virtual StatusBarPanel this [string key] {
617 				get {
618 					int index = IndexOfKey (key);
619 					if (index >= 0 && index < Count) {
620 						return (StatusBarPanel) panels [index];
621 					}
622 					return null;
623 				}
624 			}
625 
626 			#endregion	// Public Instance Properties
627 
628 			#region Public Instance Methods
Add(StatusBarPanel value)629 			public virtual int Add (StatusBarPanel value) {
630 				return AddInternal (value, true);
631 			}
632 
Add(string text)633 			public virtual StatusBarPanel Add (string text) {
634 				StatusBarPanel res = new StatusBarPanel ();
635 				res.Text = text;
636 				Add (res);
637 				return res;
638 			}
639 
AddRange(StatusBarPanel [] panels)640 			public virtual void AddRange (StatusBarPanel [] panels) {
641 				if (panels == null)
642 					throw new ArgumentNullException ("panels");
643 				if (panels.Length == 0)
644 					return;
645 
646 				for (int i = 0; i < panels.Length; i++)
647 					AddInternal (panels [i], false);
648 				owner.Refresh ();
649 			}
650 
Clear()651 			public virtual void Clear () {
652 				panels.Clear ();
653 
654 				owner.Refresh ();
655 
656 				// UIA Framework Event: Panel Cleared
657 				OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Refresh, -1));
658 			}
659 
Contains(StatusBarPanel panel)660 			public bool Contains (StatusBarPanel panel) {
661 				return panels.Contains (panel);
662 			}
663 
ContainsKey(string key)664 			public virtual bool ContainsKey (string key)
665 			{
666 				int index = IndexOfKey (key);
667 				return index >= 0 && index < Count;
668 			}
669 
GetEnumerator()670 			public IEnumerator GetEnumerator () {
671 				return panels.GetEnumerator ();
672 			}
673 
IndexOf(StatusBarPanel panel)674 			public int IndexOf (StatusBarPanel panel) {
675 				return panels.IndexOf (panel);
676 			}
677 
IndexOfKey(string key)678 			public virtual int IndexOfKey (string key)
679 			{
680 				if (key == null || key == string.Empty)
681 					return -1;
682 
683 				if (last_index_by_key >= 0 && last_index_by_key < Count &&
684 					String.Compare (((StatusBarPanel)panels [last_index_by_key]).Name, key, StringComparison.OrdinalIgnoreCase) == 0) {
685 					return last_index_by_key;
686 				}
687 
688 				for (int i = 0; i < Count; i++) {
689 					StatusBarPanel item;
690 					item = panels [i] as StatusBarPanel;
691 					if (item != null && String.Compare (item.Name, key, StringComparison.OrdinalIgnoreCase) == 0) {
692 						last_index_by_key = i;
693 						return i;
694 					}
695 				}
696 
697 				return -1;
698 			}
699 
Insert(int index, StatusBarPanel value)700 			public virtual void Insert (int index, StatusBarPanel value) {
701 				if (value == null)
702 					throw new ArgumentNullException ("value");
703 				if (index > Count)
704 					throw new ArgumentOutOfRangeException ("index");
705 				// TODO: InvalidArgumentException for bad AutoSize values
706 				// although it seems impossible to set it to a bad value
707 				value.SetParent (owner);
708 
709 				panels.Insert(index, value);
710 				owner.Refresh ();
711 
712 				// UIA Framework Event: Panel Added
713 				OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Add, index));
714 			}
715 
Remove(StatusBarPanel value)716 			public virtual void Remove (StatusBarPanel value) {
717 				int index = IndexOf (value);
718 				panels.Remove (value);
719 
720 				// UIA Framework Event: Panel Removed
721 				if (index >= 0)
722 					OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Remove, index));
723 			}
724 
RemoveAt(int index)725 			public virtual void RemoveAt (int index) {
726 				panels.RemoveAt (index);
727 
728 				// UIA Framework Event: Panel Removed
729 				OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Remove, index));
730 			}
731 
RemoveByKey(string key)732 			public virtual void RemoveByKey (string key)
733 			{
734 				int index = IndexOfKey (key);
735 				if (index >= 0 && index < Count)
736 					RemoveAt (index);
737 			}
738 
739 			#endregion	// Public Instance Methods
740 
741 			#region IList & ICollection Interfaces
742 			bool ICollection.IsSynchronized {
743 				get { return panels.IsSynchronized; }
744 			}
745 
746 			object ICollection.SyncRoot {
747 				get { return panels.SyncRoot; }
748 			}
749 
ICollection.CopyTo(Array dest, int index)750 			void ICollection.CopyTo (Array dest, int index)
751 			{
752 				panels.CopyTo (dest, index);
753 			}
754 
755 
756 			object IList.this [int index] {
757 				get { return this[index]; }
758 				set {
759 					if (!(value is StatusBarPanel))
760 						throw new ArgumentException ("Value must be of type StatusBarPanel.", "value");
761 
762 					this[index] = (StatusBarPanel)value;
763 				}
764 			}
765 
IList.Add(object value)766 			int IList.Add (object value) {
767 				if (!(value is StatusBarPanel))
768 					throw new ArgumentException ("Value must be of type StatusBarPanel.", "value");
769 
770 				return AddInternal ((StatusBarPanel)value, true);
771 			}
772 
IList.Contains(object panel)773 			bool IList.Contains (object panel) {
774 				return panels.Contains (panel);
775 			}
776 
IList.IndexOf(object panel)777 			int IList.IndexOf (object panel)
778 			{
779 				return panels.IndexOf (panel);
780 			}
781 
IList.Insert(int index, object value)782 			void IList.Insert (int index, object value)
783 			{
784 				if (!(value is StatusBarPanel))
785 					throw new ArgumentException ("Value must be of type StatusBarPanel.", "value");
786 
787 				Insert (index, (StatusBarPanel)value);
788 			}
789 
790 			bool IList.IsFixedSize {
791 				get { return false; }
792 			}
793 
IList.Remove(object value)794 			void IList.Remove (object value)
795 			{
796 				StatusBarPanel s = value as StatusBarPanel;
797 				Remove (s);
798 			}
799 			#endregion	// IList & ICollection Interfaces
800 		}
801 		#endregion	// Subclass StatusBarPanelCollection
802 	}
803 
804 }
805 
806