PageRenderTime 35ms CodeModel.GetById 21ms app.highlight 12ms RepoModel.GetById 0ms app.codeStats 0ms

/mcs/class/Managed.Windows.Forms/System.Windows.Forms/StatusStrip.cs

https://github.com/iainlane/mono
C# | 313 lines | 224 code | 51 blank | 38 comment | 38 complexity | d4df8fa716502e7660c68853c5a63c19 MD5 | raw file
  1//
  2// StatusStrip.cs
  3//
  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:
 11// 
 12// The above copyright notice and this permission notice shall be
 13// included in all copies or substantial portions of the Software.
 14// 
 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.
 22//
 23// Copyright (c) 2006 Jonathan Pobst
 24//
 25// Authors:
 26//	Jonathan Pobst (monkey@jpobst.com)
 27//
 28
 29using System;
 30using System.Drawing;
 31using System.ComponentModel;
 32using System.Runtime.InteropServices;
 33
 34namespace System.Windows.Forms
 35{
 36	[ClassInterface (ClassInterfaceType.AutoDispatch)]
 37	[ComVisible (true)]
 38	public class StatusStrip : ToolStrip
 39	{
 40		private bool sizing_grip;
 41		
 42		public StatusStrip ()
 43		{
 44			SetStyle (ControlStyles.ResizeRedraw, true);
 45			
 46			base.CanOverflow = false;
 47			this.GripStyle = ToolStripGripStyle.Hidden;
 48			base.LayoutStyle = ToolStripLayoutStyle.Table;
 49			base.RenderMode = ToolStripRenderMode.System;
 50			this.sizing_grip = true;
 51			base.Stretch = true;
 52		}
 53
 54		#region Public Properties
 55		[DefaultValue (DockStyle.Bottom)]
 56		public override DockStyle Dock {
 57			get { return base.Dock; }
 58			set { base.Dock = value; }
 59		}
 60
 61		[Browsable (false)]
 62		[DefaultValue (false)]
 63		public new bool CanOverflow {
 64			get { return base.CanOverflow; }
 65			set { base.CanOverflow = value; }
 66		}
 67		
 68		[DefaultValue (ToolStripGripStyle.Hidden)]
 69		public new ToolStripGripStyle GripStyle {
 70			get { return base.GripStyle; }
 71			set { base.GripStyle = value; }
 72		}
 73		
 74		[DefaultValue (ToolStripLayoutStyle.Table)]
 75		public new ToolStripLayoutStyle LayoutStyle {	
 76			get { return base.LayoutStyle; }
 77			set { base.LayoutStyle = value; }
 78		}
 79		
 80		[Browsable (false)]
 81		public new Padding Padding {
 82			get { return base.Padding; }
 83			set { base.Padding = value; }
 84		}
 85		
 86		[DefaultValue (false)]
 87		public new bool ShowItemToolTips {
 88			get { return base.ShowItemToolTips; }
 89			set { base.ShowItemToolTips = value; }
 90		}
 91		
 92		[Browsable (false)]
 93		public Rectangle SizeGripBounds {
 94			get { return new Rectangle (this.Width - 12, 0, 12, this.Height); }
 95		}
 96		
 97		[DefaultValue (true)]
 98		public bool SizingGrip {
 99			get { return this.sizing_grip; }
100			set { this.sizing_grip = value; }
101		}
102		
103		[DefaultValue (true)]
104		public new bool Stretch {
105			get { return base.Stretch; }
106			set { base.Stretch = value; }
107		}
108		#endregion
109
110		#region Protected Properties
111		protected override DockStyle DefaultDock {
112			get { return DockStyle.Bottom; }
113		}
114
115		protected override Padding DefaultPadding {
116			get { return new Padding (1, 0, 14, 0); }
117		}
118
119		protected override bool DefaultShowItemToolTips {
120			get { return false; }
121		}
122
123		protected override Size DefaultSize {
124			get { return new Size (200, 22); }
125		}
126		#endregion
127
128		#region Protected Methods
129		protected override AccessibleObject CreateAccessibilityInstance ()
130		{
131			return new StatusStripAccessibleObject ();
132		}
133		
134		protected internal override ToolStripItem CreateDefaultItem (string text, Image image, EventHandler onClick)
135		{
136			if (text == "-")
137				return new ToolStripSeparator ();
138				
139			return new ToolStripLabel (text, image, false, onClick);
140		}
141
142		protected override void Dispose (bool disposing)
143		{
144			base.Dispose (disposing);
145		}
146
147		protected override void OnLayout (LayoutEventArgs levent)
148		{
149			this.OnSpringTableLayoutCore ();
150			this.Invalidate ();
151		}
152
153		protected override void OnPaintBackground (PaintEventArgs e)
154		{
155			base.OnPaintBackground (e);
156			
157			if (this.sizing_grip)
158				this.Renderer.DrawStatusStripSizingGrip (new ToolStripRenderEventArgs (e.Graphics, this, Bounds, SystemColors.Control));
159		}
160
161		protected virtual void OnSpringTableLayoutCore ()
162		{
163			if (!this.Created)
164				return;
165
166			ToolStripItemOverflow[] overflow = new ToolStripItemOverflow[this.Items.Count];
167			ToolStripItemPlacement[] placement = new ToolStripItemPlacement[this.Items.Count];
168			Size proposedSize = new Size (0, Bounds.Height);
169			int[] widths = new int[this.Items.Count];
170			int total_width = 0;
171			int toolstrip_width = DisplayRectangle.Width;
172			int i = 0;
173			int spring_count = 0;
174
175			foreach (ToolStripItem tsi in this.Items) {
176				overflow[i] = tsi.Overflow;
177				widths[i] = tsi.GetPreferredSize (proposedSize).Width + tsi.Margin.Horizontal;
178				placement[i] = tsi.Overflow == ToolStripItemOverflow.Always ? ToolStripItemPlacement.None : ToolStripItemPlacement.Main;
179				placement[i] = tsi.Available && tsi.InternalVisible ? placement[i] : ToolStripItemPlacement.None;
180				total_width += placement[i] == ToolStripItemPlacement.Main ? widths[i] : 0;
181				if (tsi is ToolStripStatusLabel && (tsi as ToolStripStatusLabel).Spring)
182					spring_count++;
183					
184				i++;
185			}
186
187			while (total_width > toolstrip_width) {
188				bool removed_one = false;
189
190				// Start at the right, removing Overflow.AsNeeded first
191				for (int j = widths.Length - 1; j >= 0; j--)
192					if (overflow[j] == ToolStripItemOverflow.AsNeeded && placement[j] == ToolStripItemPlacement.Main) {
193						placement[j] = ToolStripItemPlacement.None;
194						total_width -= widths[j];
195						removed_one = true;
196						break;
197					}
198
199				// If we didn't remove any AsNeeded ones, we have to start removing Never ones
200				// These are not put on the Overflow, they are simply not shown
201				if (!removed_one)
202					for (int j = widths.Length - 1; j >= 0; j--)
203						if (overflow[j] == ToolStripItemOverflow.Never && placement[j] == ToolStripItemPlacement.Main) {
204							placement[j] = ToolStripItemPlacement.None;
205							total_width -= widths[j];
206							removed_one = true;
207							break;
208						}
209
210				// There's nothing left to remove, break or we will loop forever	
211				if (!removed_one)
212					break;
213			}
214
215			if (spring_count > 0) {
216				int per_item = (toolstrip_width - total_width) / spring_count;
217				i = 0;
218				
219				foreach (ToolStripItem tsi in this.Items) {
220					if (tsi is ToolStripStatusLabel && (tsi as ToolStripStatusLabel).Spring)
221						widths[i] += per_item;
222						
223					i++;
224				}
225			}
226
227			i = 0;
228			Point layout_pointer = new Point (this.DisplayRectangle.Left, this.DisplayRectangle.Top);
229			int button_height = this.DisplayRectangle.Height;
230
231			// Now we should know where everything goes, so lay everything out
232			foreach (ToolStripItem tsi in this.Items) {
233				tsi.SetPlacement (placement[i]);
234
235				if (placement[i] == ToolStripItemPlacement.Main) {
236					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));
237					layout_pointer.X += widths[i];
238				}
239
240				i++;
241			}
242
243			this.SetDisplayedItems ();
244		}
245
246		protected override void SetDisplayedItems ()
247		{
248			// Only clean the internal collection, without modifying Owner/Parent on items.
249			this.displayed_items.ClearInternal ();
250
251			foreach (ToolStripItem tsi in this.Items)
252				if (tsi.Placement == ToolStripItemPlacement.Main && tsi.Available) {
253					this.displayed_items.AddNoOwnerOrLayout (tsi);
254					tsi.Parent = this;
255				}
256		}
257		
258		protected override void WndProc (ref Message m)
259		{
260			switch ((Msg)m.Msg) {
261				// If the mouse is over the size grip, change the cursor
262				case Msg.WM_MOUSEMOVE: {
263					if (FromParamToMouseButtons ((int) m.WParam.ToInt32()) == MouseButtons.None) {	
264						Point p = new Point (LowOrder ((int) m.LParam.ToInt32 ()), HighOrder ((int) m.LParam.ToInt32 ()));
265						
266						if (this.SizingGrip && this.SizeGripBounds.Contains (p)) {
267							this.Cursor = Cursors.SizeNWSE;
268							return;
269						} else
270							this.Cursor = Cursors.Default;
271					}
272
273					break;
274				}
275				// If the left mouse button is pushed over the size grip,
276				// send the WM a message to begin a window resize operation
277				case Msg.WM_LBUTTONDOWN: {
278					Point p = new Point (LowOrder ((int)m.LParam.ToInt32 ()), HighOrder ((int)m.LParam.ToInt32 ()));
279					Form form = FindForm ();
280
281					if (this.SizingGrip && this.SizeGripBounds.Contains (p)) {
282						// For top level forms it's not enoug to send a NCLBUTTONDOWN message, so
283						// we make a direct call to our XplatUI engine.
284						if (!form.IsMdiChild)
285							XplatUI.BeginMoveResize (form.Handle);
286
287						XplatUI.SendMessage (form.Handle, Msg.WM_NCLBUTTONDOWN, (IntPtr) HitTest.HTBOTTOMRIGHT, IntPtr.Zero);
288						return;
289					}
290					
291					break;
292				}
293			}
294
295			base.WndProc (ref m);
296		}
297		#endregion
298
299		#region Public Events
300		[Browsable (false)]
301		public new event EventHandler PaddingChanged {
302			add { base.PaddingChanged += value; }
303			remove { base.PaddingChanged -= value; }
304		}
305		#endregion
306
307		#region StatusStripAccessibleObject
308		private class StatusStripAccessibleObject : AccessibleObject
309		{
310		}
311		#endregion
312	}
313}