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; }
101 [EditorBrowsable (EditorBrowsableState
.Never
)]
102 protected override bool DoubleBuffered
{
104 return base.DoubleBuffered
;
107 base.DoubleBuffered
= value;
112 public override Font Font
{
113 get { return base.Font; }
123 [EditorBrowsable(EditorBrowsableState
.Never
)]
124 public override Color ForeColor
{
125 get { return base.ForeColor; }
126 set { base.ForeColor = value; }
130 [EditorBrowsable(EditorBrowsableState
.Never
)]
131 public new ImeMode ImeMode
{
132 get { return base.ImeMode; }
133 set { base.ImeMode = value; }
136 [MergableProperty(false)]
138 [DesignerSerializationVisibility(DesignerSerializationVisibility
.Content
)]
139 public StatusBarPanelCollection Panels
{
142 panels
= new StatusBarPanelCollection (this);
147 [DefaultValue(false)]
148 public bool ShowPanels
{
149 get { return show_panels; }
151 if (show_panels
== value)
159 public bool SizingGrip
{
160 get { return sizing_grip; }
162 if (sizing_grip
== value)
169 [DefaultValue(false)]
170 public new bool TabStop
{
171 get { return base.TabStop; }
172 set { base.TabStop = value; }
176 public override string Text
{
177 get { return base.Text; }
187 #endregion Public Instance Properties
189 #region Protected Instance Properties
190 protected override CreateParams CreateParams
{
192 return base.CreateParams
;
196 protected override ImeMode DefaultImeMode
{
197 get { return ImeMode.Disable; }
200 protected override Size DefaultSize
{
201 get { return ThemeEngine.Current.StatusBarDefaultSize; }
204 #endregion // Protected Instance Properties
206 #region Public Instance Methods
207 public override string ToString () {
208 return base.ToString () + ", Panels.Count: " + Panels
.Count
+
209 (Panels
.Count
> 0 ? ", Panels[0]: " + Panels
[0] : String
.Empty
);
212 #endregion // Public Instance Methods
214 #region Protected Instance Methods
215 protected override void CreateHandle ()
217 base.CreateHandle ();
220 protected override void Dispose (bool disposing
) {
221 base.Dispose (disposing
);
224 protected virtual void OnDrawItem (StatusBarDrawItemEventArgs e
) {
225 StatusBarDrawItemEventHandler eh
= (StatusBarDrawItemEventHandler
)(Events
[DrawItemEvent
]);
230 protected override void OnHandleCreated (EventArgs e
) {
231 base.OnHandleCreated (e
);
235 protected override void OnHandleDestroyed (EventArgs e
) {
236 base.OnHandleDestroyed (e
);
239 protected override void OnLayout (LayoutEventArgs e
) {
243 protected override void OnMouseDown (MouseEventArgs e
) {
248 float gap
= ThemeEngine
.Current
.StatusBarHorzGapWidth
;
249 for (int i
= 0; i
< panels
.Count
; i
++) {
250 float x
= panels
[i
].Width
+ prev_x
+ (i
== panels
.Count
- 1 ? gap
: gap
/ 2);
251 if (e
.X
>= prev_x
&& e
.X
<= x
) {
252 OnPanelClick (new StatusBarPanelClickEventArgs (panels
[i
],
253 e
.Button
, e
.Clicks
, e
.X
, e
.Y
));
259 base.OnMouseDown (e
);
262 protected virtual void OnPanelClick (StatusBarPanelClickEventArgs e
) {
263 StatusBarPanelClickEventHandler eh
= (StatusBarPanelClickEventHandler
)(Events
[PanelClickEvent
]);
268 protected override void OnResize (EventArgs e
)
272 if (Width
<= 0 || Height
<= 0)
278 protected override void WndProc(ref Message m
) {
279 base.WndProc (ref m
);
282 #endregion // Methods
285 #region Internal Methods
286 internal void OnDrawItemInternal (StatusBarDrawItemEventArgs e
)
291 internal void UpdatePanel (StatusBarPanel panel
)
293 if (panel
.AutoSize
== StatusBarPanelAutoSize
.Contents
) {
301 internal void UpdatePanelContents (StatusBarPanel panel
)
303 if (panel
.AutoSize
== StatusBarPanelAutoSize
.Contents
) {
309 Invalidate (new Rectangle (panel
.X
+ 2, 2, panel
.Width
- 4, bounds
.Height
- 4));
312 void UpdateStatusBar ()
318 internal override void OnPaintInternal (PaintEventArgs pevent
)
320 Draw (pevent
.Graphics
, pevent
.ClipRectangle
);
323 private void CalcPanelSizes ()
325 if (panels
== null || !show_panels
)
328 if (Width
== 0 || Height
== 0)
332 int gap
= ThemeEngine
.Current
.StatusBarHorzGapWidth
;
334 ArrayList springs
= null;
337 for (int i
= 0; i
< panels
.Count
; i
++) {
338 StatusBarPanel p
= panels
[i
];
340 if (p
.AutoSize
== StatusBarPanelAutoSize
.None
) {
345 if (p
.AutoSize
== StatusBarPanelAutoSize
.Contents
) {
346 int len
= (int) (DeviceContext
.MeasureString (p
.Text
, Font
).Width
+ 0.5F
);
347 p
.SetWidth (len
+ 8);
352 if (p
.AutoSize
== StatusBarPanelAutoSize
.Spring
) {
354 springs
= new ArrayList ();
364 int spring_total
= springs
.Count
;
365 int total_width
= Width
- taken
- (SizingGrip
? ThemeEngine
.Current
.StatusBarSizeGripWidth
: 0);
366 for (int i
= 0; i
< spring_total
; i
++) {
367 StatusBarPanel p
= (StatusBarPanel
) springs
[i
];
368 int width
= total_width
/ spring_total
;
369 p
.SetWidth (width
>= p
.MinWidth
? width
: p
.MinWidth
);
373 for (int i
= 0; i
< panels
.Count
; i
++) {
374 StatusBarPanel p
= panels
[i
];
376 taken
+= p
.Width
+ gap
;
380 private void Draw (Graphics dc
, Rectangle clip
)
382 ThemeEngine
.Current
.DrawStatusBar (dc
, clip
, this);
385 #endregion // Internal Methods
390 [EditorBrowsable(EditorBrowsableState
.Never
)]
391 public new event EventHandler BackColorChanged
{
392 add { base.BackColorChanged += value; }
393 remove { base.BackColorChanged -= value; }
397 [EditorBrowsable(EditorBrowsableState
.Never
)]
398 public new event EventHandler BackgroundImageChanged
{
399 add { base.BackgroundImageChanged += value; }
400 remove { base.BackgroundImageChanged -= value; }
405 [EditorBrowsable (EditorBrowsableState
.Never
)]
406 public new event EventHandler BackgroundImageLayoutChanged
408 add { base.BackgroundImageLayoutChanged += value; }
409 remove { base.BackgroundImageLayoutChanged -= value; }
414 [EditorBrowsable(EditorBrowsableState
.Never
)]
415 public new event EventHandler ForeColorChanged
{
416 add { base.ForeColorChanged += value; }
417 remove { base.ForeColorChanged -= value; }
421 [EditorBrowsable(EditorBrowsableState
.Never
)]
422 public new event EventHandler ImeModeChanged
{
423 add { base.ImeModeChanged += value; }
424 remove { base.ImeModeChanged -= value; }
428 [EditorBrowsable(EditorBrowsableState
.Never
)]
429 public new event PaintEventHandler Paint
{
430 add { base.Paint += value; }
431 remove { base.Paint -= value; }
434 static object DrawItemEvent
= new object ();
435 static object PanelClickEvent
= new object ();
437 public event StatusBarDrawItemEventHandler DrawItem
{
438 add { Events.AddHandler (DrawItemEvent, value); }
439 remove { Events.RemoveHandler (DrawItemEvent, value); }
442 public event StatusBarPanelClickEventHandler PanelClick
{
443 add { Events.AddHandler (PanelClickEvent, value); }
444 remove { Events.RemoveHandler (PanelClickEvent, value); }
449 #region Subclass StatusBarPanelCollection
451 [ListBindable (false)]
453 public class StatusBarPanelCollection
: IList
, ICollection
, IEnumerable
{
455 private StatusBar owner
;
456 private ArrayList panels
;
458 private int last_index_by_key
;
462 #region Public Constructors
463 public StatusBarPanelCollection (StatusBar owner
)
468 #endregion // Public Constructors
470 #region Private & Internal Methods
471 private int AddInternal (StatusBarPanel p
, bool refresh
) {
473 throw new ArgumentNullException ("value");
475 panels
= new ArrayList ();
477 int res
= panels
.Add (p
);
481 owner
.CalcPanelSizes ();
488 #endregion // Private & Internal Methods
490 #region Public Instance Properties
492 [EditorBrowsable(EditorBrowsableState
.Never
)]
501 public bool IsReadOnly
{
502 get { return false; }
505 public virtual StatusBarPanel
this [int index
] {
507 if (index
< 0 || index
>= Count
)
508 throw new ArgumentOutOfRangeException ("index");
509 return (StatusBarPanel
) panels
[index
];
513 throw new ArgumentNullException ("index");
514 if (index
< 0 || index
>= Count
)
515 throw new ArgumentOutOfRangeException ("index");
516 panels
[index
] = value;
522 public virtual StatusBarPanel
this [string key
] {
524 int index
= IndexOfKey (key
);
525 if (index
>= 0 && index
< Count
) {
526 return (StatusBarPanel
) panels
[index
];
533 #endregion // Public Instance Properties
535 #region Public Instance Methods
536 public virtual int Add (StatusBarPanel p
) {
537 return AddInternal (p
, true);
540 public virtual StatusBarPanel
Add (string text
) {
541 StatusBarPanel res
= new StatusBarPanel ();
547 public virtual void AddRange (StatusBarPanel
[] range
) {
549 throw new ArgumentNullException ("panels");
550 if (range
.Length
== 0)
553 panels
= new ArrayList (range
.Length
);
555 for (int i
= 0; i
< range
.Length
; i
++)
556 AddInternal (range
[i
], false);
560 public virtual void Clear () {
566 public bool Contains (StatusBarPanel panel
) {
567 return panels
.Contains (panel
);
571 public virtual bool ContainsKey (string key
)
573 int index
= IndexOfKey (key
);
574 return index
>= 0 && index
< Count
;
578 public IEnumerator
GetEnumerator () {
579 return panels
.GetEnumerator ();
582 public int IndexOf (StatusBarPanel panel
) {
583 return panels
.IndexOf (panel
);
587 public virtual int IndexOfKey (string key
)
589 if (key
== null || key
== string.Empty
)
592 if (last_index_by_key
>= 0 && last_index_by_key
< Count
&&
593 String
.Compare (((StatusBarPanel
)panels
[last_index_by_key
]).Name
, key
, StringComparison
.OrdinalIgnoreCase
) == 0) {
594 return last_index_by_key
;
597 for (int i
= 0; i
< Count
; i
++) {
599 item
= panels
[i
] as StatusBarPanel
;
600 if (item
!= null && String
.Compare (item
.Name
, key
, StringComparison
.OrdinalIgnoreCase
) == 0) {
601 last_index_by_key
= i
;
610 public virtual void Insert (int index
, StatusBarPanel
value) {
612 throw new ArgumentNullException ("value");
614 throw new ArgumentOutOfRangeException ("index");
615 // TODO: InvalidArgumentException for bad AutoSize values
616 // although it seems impossible to set it to a bad value
617 value.SetParent (owner
);
618 panels
[index
] = value;
623 public virtual void Remove (StatusBarPanel panel
) {
624 panels
.Remove (panel
);
627 public virtual void RemoveAt (int index
) {
628 panels
.RemoveAt (index
);
632 public virtual void RemoveByKey (string key
)
634 int index
= IndexOfKey (key
);
635 if (index
>= 0 && index
< Count
)
640 #endregion // Public Instance Methods
642 #region IList & ICollection Interfaces
643 bool ICollection
.IsSynchronized
{
644 get { return panels.IsSynchronized; }
647 object ICollection
.SyncRoot
{
648 get { return panels.SyncRoot; }
651 void ICollection
.CopyTo (Array dest
, int index
)
653 panels
.CopyTo (dest
, index
);
657 object IList
.this [int index
] {
658 get { return panels [index]; }
659 set { panels [index] = value; }
662 int IList
.Add (object value) {
663 return panels
.Add (value);
666 bool IList
.Contains (object panel
) {
667 return panels
.Contains (panel
);
670 int IList
.IndexOf (object panel
)
672 return panels
.IndexOf (panel
);
675 void IList
.Insert (int index
, object value)
677 panels
.Insert (index
, value);
680 bool IList
.IsFixedSize
{
681 get { return false; }
684 void IList
.Remove (object value)
686 panels
.Remove (value);
688 #endregion // IList & ICollection Interfaces
690 #endregion // Subclass StatusBarPanelCollection