4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the
6 // "Software"), to deal in the Software without restriction, including
7 // without limitation the rights to use, copy, modify, merge, publish,
8 // distribute, sublicense, and/or sell copies of the Software, and to
9 // permit persons to whom the Software is furnished to do so, subject to
10 // the following conditions:
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 // Copyright (c) 2006 Jonathan Pobst
26 // Jonathan Pobst (monkey@jpobst.com)
32 using System.ComponentModel;
33 using System.Runtime.InteropServices;
35 namespace System.Windows.Forms
37 [ClassInterface (ClassInterfaceType.AutoDispatch)]
39 public class StatusStrip : ToolStrip
41 private bool sizing_grip;
45 SetStyle (ControlStyles.ResizeRedraw, true);
47 base.CanOverflow = false;
48 this.GripStyle = ToolStripGripStyle.Hidden;
49 base.LayoutStyle = ToolStripLayoutStyle.Table;
50 this.sizing_grip = true;
54 #region Public Properties
55 [DefaultValue (DockStyle.Bottom)]
56 public override DockStyle Dock {
57 get { return base.Dock; }
58 set { base.Dock = value; }
62 [DefaultValue (false)]
63 public new bool CanOverflow {
64 get { return base.CanOverflow; }
65 set { base.CanOverflow = value; }
68 [DefaultValue (ToolStripGripStyle.Hidden)]
69 public new ToolStripGripStyle GripStyle {
70 get { return base.GripStyle; }
71 set { base.GripStyle = value; }
74 [DefaultValue (ToolStripLayoutStyle.Table)]
75 public new ToolStripLayoutStyle LayoutStyle {
76 get { return base.LayoutStyle; }
77 set { base.LayoutStyle = value; }
81 public new Padding Padding {
82 get { return base.Padding; }
83 set { base.Padding = value; }
86 [DefaultValue (false)]
87 public new bool ShowItemToolTips {
88 get { return base.ShowItemToolTips; }
89 set { base.ShowItemToolTips = value; }
93 public Rectangle SizeGripBounds {
94 get { return new Rectangle (this.Width - 12, 0, 12, this.Height); }
98 public bool SizingGrip {
99 get { return this.sizing_grip; }
100 set { this.sizing_grip = value; }
103 [DefaultValue (true)]
104 public new bool Stretch {
105 get { return base.Stretch; }
106 set { base.Stretch = value; }
110 #region Protected Properties
111 protected override DockStyle DefaultDock {
112 get { return DockStyle.Bottom; }
115 protected override Padding DefaultPadding {
116 get { return new Padding (1, 0, 14, 0); }
119 protected override bool DefaultShowItemToolTips {
120 get { return false; }
123 protected override Size DefaultSize {
124 get { return new Size (200, 22); }
128 #region Protected Methods
129 protected internal override ToolStripItem CreateDefaultItem (string text, Image image, EventHandler onClick)
132 return new ToolStripSeparator ();
134 return new ToolStripLabel (text, image, false, onClick);
137 protected override void Dispose (bool disposing)
139 base.Dispose (disposing);
142 protected override void OnLayout (LayoutEventArgs e)
144 this.OnSpringTableLayoutCore ();
147 protected override void OnPaintBackground (PaintEventArgs pevent)
149 base.OnPaintBackground (pevent);
151 if (this.sizing_grip)
152 this.Renderer.DrawStatusStripSizingGrip (new ToolStripRenderEventArgs (pevent.Graphics, this));
155 protected virtual void OnSpringTableLayoutCore ()
160 ToolStripItemOverflow[] overflow = new ToolStripItemOverflow[this.Items.Count];
161 ToolStripItemPlacement[] placement = new ToolStripItemPlacement[this.Items.Count];
162 Size proposedSize = new Size (0, Bounds.Height);
163 int[] widths = new int[this.Items.Count];
165 int toolstrip_width = DisplayRectangle.Width;
167 int spring_count = 0;
169 foreach (ToolStripItem tsi in this.Items) {
170 overflow[i] = tsi.Overflow;
171 widths[i] = tsi.GetPreferredSize (proposedSize).Width + tsi.Margin.Horizontal;
172 placement[i] = tsi.Overflow == ToolStripItemOverflow.Always ? ToolStripItemPlacement.None : ToolStripItemPlacement.Main;
173 placement[i] = tsi.Available ? placement[i] : ToolStripItemPlacement.None;
174 total_width += placement[i] == ToolStripItemPlacement.Main ? widths[i] : 0;
175 if (tsi is ToolStripStatusLabel && (tsi as ToolStripStatusLabel).Spring)
181 while (total_width > toolstrip_width) {
182 bool removed_one = false;
184 // Start at the right, removing Overflow.AsNeeded first
185 for (int j = widths.Length - 1; j >= 0; j--)
186 if (overflow[j] == ToolStripItemOverflow.AsNeeded && placement[j] == ToolStripItemPlacement.Main) {
187 placement[j] = ToolStripItemPlacement.None;
188 total_width -= widths[j];
193 // If we didn't remove any AsNeeded ones, we have to start removing Never ones
194 // These are not put on the Overflow, they are simply not shown
196 for (int j = widths.Length - 1; j >= 0; j--)
197 if (overflow[j] == ToolStripItemOverflow.Never && placement[j] == ToolStripItemPlacement.Main) {
198 placement[j] = ToolStripItemPlacement.None;
199 total_width -= widths[j];
204 // There's nothing left to remove, break or we will loop forever
209 if (spring_count > 0) {
210 int per_item = (toolstrip_width - total_width) / spring_count;
213 foreach (ToolStripItem tsi in this.Items) {
214 if (tsi is ToolStripStatusLabel && (tsi as ToolStripStatusLabel).Spring)
215 widths[i] += per_item;
222 Point layout_pointer = new Point (this.DisplayRectangle.Left, this.DisplayRectangle.Top);
223 int button_height = this.DisplayRectangle.Height;
225 // Now we should know where everything goes, so lay everything out
226 foreach (ToolStripItem tsi in this.Items) {
227 tsi.SetPlacement (placement[i]);
229 if (placement[i] == ToolStripItemPlacement.Main) {
230 tsi.SetBounds (new Rectangle (layout_pointer.X + tsi.Margin.Left, layout_pointer.Y + tsi.Margin.Top, widths[i] - tsi.Margin.Horizontal, button_height - tsi.Margin.Vertical));
231 layout_pointer.X += widths[i];
237 this.SetDisplayedItems ();
240 protected override void SetDisplayedItems ()
242 this.displayed_items.Clear ();
244 foreach (ToolStripItem tsi in this.Items)
245 if (tsi.Placement == ToolStripItemPlacement.Main) {
246 this.displayed_items.AddNoOwnerOrLayout (tsi);
247 tsi.InternalVisible = true;
249 tsi.InternalVisible = false;
252 protected override void WndProc (ref Message m)
254 switch ((Msg)m.Msg) {
255 // If the mouse is over the size grip, change the cursor
256 case Msg.WM_MOUSEMOVE: {
257 if (FromParamToMouseButtons ((int) m.WParam.ToInt32()) == MouseButtons.None) {
258 Point p = new Point (LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()));
260 if (this.SizingGrip && this.SizeGripBounds.Contains (p)) {
261 this.Cursor = Cursors.SizeNESW;
264 this.Cursor = Cursors.Default;
269 // If the left mouse button is pushed over the size grip,
270 // send the WM a message to begin a window resize operation
271 case Msg.WM_LBUTTONDOWN: {
272 Point p = new Point (LowOrder ((int)m.LParam.ToInt32 ()), HighOrder ((int)m.LParam.ToInt32 ()));
274 if (this.SizingGrip && this.SizeGripBounds.Contains (p)) {
275 XplatUI.SendMessage (this.FindForm().Handle, Msg.WM_NCLBUTTONDOWN, (IntPtr) HitTest.HTBOTTOMRIGHT, IntPtr.Zero);
283 base.WndProc (ref m);
287 #region Public Events
289 public new event EventHandler PaddingChanged {
290 add { base.PaddingChanged += value; }
291 remove { base.PaddingChanged -= value; }