[LoongArch64] Part-5:add loongarch support in some files for LoongArch64. (#21769)
[mono-project.git] / mcs / class / System.Windows.Forms / System.Windows.Forms / StatusBar.cs
blobd7d4fc2184807ec6c27e1e6404f38874150c403c
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.
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.
22 // Authors:
23 // Jackson Harper (jackson@ximian.com)
26 // TODO:
27 // - Change cursor when mouse is over grip
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;
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;
48 private bool show_panels = false;
49 private bool sizing_grip = true;
51 // Stuff for panel Tooltips
52 private Timer tooltip_timer;
53 private ToolTip tooltip_window;
54 private StatusBarPanel tooltip_currently_showing;
55 #endregion // Fields
57 #region Public Constructors
58 public StatusBar ()
60 Dock = DockStyle.Bottom;
61 this.TabStop = false;
62 this.SetStyle(ControlStyles.UserPaint | ControlStyles.Selectable, false);
64 // For displaying/hiding tooltips
65 MouseMove += new MouseEventHandler (StatusBar_MouseMove);
66 MouseLeave += new EventHandler (StatusBar_MouseLeave);
68 #endregion // Public Constructors
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; }
78 [Browsable(false)]
79 [EditorBrowsable(EditorBrowsableState.Never)]
80 public override Image BackgroundImage {
81 get { return base.BackgroundImage; }
82 set { base.BackgroundImage = value; }
85 [Browsable (false)]
86 [EditorBrowsable (EditorBrowsableState.Never)]
87 public override ImageLayout BackgroundImageLayout {
88 get {
89 return base.BackgroundImageLayout;
91 set {
92 base.BackgroundImageLayout = value;
96 [Localizable(true)]
97 [DefaultValue(DockStyle.Bottom)]
98 public override DockStyle Dock {
99 get { return base.Dock; }
100 set { base.Dock = value; }
103 [EditorBrowsable (EditorBrowsableState.Never)]
104 protected override bool DoubleBuffered {
105 get {
106 return base.DoubleBuffered;
108 set {
109 base.DoubleBuffered = value;
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 ();
124 [Browsable(false)]
125 [EditorBrowsable(EditorBrowsableState.Never)]
126 public override Color ForeColor {
127 get { return base.ForeColor; }
128 set { base.ForeColor = value; }
131 [Browsable(false)]
132 [EditorBrowsable(EditorBrowsableState.Never)]
133 public new ImeMode ImeMode {
134 get { return base.ImeMode; }
135 set { base.ImeMode = value; }
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;
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 ();
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 ();
171 [DefaultValue(false)]
172 public new bool TabStop {
173 get { return base.TabStop; }
174 set { base.TabStop = value; }
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 ();
189 #endregion Public Instance Properties
191 #region Protected Instance Properties
192 protected override CreateParams CreateParams {
193 get {
194 return base.CreateParams;
198 protected override ImeMode DefaultImeMode {
199 get { return ImeMode.Disable; }
202 protected override Size DefaultSize {
203 get { return ThemeEngine.Current.StatusBarDefaultSize; }
206 #endregion // Protected Instance Properties
208 #region Public Instance Methods
209 public override string ToString () {
210 return base.ToString () + ", Panels.Count: " + Panels.Count +
211 (Panels.Count > 0 ? ", Panels[0]: " + Panels [0] : String.Empty);
214 #endregion // Public Instance Methods
216 #region Protected Instance Methods
217 protected override void CreateHandle ()
219 base.CreateHandle ();
222 protected override void Dispose (bool disposing) {
223 if (!IsDisposed && disposing)
225 if (tooltip_timer != null)
226 tooltip_timer.Dispose();
228 if (tooltip_window != null)
229 tooltip_window.Dispose();
231 if (panels != null) {
232 var copiedPanels = new StatusBarPanel [panels.Count];
233 ((ICollection) panels).CopyTo (copiedPanels, 0);
234 panels.Clear ();
236 foreach (StatusBarPanel panel in copiedPanels) {
237 panel.Dispose ();
242 base.Dispose (disposing);
245 protected virtual void OnDrawItem (StatusBarDrawItemEventArgs sbdievent) {
246 StatusBarDrawItemEventHandler eh = (StatusBarDrawItemEventHandler)(Events [DrawItemEvent]);
247 if (eh != null)
248 eh (this, sbdievent);
251 protected override void OnHandleCreated (EventArgs e) {
252 base.OnHandleCreated (e);
253 CalcPanelSizes ();
256 protected override void OnHandleDestroyed (EventArgs e) {
257 base.OnHandleDestroyed (e);
260 protected override void OnLayout (LayoutEventArgs levent) {
261 base.OnLayout (levent);
264 protected override void OnMouseDown (MouseEventArgs e) {
265 if (panels == null)
266 return;
268 float prev_x = 0;
269 float gap = ThemeEngine.Current.StatusBarHorzGapWidth;
270 for (int i = 0; i < panels.Count; i++) {
271 float x = panels [i].Width + prev_x + (i == panels.Count - 1 ? gap : gap / 2);
272 if (e.X >= prev_x && e.X <= x) {
273 OnPanelClick (new StatusBarPanelClickEventArgs (panels [i],
274 e.Button, e.Clicks, e.X, e.Y));
275 break;
277 prev_x = x;
280 base.OnMouseDown (e);
283 protected virtual void OnPanelClick (StatusBarPanelClickEventArgs e) {
284 StatusBarPanelClickEventHandler eh = (StatusBarPanelClickEventHandler)(Events [PanelClickEvent]);
285 if (eh != null)
286 eh (this, e);
289 protected override void OnResize (EventArgs e)
291 base.OnResize (e);
293 if (Width <= 0 || Height <= 0)
294 return;
296 UpdateStatusBar ();
299 protected override void WndProc(ref Message m) {
300 base.WndProc (ref m);
303 #endregion // Methods
306 #region Internal Methods
307 internal void OnDrawItemInternal (StatusBarDrawItemEventArgs e)
309 OnDrawItem (e);
312 internal void UpdatePanel (StatusBarPanel panel)
314 if (panel.AutoSize == StatusBarPanelAutoSize.Contents) {
315 UpdateStatusBar ();
316 return;
319 UpdateStatusBar ();
322 internal void UpdatePanelContents (StatusBarPanel panel)
324 if (panel.AutoSize == StatusBarPanelAutoSize.Contents) {
325 UpdateStatusBar ();
326 Invalidate ();
327 return;
330 Invalidate (new Rectangle (panel.X + 2, 2, panel.Width - 4, bounds.Height - 4));
333 void UpdateStatusBar ()
335 CalcPanelSizes ();
336 Refresh ();
339 internal override void OnPaintInternal (PaintEventArgs pevent)
341 Draw (pevent.Graphics, pevent.ClipRectangle);
344 private void CalcPanelSizes ()
346 if (panels == null || !show_panels)
347 return;
349 if (Width == 0 || Height == 0)
350 return;
352 int border = 2;
353 int gap = ThemeEngine.Current.StatusBarHorzGapWidth;
354 int taken = 0;
355 ArrayList springs = null;
357 taken = border;
358 for (int i = 0; i < panels.Count; i++) {
359 StatusBarPanel p = panels [i];
361 if (p.AutoSize == StatusBarPanelAutoSize.None) {
362 taken += p.Width;
363 taken += gap;
364 continue;
366 if (p.AutoSize == StatusBarPanelAutoSize.Contents) {
367 int len = (int)(TextRenderer.MeasureString (p.Text, Font).Width + 0.5F);
368 if (p.Icon != null) {
369 len += 21;
371 p.SetWidth (len + 8);
372 taken += p.Width;
373 taken += gap;
374 continue;
376 if (p.AutoSize == StatusBarPanelAutoSize.Spring) {
377 if (springs == null)
378 springs = new ArrayList ();
379 springs.Add (p);
380 taken += gap;
381 continue;
385 if (springs != null) {
386 int spring_total = springs.Count;
387 int total_width = Width - taken - (SizingGrip ? ThemeEngine.Current.StatusBarSizeGripWidth : 0);
388 for (int i = 0; i < spring_total; i++) {
389 StatusBarPanel p = (StatusBarPanel)springs[i];
390 int width = total_width / spring_total;
391 p.SetWidth(width >= p.MinWidth ? width : p.MinWidth);
395 taken = border;
396 for (int i = 0; i < panels.Count; i++) {
397 StatusBarPanel p = panels [i];
398 p.X = taken;
399 taken += p.Width + gap;
403 private void Draw (Graphics dc, Rectangle clip)
405 ThemeEngine.Current.DrawStatusBar (dc, clip, this);
408 #endregion // Internal Methods
410 #region Stuff for ToolTips
411 private void StatusBar_MouseMove (object sender, MouseEventArgs e)
413 if (!show_panels)
414 return;
416 StatusBarPanel p = GetPanelAtPoint (e.Location);
418 if (p != tooltip_currently_showing)
419 MouseLeftPanel (tooltip_currently_showing);
421 if (p != null && tooltip_currently_showing == null)
422 MouseEnteredPanel (p);
425 private void StatusBar_MouseLeave (object sender, EventArgs e)
427 if (tooltip_currently_showing != null)
428 MouseLeftPanel (tooltip_currently_showing);
431 private StatusBarPanel GetPanelAtPoint (Point point)
433 foreach (StatusBarPanel p in Panels)
434 if (point.X >= p.X && point.X <= (p.X + p.Width))
435 return p;
437 return null;
440 private void MouseEnteredPanel (StatusBarPanel item)
442 tooltip_currently_showing = item;
443 ToolTipTimer.Start ();
446 private void MouseLeftPanel (StatusBarPanel item)
448 ToolTipTimer.Stop ();
449 ToolTipWindow.Hide (this);
450 tooltip_currently_showing = null;
453 private Timer ToolTipTimer {
454 get {
455 if (tooltip_timer == null) {
456 tooltip_timer = new Timer ();
457 tooltip_timer.Enabled = false;
458 tooltip_timer.Interval = 500;
459 tooltip_timer.Tick += new EventHandler (ToolTipTimer_Tick);
462 return tooltip_timer;
466 private ToolTip ToolTipWindow {
467 get {
468 if (tooltip_window == null)
469 tooltip_window = new ToolTip ();
471 return tooltip_window;
475 private void ToolTipTimer_Tick (object o, EventArgs args)
477 string tooltip = tooltip_currently_showing.ToolTipText;
479 if (tooltip != null && tooltip.Length > 0)
480 ToolTipWindow.Present (this, tooltip);
482 ToolTipTimer.Stop ();
484 #endregion
486 #region Events
487 [Browsable(false)]
488 [EditorBrowsable(EditorBrowsableState.Never)]
489 public new event EventHandler BackColorChanged {
490 add { base.BackColorChanged += value; }
491 remove { base.BackColorChanged -= value; }
494 [Browsable(false)]
495 [EditorBrowsable(EditorBrowsableState.Never)]
496 public new event EventHandler BackgroundImageChanged {
497 add { base.BackgroundImageChanged += value; }
498 remove { base.BackgroundImageChanged -= value; }
501 [Browsable (false)]
502 [EditorBrowsable (EditorBrowsableState.Never)]
503 public new event EventHandler BackgroundImageLayoutChanged
505 add { base.BackgroundImageLayoutChanged += value; }
506 remove { base.BackgroundImageLayoutChanged -= value; }
509 [Browsable(false)]
510 [EditorBrowsable(EditorBrowsableState.Never)]
511 public new event EventHandler ForeColorChanged {
512 add { base.ForeColorChanged += value; }
513 remove { base.ForeColorChanged -= value; }
516 [Browsable(false)]
517 [EditorBrowsable(EditorBrowsableState.Never)]
518 public new event EventHandler ImeModeChanged {
519 add { base.ImeModeChanged += value; }
520 remove { base.ImeModeChanged -= value; }
523 [Browsable(false)]
524 [EditorBrowsable(EditorBrowsableState.Never)]
525 public new event PaintEventHandler Paint {
526 add { base.Paint += value; }
527 remove { base.Paint -= value; }
530 static object DrawItemEvent = new object ();
531 static object PanelClickEvent = new object ();
533 public event StatusBarDrawItemEventHandler DrawItem {
534 add { Events.AddHandler (DrawItemEvent, value); }
535 remove { Events.RemoveHandler (DrawItemEvent, value); }
538 public event StatusBarPanelClickEventHandler PanelClick {
539 add { Events.AddHandler (PanelClickEvent, value); }
540 remove { Events.RemoveHandler (PanelClickEvent, value); }
542 #endregion // Events
545 #region Subclass StatusBarPanelCollection
546 [ListBindable (false)]
547 public class StatusBarPanelCollection : IList, ICollection, IEnumerable {
548 #region Fields
549 private StatusBar owner;
550 private ArrayList panels = new ArrayList ();
551 private int last_index_by_key;
552 #endregion // Fields
554 #region UIA Framework Events
555 static object UIACollectionChangedEvent = new object ();
557 internal event CollectionChangeEventHandler UIACollectionChanged {
558 add { owner.Events.AddHandler (UIACollectionChangedEvent, value); }
559 remove { owner.Events.RemoveHandler (UIACollectionChangedEvent, value); }
562 internal void OnUIACollectionChanged (CollectionChangeEventArgs e)
564 CollectionChangeEventHandler eh
565 = (CollectionChangeEventHandler) owner.Events [UIACollectionChangedEvent];
566 if (eh != null)
567 eh (owner, e);
569 #endregion
571 #region Public Constructors
572 public StatusBarPanelCollection (StatusBar owner)
574 this.owner = owner;
577 #endregion // Public Constructors
579 #region Private & Internal Methods
580 private int AddInternal (StatusBarPanel p, bool refresh) {
581 if (p == null)
582 throw new ArgumentNullException ("value");
584 p.SetParent (owner);
585 int res = panels.Add (p);
587 if (refresh) {
588 owner.CalcPanelSizes ();
589 owner.Refresh ();
592 // UIA Framework Event: Panel Added
593 OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Add, res));
595 return res;
598 #endregion // Private & Internal Methods
600 #region Public Instance Properties
601 [Browsable(false)]
602 [EditorBrowsable(EditorBrowsableState.Never)]
603 public int Count {
604 get { return panels.Count; }
607 public bool IsReadOnly {
608 get { return false; }
611 public virtual StatusBarPanel this [int index] {
612 get {
613 if (index < 0 || index >= Count)
614 throw new ArgumentOutOfRangeException ("index");
615 return (StatusBarPanel) panels [index];
617 set {
618 if (value == null)
619 throw new ArgumentNullException ("index");
620 if (index < 0 || index >= Count)
621 throw new ArgumentOutOfRangeException ("index");
623 // UIA Framework Event: Panel Removed
624 OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Remove, index));
626 value.SetParent (owner);
628 panels [index] = value;
630 // UIA Framework Event: Panel Added
631 OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Add, index));
635 public virtual StatusBarPanel this [string key] {
636 get {
637 int index = IndexOfKey (key);
638 if (index >= 0 && index < Count) {
639 return (StatusBarPanel) panels [index];
641 return null;
645 #endregion // Public Instance Properties
647 #region Public Instance Methods
648 public virtual int Add (StatusBarPanel value) {
649 return AddInternal (value, true);
652 public virtual StatusBarPanel Add (string text) {
653 StatusBarPanel res = new StatusBarPanel ();
654 res.Text = text;
655 Add (res);
656 return res;
659 public virtual void AddRange (StatusBarPanel [] panels) {
660 if (panels == null)
661 throw new ArgumentNullException ("panels");
662 if (panels.Length == 0)
663 return;
665 for (int i = 0; i < panels.Length; i++)
666 AddInternal (panels [i], false);
667 owner.Refresh ();
670 public virtual void Clear () {
671 panels.Clear ();
673 owner.Refresh ();
675 // UIA Framework Event: Panel Cleared
676 OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Refresh, -1));
679 public bool Contains (StatusBarPanel panel) {
680 return panels.Contains (panel);
683 public virtual bool ContainsKey (string key)
685 int index = IndexOfKey (key);
686 return index >= 0 && index < Count;
689 public IEnumerator GetEnumerator () {
690 return panels.GetEnumerator ();
693 public int IndexOf (StatusBarPanel panel) {
694 return panels.IndexOf (panel);
697 public virtual int IndexOfKey (string key)
699 if (key == null || key == string.Empty)
700 return -1;
702 if (last_index_by_key >= 0 && last_index_by_key < Count &&
703 String.Compare (((StatusBarPanel)panels [last_index_by_key]).Name, key, StringComparison.OrdinalIgnoreCase) == 0) {
704 return last_index_by_key;
707 for (int i = 0; i < Count; i++) {
708 StatusBarPanel item;
709 item = panels [i] as StatusBarPanel;
710 if (item != null && String.Compare (item.Name, key, StringComparison.OrdinalIgnoreCase) == 0) {
711 last_index_by_key = i;
712 return i;
716 return -1;
719 public virtual void Insert (int index, StatusBarPanel value) {
720 if (value == null)
721 throw new ArgumentNullException ("value");
722 if (index > Count)
723 throw new ArgumentOutOfRangeException ("index");
724 // TODO: InvalidArgumentException for bad AutoSize values
725 // although it seems impossible to set it to a bad value
726 value.SetParent (owner);
728 panels.Insert(index, value);
729 owner.Refresh ();
731 // UIA Framework Event: Panel Added
732 OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Add, index));
735 public virtual void Remove (StatusBarPanel value) {
736 int index = IndexOf (value);
737 panels.Remove (value);
739 // UIA Framework Event: Panel Removed
740 if (index >= 0)
741 OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Remove, index));
744 public virtual void RemoveAt (int index) {
745 panels.RemoveAt (index);
747 // UIA Framework Event: Panel Removed
748 OnUIACollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Remove, index));
751 public virtual void RemoveByKey (string key)
753 int index = IndexOfKey (key);
754 if (index >= 0 && index < Count)
755 RemoveAt (index);
758 #endregion // Public Instance Methods
760 #region IList & ICollection Interfaces
761 bool ICollection.IsSynchronized {
762 get { return panels.IsSynchronized; }
765 object ICollection.SyncRoot {
766 get { return panels.SyncRoot; }
769 void ICollection.CopyTo (Array dest, int index)
771 panels.CopyTo (dest, index);
775 object IList.this [int index] {
776 get { return this[index]; }
777 set {
778 if (!(value is StatusBarPanel))
779 throw new ArgumentException ("Value must be of type StatusBarPanel.", "value");
781 this[index] = (StatusBarPanel)value;
785 int IList.Add (object value) {
786 if (!(value is StatusBarPanel))
787 throw new ArgumentException ("Value must be of type StatusBarPanel.", "value");
789 return AddInternal ((StatusBarPanel)value, true);
792 bool IList.Contains (object panel) {
793 return panels.Contains (panel);
796 int IList.IndexOf (object panel)
798 return panels.IndexOf (panel);
801 void IList.Insert (int index, object value)
803 if (!(value is StatusBarPanel))
804 throw new ArgumentException ("Value must be of type StatusBarPanel.", "value");
806 Insert (index, (StatusBarPanel)value);
809 bool IList.IsFixedSize {
810 get { return false; }
813 void IList.Remove (object value)
815 StatusBarPanel s = value as StatusBarPanel;
816 Remove (s);
818 #endregion // IList & ICollection Interfaces
820 #endregion // Subclass StatusBarPanelCollection