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