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:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
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.
20 // Copyright (c) 2004-2005 Novell, Inc.
23 // Jackson Harper (jackson@ximian.com)
27 // - Change cursor when mouse is over grip
30 using System
.Collections
;
31 using System
.ComponentModel
;
32 using System
.ComponentModel
.Design
;
34 using System
.Drawing
.Text
;
35 using System
.Drawing
.Imaging
;
36 using System
.Runtime
.InteropServices
;
38 namespace System
.Windows
.Forms
{
41 [ClassInterface (ClassInterfaceType
.AutoDispatch
)]
43 [DefaultEvent("PanelClick")]
44 [Designer("System.Windows.Forms.Design.StatusBarDesigner, " + Consts
.AssemblySystem_Design
, "System.ComponentModel.Design.IDesigner")]
45 [DefaultProperty("Text")]
46 public class StatusBar
: Control
{
48 private StatusBarPanelCollection panels
;
50 private bool show_panels
= false;
51 private bool sizing_grip
= true;
55 #region Public Constructors
58 Dock
= DockStyle
.Bottom
;
60 this.SetStyle(ControlStyles
.UserPaint
| ControlStyles
.Selectable
, false);
62 #endregion // Public Constructors
64 #region Public Instance Properties
66 [EditorBrowsable(EditorBrowsableState
.Never
)]
67 public override Color BackColor
{
68 get { return base.BackColor; }
69 set { base.BackColor = value; }
73 [EditorBrowsable(EditorBrowsableState
.Never
)]
74 public override Image BackgroundImage
{
75 get { return base.BackgroundImage; }
76 set { base.BackgroundImage = value; }
81 [EditorBrowsable (EditorBrowsableState
.Never
)]
82 public override ImageLayout BackgroundImageLayout
{
84 return base.BackgroundImageLayout
;
87 base.BackgroundImageLayout
= value;
93 [DefaultValue(DockStyle
.Bottom
)]
94 public override DockStyle Dock
{
95 get { return base.Dock; }
96 set { base.Dock = value; }
100 [EditorBrowsable (EditorBrowsableState
.Never
)]
101 protected override bool DoubleBuffered
{
103 return base.DoubleBuffered
;
106 base.DoubleBuffered
= value;
111 public override Font Font
{
112 get { return base.Font; }
122 [EditorBrowsable(EditorBrowsableState
.Never
)]
123 public override Color ForeColor
{
124 get { return base.ForeColor; }
125 set { base.ForeColor = value; }
129 [EditorBrowsable(EditorBrowsableState
.Never
)]
130 public new ImeMode ImeMode
{
131 get { return base.ImeMode; }
132 set { base.ImeMode = value; }
135 [MergableProperty(false)]
137 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Content
)]
138 public StatusBarPanelCollection Panels
{
141 panels
= new StatusBarPanelCollection (this);
146 [DefaultValue(false)]
147 public bool ShowPanels
{
148 get { return show_panels; }
150 if (show_panels
== value)
158 public bool SizingGrip
{
159 get { return sizing_grip; }
161 if (sizing_grip
== value)
168 [DefaultValue(false)]
169 public new bool TabStop
{
170 get { return base.TabStop; }
171 set { base.TabStop = value; }
175 public override string Text
{
176 get { return base.Text; }
186 #endregion Public Instance Properties
188 #region Protected Instance Properties
189 protected override CreateParams CreateParams
{
191 return base.CreateParams
;
195 protected override ImeMode DefaultImeMode
{
196 get { return ImeMode.Disable; }
199 protected override Size DefaultSize
{
200 get { return ThemeEngine.Current.StatusBarDefaultSize; }
203 #endregion // Protected Instance Properties
205 #region Public Instance Methods
206 public override string ToString () {
207 return base.ToString () + ", Panels.Count: " + Panels
.Count
+
208 (Panels
.Count
> 0 ? ", Panels[0]: " + Panels
[0] : String
.Empty
);
211 #endregion // Public Instance Methods
213 #region Protected Instance Methods
214 protected override void CreateHandle ()
216 base.CreateHandle ();
219 protected override void Dispose (bool disposing
) {
220 base.Dispose (disposing
);
223 protected virtual void OnDrawItem (StatusBarDrawItemEventArgs e
) {
224 StatusBarDrawItemEventHandler eh
= (StatusBarDrawItemEventHandler
)(Events
[DrawItemEvent
]);
229 protected override void OnHandleCreated (EventArgs e
) {
230 base.OnHandleCreated (e
);
234 protected override void OnHandleDestroyed (EventArgs e
) {
235 base.OnHandleDestroyed (e
);
238 protected override void OnLayout (LayoutEventArgs e
) {
242 protected override void OnMouseDown (MouseEventArgs e
) {
247 float gap
= ThemeEngine
.Current
.StatusBarHorzGapWidth
;
248 for (int i
= 0; i
< panels
.Count
; i
++) {
249 float x
= panels
[i
].Width
+ prev_x
+ (i
== panels
.Count
- 1 ? gap
: gap
/ 2);
250 if (e
.X
>= prev_x
&& e
.X
<= x
) {
251 OnPanelClick (new StatusBarPanelClickEventArgs (panels
[i
],
252 e
.Button
, e
.Clicks
, e
.X
, e
.Y
));
258 base.OnMouseDown (e
);
261 protected virtual void OnPanelClick (StatusBarPanelClickEventArgs e
) {
262 StatusBarPanelClickEventHandler eh
= (StatusBarPanelClickEventHandler
)(Events
[PanelClickEvent
]);
267 protected override void OnResize (EventArgs e
)
271 if (Width
<= 0 || Height
<= 0)
277 protected override void WndProc(ref Message m
) {
278 base.WndProc (ref m
);
281 #endregion // Methods
284 #region Internal Methods
285 internal void OnDrawItemInternal (StatusBarDrawItemEventArgs e
)
290 internal void UpdatePanel (StatusBarPanel panel
)
292 if (panel
.AutoSize
== StatusBarPanelAutoSize
.Contents
) {
300 internal void UpdatePanelContents (StatusBarPanel panel
)
302 if (panel
.AutoSize
== StatusBarPanelAutoSize
.Contents
) {
308 Invalidate (new Rectangle (panel
.X
+ 2, 2, panel
.Width
- 4, bounds
.Height
- 4));
311 void UpdateStatusBar ()
317 internal override void OnPaintInternal (PaintEventArgs pevent
)
319 Draw (pevent
.Graphics
, pevent
.ClipRectangle
);
322 private void CalcPanelSizes ()
324 if (panels
== null || !show_panels
)
327 if (Width
== 0 || Height
== 0)
331 int gap
= ThemeEngine
.Current
.StatusBarHorzGapWidth
;
333 ArrayList springs
= null;
336 for (int i
= 0; i
< panels
.Count
; i
++) {
337 StatusBarPanel p
= panels
[i
];
339 if (p
.AutoSize
== StatusBarPanelAutoSize
.None
) {
344 if (p
.AutoSize
== StatusBarPanelAutoSize
.Contents
) {
345 int len
= (int) (DeviceContext
.MeasureString (p
.Text
, Font
).Width
+ 0.5F
);
346 p
.SetWidth (len
+ 8);
351 if (p
.AutoSize
== StatusBarPanelAutoSize
.Spring
) {
353 springs
= new ArrayList ();
363 int spring_total
= springs
.Count
;
364 int total_width
= Width
- taken
- (SizingGrip
? ThemeEngine
.Current
.StatusBarSizeGripWidth
: 0);
365 for (int i
= 0; i
< spring_total
; i
++) {
366 StatusBarPanel p
= (StatusBarPanel
) springs
[i
];
367 int width
= total_width
/ spring_total
;
368 p
.SetWidth (width
>= p
.MinWidth
? width
: p
.MinWidth
);
372 for (int i
= 0; i
< panels
.Count
; i
++) {
373 StatusBarPanel p
= panels
[i
];
375 taken
+= p
.Width
+ gap
;
379 private void Draw (Graphics dc
, Rectangle clip
)
381 ThemeEngine
.Current
.DrawStatusBar (dc
, clip
, this);
384 #endregion // Internal Methods
389 [EditorBrowsable(EditorBrowsableState
.Never
)]
390 public new event EventHandler BackColorChanged
{
391 add { base.BackColorChanged += value; }
392 remove { base.BackColorChanged -= value; }
396 [EditorBrowsable(EditorBrowsableState
.Never
)]
397 public new event EventHandler BackgroundImageChanged
{
398 add { base.BackgroundImageChanged += value; }
399 remove { base.BackgroundImageChanged -= value; }
404 [EditorBrowsable (EditorBrowsableState
.Never
)]
405 public new event EventHandler BackgroundImageLayoutChanged
407 add { base.BackgroundImageLayoutChanged += value; }
408 remove { base.BackgroundImageLayoutChanged -= value; }
413 [EditorBrowsable(EditorBrowsableState
.Never
)]
414 public new event EventHandler ForeColorChanged
{
415 add { base.ForeColorChanged += value; }
416 remove { base.ForeColorChanged -= value; }
420 [EditorBrowsable(EditorBrowsableState
.Never
)]
421 public new event EventHandler ImeModeChanged
{
422 add { base.ImeModeChanged += value; }
423 remove { base.ImeModeChanged -= value; }
427 [EditorBrowsable(EditorBrowsableState
.Never
)]
428 public new event PaintEventHandler Paint
{
429 add { base.Paint += value; }
430 remove { base.Paint -= value; }
433 static object DrawItemEvent
= new object ();
434 static object PanelClickEvent
= new object ();
436 public event StatusBarDrawItemEventHandler DrawItem
{
437 add { Events.AddHandler (DrawItemEvent, value); }
438 remove { Events.RemoveHandler (DrawItemEvent, value); }
441 public event StatusBarPanelClickEventHandler PanelClick
{
442 add { Events.AddHandler (PanelClickEvent, value); }
443 remove { Events.RemoveHandler (PanelClickEvent, value); }
448 #region Subclass StatusBarPanelCollection
450 [ListBindable (false)]
452 public class StatusBarPanelCollection
: IList
, ICollection
, IEnumerable
{
454 private StatusBar owner
;
455 private ArrayList panels
;
457 private int last_index_by_key
;
461 #region Public Constructors
462 public StatusBarPanelCollection (StatusBar owner
)
467 #endregion // Public Constructors
469 #region Private & Internal Methods
470 private int AddInternal (StatusBarPanel p
, bool refresh
) {
472 throw new ArgumentNullException ("value");
474 panels
= new ArrayList ();
476 int res
= panels
.Add (p
);
480 owner
.CalcPanelSizes ();
487 #endregion // Private & Internal Methods
489 #region Public Instance Properties
491 [EditorBrowsable(EditorBrowsableState
.Never
)]
500 public bool IsReadOnly
{
501 get { return false; }
504 public virtual StatusBarPanel
this [int index
] {
506 if (index
< 0 || index
>= Count
)
507 throw new ArgumentOutOfRangeException ("index");
508 return (StatusBarPanel
) panels
[index
];
512 throw new ArgumentNullException ("index");
513 if (index
< 0 || index
>= Count
)
514 throw new ArgumentOutOfRangeException ("index");
515 panels
[index
] = value;
521 public virtual StatusBarPanel
this [string key
] {
523 int index
= IndexOfKey (key
);
524 if (index
>= 0 && index
< Count
) {
525 return (StatusBarPanel
) panels
[index
];
532 #endregion // Public Instance Properties
534 #region Public Instance Methods
535 public virtual int Add (StatusBarPanel p
) {
536 return AddInternal (p
, true);
539 public virtual StatusBarPanel
Add (string text
) {
540 StatusBarPanel res
= new StatusBarPanel ();
546 public virtual void AddRange (StatusBarPanel
[] range
) {
548 throw new ArgumentNullException ("panels");
549 if (range
.Length
== 0)
552 panels
= new ArrayList (range
.Length
);
554 for (int i
= 0; i
< range
.Length
; i
++)
555 AddInternal (range
[i
], false);
559 public virtual void Clear () {
565 public bool Contains (StatusBarPanel panel
) {
566 return panels
.Contains (panel
);
570 public virtual bool ContainsKey (string key
)
572 int index
= IndexOfKey (key
);
573 return index
>= 0 && index
< Count
;
577 public IEnumerator
GetEnumerator () {
578 return panels
.GetEnumerator ();
581 public int IndexOf (StatusBarPanel panel
) {
582 return panels
.IndexOf (panel
);
586 public virtual int IndexOfKey (string key
)
588 if (key
== null || key
== string.Empty
)
591 if (last_index_by_key
>= 0 && last_index_by_key
< Count
&&
592 String
.Compare (((StatusBarPanel
)panels
[last_index_by_key
]).Name
, key
, StringComparison
.OrdinalIgnoreCase
) == 0) {
593 return last_index_by_key
;
596 for (int i
= 0; i
< Count
; i
++) {
598 item
= panels
[i
] as StatusBarPanel
;
599 if (item
!= null && String
.Compare (item
.Name
, key
, StringComparison
.OrdinalIgnoreCase
) == 0) {
600 last_index_by_key
= i
;
609 public virtual void Insert (int index
, StatusBarPanel
value) {
611 throw new ArgumentNullException ("value");
613 throw new ArgumentOutOfRangeException ("index");
614 // TODO: InvalidArgumentException for bad AutoSize values
615 // although it seems impossible to set it to a bad value
616 value.SetParent (owner
);
617 panels
[index
] = value;
622 public virtual void Remove (StatusBarPanel panel
) {
623 panels
.Remove (panel
);
626 public virtual void RemoveAt (int index
) {
627 panels
.RemoveAt (index
);
631 public virtual void RemoveByKey (string key
)
633 int index
= IndexOfKey (key
);
634 if (index
>= 0 && index
< Count
)
639 #endregion // Public Instance Methods
641 #region IList & ICollection Interfaces
642 bool ICollection
.IsSynchronized
{
643 get { return panels.IsSynchronized; }
646 object ICollection
.SyncRoot
{
647 get { return panels.SyncRoot; }
650 void ICollection
.CopyTo (Array dest
, int index
)
652 panels
.CopyTo (dest
, index
);
656 object IList
.this [int index
] {
657 get { return panels [index]; }
658 set { panels [index] = value; }
661 int IList
.Add (object value) {
662 return panels
.Add (value);
665 bool IList
.Contains (object panel
) {
666 return panels
.Contains (panel
);
669 int IList
.IndexOf (object panel
)
671 return panels
.IndexOf (panel
);
674 void IList
.Insert (int index
, object value)
676 panels
.Insert (index
, value);
679 bool IList
.IsFixedSize
{
680 get { return false; }
683 void IList
.Remove (object value)
685 panels
.Remove (value);
687 #endregion // IList & ICollection Interfaces
689 #endregion // Subclass StatusBarPanelCollection