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;
37 namespace System.Windows.Forms {
38 [DefaultEvent("PanelClick")]
39 [Designer("System.Windows.Forms.Design.StatusBarDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
40 [DefaultProperty("Text")]
41 public class StatusBar : Control {
43 private StatusBarPanelCollection panels;
45 private bool show_panels = false;
46 private bool sizing_grip = true;
50 #region Public Constructors
51 [MonoTODO("Change cursor when mouse is over grip")]
54 base.Dock = DockStyle.Bottom;
55 Anchor = AnchorStyles.Top | AnchorStyles.Left;
57 this.SetStyle(ControlStyles.UserPaint | ControlStyles.Selectable, false);
59 #endregion // Public Constructors
61 #region Public Instance Properties
63 [EditorBrowsable(EditorBrowsableState.Never)]
64 public Color BackColor {
65 get { return base.BackColor; }
67 if (value == BackColor)
69 base.BackColor = value;
70 if (BackColorChanged != null)
71 BackColorChanged (this, EventArgs.Empty);
77 [EditorBrowsable(EditorBrowsableState.Never)]
78 public Image BackgroundImage {
79 get { return base.BackgroundImage; }
81 if (value == BackgroundImage)
83 base.BackgroundImage = value;
84 if (BackgroundImageChanged != null)
85 BackgroundImageChanged (this, EventArgs.Empty);
90 [DefaultValue(DockStyle.Bottom)]
91 public override DockStyle Dock {
92 get { return base.Dock; }
102 public override Font Font {
103 get { return base.Font; }
113 [EditorBrowsable(EditorBrowsableState.Never)]
114 public Color ForeColor {
115 get { return base.ForeColor; }
117 if (value == ForeColor)
119 if (ForeColorChanged != null)
120 ForeColorChanged (this, EventArgs.Empty);
126 [EditorBrowsable(EditorBrowsableState.Never)]
127 public new ImeMode ImeMode {
128 get { return base.ImeMode; }
130 if (value == ImeMode)
132 base.ImeMode = value;
133 if (ImeModeChanged != null)
134 ImeModeChanged (this, EventArgs.Empty);
138 [MergableProperty(false)]
140 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
141 public StatusBarPanelCollection Panels {
144 panels = new StatusBarPanelCollection (this);
149 [DefaultValue(false)]
150 public bool ShowPanels {
151 get { return show_panels; }
153 if (show_panels == value)
160 public bool SizingGrip {
161 get { return sizing_grip; }
163 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 if (DrawItem != null)
229 protected override void OnHandleCreated (EventArgs e) {
230 base.OnHandleCreated (e);
233 protected override void OnHandleDestroyed (EventArgs e) {
234 base.OnHandleDestroyed (e);
237 protected override void OnLayout (LayoutEventArgs e) {
241 protected override void OnMouseDown (MouseEventArgs e) {
246 float gap = ThemeEngine.Current.StatusBarHorzGapWidth;
247 for (int i = 0; i < panels.Count; i++) {
248 float x = panels [i].Width + prev_x + (i == panels.Count - 1 ? gap : gap / 2);
249 if (e.X >= prev_x && e.X <= x) {
250 OnPanelClick (new StatusBarPanelClickEventArgs (panels [i],
251 e.Button, e.Clicks, e.X, e.Y));
257 base.OnMouseDown (e);
260 protected virtual void OnPanelClick (StatusBarPanelClickEventArgs e) {
261 if (PanelClick != null)
262 PanelClick (this, e);
265 protected override void OnResize (EventArgs e)
269 if (Width <= 0 || Height <= 0)
275 protected override void WndProc(ref Message m) {
276 switch ((Msg) m.Msg) {
278 PaintEventArgs paint_event;
280 paint_event = XplatUI.PaintEventStart (Handle, true);
281 DoPaint (paint_event);
282 XplatUI.PaintEventEnd (Handle, true);
286 base.WndProc (ref m);
289 #endregion // Methods
292 #region Internal Methods
293 internal void OnDrawItemInternal (StatusBarDrawItemEventArgs e)
298 private void DoPaint (PaintEventArgs pevent)
300 if (Width <= 0 || Height <= 0 || Visible == false)
304 Draw (pevent.Graphics, pevent.ClipRectangle);
307 private void CalcPanelSizes ()
309 if (panels == null || !show_panels)
312 if (Width == 0 || Height == 0)
315 int gap = ThemeEngine.Current.StatusBarHorzGapWidth;
317 ArrayList springs = null;
318 for (int i = 0; i < panels.Count; i++) {
319 StatusBarPanel p = panels [i];
320 if (p.AutoSize == StatusBarPanelAutoSize.None) {
325 if (p.AutoSize == StatusBarPanelAutoSize.Contents) {
326 int len = (int) (DeviceContext.MeasureString (p.Text, Font).Width + 0.5F);
327 p.Width = (int) (len + 8);
332 if (p.AutoSize == StatusBarPanelAutoSize.Spring) {
334 springs = new ArrayList ();
344 int spring_total = springs.Count;
345 int total_width = Width - taken - (SizingGrip ? ThemeEngine.Current.StatusBarSizeGripWidth : 0);
346 for (int i = 0; i < spring_total; i++) {
347 StatusBarPanel p = (StatusBarPanel) springs [i];
348 int width = total_width / spring_total;
349 p.Width = (width >= p.MinWidth ? width : p.MinWidth);
353 private void Draw (Graphics dc, Rectangle clip)
355 ThemeEngine.Current.DrawStatusBar (dc, this.ClientRectangle, this);
357 #endregion // Internal Methods
362 [EditorBrowsable(EditorBrowsableState.Never)]
363 public new event EventHandler BackColorChanged;
366 [EditorBrowsable(EditorBrowsableState.Never)]
367 public new event EventHandler BackgroundImageChanged;
370 [EditorBrowsable(EditorBrowsableState.Never)]
371 public new event EventHandler ForeColorChanged;
374 [EditorBrowsable(EditorBrowsableState.Never)]
375 public new event EventHandler ImeModeChanged;
377 public event StatusBarDrawItemEventHandler DrawItem;
380 [EditorBrowsable(EditorBrowsableState.Never)]
381 public new event PaintEventHandler Paint;
382 public event StatusBarPanelClickEventHandler PanelClick;
386 #region Subclass StatusBarPanelCollection
387 public class StatusBarPanelCollection : IList, ICollection, IEnumerable {
389 private StatusBar owner;
390 private ArrayList panels;
393 #region Public Constructors
394 public StatusBarPanelCollection (StatusBar owner)
399 #endregion // Public Constructors
401 #region Private & Internal Methods
402 private int AddInternal (StatusBarPanel p, bool refresh) {
404 throw new ArgumentNullException ("value");
406 panels = new ArrayList ();
408 int res = panels.Add (p);
412 owner.CalcPanelSizes ();
419 #endregion // Private & Internal Methods
421 #region Public Instance Properties
423 [EditorBrowsable(EditorBrowsableState.Never)]
424 public virtual int Count {
432 public virtual bool IsReadOnly {
433 get { return false; }
436 public virtual StatusBarPanel this [int index] {
438 if (index < 0 || index >= Count)
439 throw new ArgumentOutOfRangeException ("index");
440 return (StatusBarPanel) panels [index];
444 throw new ArgumentNullException ("index");
445 if (index < 0 || index >= Count)
446 throw new ArgumentOutOfRangeException ("index");
447 panels [index] = value;
451 #endregion // Public Instance Properties
453 #region Public Instance Methods
454 public virtual int Add (StatusBarPanel p) {
455 return AddInternal (p, true);
458 public virtual StatusBarPanel Add (string text) {
459 StatusBarPanel res = new StatusBarPanel ();
465 public virtual void AddRange (StatusBarPanel [] range) {
467 throw new ArgumentNullException ("panels");
468 if (range.Length == 0)
471 panels = new ArrayList (range.Length);
473 for (int i = 0; i < range.Length; i++)
474 AddInternal (range [i], false);
478 public virtual void Clear () {
484 public virtual bool Contains (StatusBarPanel panel) {
485 return panels.Contains (panel);
488 public virtual IEnumerator GetEnumerator () {
489 return panels.GetEnumerator ();
492 public virtual int IndexOf (StatusBarPanel panel) {
493 return panels.IndexOf (panel);
496 public virtual void Insert (int index, StatusBarPanel value) {
498 throw new ArgumentNullException ("value");
500 throw new ArgumentOutOfRangeException ("index");
501 // TODO: InvalidArgumentException for bad AutoSize values
502 // although it seems impossible to set it to a bad value
503 value.SetParent (owner);
504 panels [index] = value;
509 public virtual void Remove (StatusBarPanel panel) {
510 panels.Remove (panel);
513 public virtual void RemoveAt (int index) {
514 panels.RemoveAt (index);
517 #endregion // Public Instance Methods
519 #region IList & ICollection Interfaces
520 bool ICollection.IsSynchronized {
521 get { return panels.IsSynchronized; }
524 object ICollection.SyncRoot {
525 get { return panels.SyncRoot; }
528 void ICollection.CopyTo (Array dest, int index)
530 panels.CopyTo (dest, index);
534 object IList.this [int index] {
535 get { return panels [index]; }
536 set { panels [index] = value; }
539 int IList.Add (object value) {
540 return panels.Add (value);
543 bool IList.Contains (object panel) {
544 return panels.Contains (panel);
547 int IList.IndexOf (object panel)
549 return panels.IndexOf (panel);
552 void IList.Insert (int index, object value)
554 panels.Insert (index, value);
557 bool IList.IsFixedSize {
558 get { return false; }
561 void IList.Remove (object value)
563 panels.Remove (value);
565 #endregion // IList & ICollection Interfaces
567 #endregion // Subclass StatusBarPanelCollection