copied mono-api-diff.cs from mono-2-2 branch so new patch can be applied and history...
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / StatusStrip.cs
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 #if NET_2_0
29
30 using System;
31 using System.Drawing;
32 using System.ComponentModel;
33 using System.Runtime.InteropServices;
34
35 namespace System.Windows.Forms
36 {
37         [ClassInterface (ClassInterfaceType.AutoDispatch)]
38         [ComVisible (true)]
39         public class StatusStrip : ToolStrip
40         {
41                 private bool sizing_grip;
42                 
43                 public StatusStrip ()
44                 {
45                         SetStyle (ControlStyles.ResizeRedraw, true);
46                         
47                         base.CanOverflow = false;
48                         this.GripStyle = ToolStripGripStyle.Hidden;
49                         base.LayoutStyle = ToolStripLayoutStyle.Table;
50                         base.RenderMode = ToolStripRenderMode.System;
51                         this.sizing_grip = true;
52                         base.Stretch = true;
53                 }
54
55                 #region Public Properties
56                 [DefaultValue (DockStyle.Bottom)]
57                 public override DockStyle Dock {
58                         get { return base.Dock; }
59                         set { base.Dock = value; }
60                 }
61
62                 [Browsable (false)]
63                 [DefaultValue (false)]
64                 public new bool CanOverflow {
65                         get { return base.CanOverflow; }
66                         set { base.CanOverflow = value; }
67                 }
68                 
69                 [DefaultValue (ToolStripGripStyle.Hidden)]
70                 public new ToolStripGripStyle GripStyle {
71                         get { return base.GripStyle; }
72                         set { base.GripStyle = value; }
73                 }
74                 
75                 [DefaultValue (ToolStripLayoutStyle.Table)]
76                 public new ToolStripLayoutStyle LayoutStyle {   
77                         get { return base.LayoutStyle; }
78                         set { base.LayoutStyle = value; }
79                 }
80                 
81                 [Browsable (false)]
82                 public new Padding Padding {
83                         get { return base.Padding; }
84                         set { base.Padding = value; }
85                 }
86                 
87                 [DefaultValue (false)]
88                 public new bool ShowItemToolTips {
89                         get { return base.ShowItemToolTips; }
90                         set { base.ShowItemToolTips = value; }
91                 }
92                 
93                 [Browsable (false)]
94                 public Rectangle SizeGripBounds {
95                         get { return new Rectangle (this.Width - 12, 0, 12, this.Height); }
96                 }
97                 
98                 [DefaultValue (true)]
99                 public bool SizingGrip {
100                         get { return this.sizing_grip; }
101                         set { this.sizing_grip = value; }
102                 }
103                 
104                 [DefaultValue (true)]
105                 public new bool Stretch {
106                         get { return base.Stretch; }
107                         set { base.Stretch = value; }
108                 }
109                 #endregion
110
111                 #region Protected Properties
112                 protected override DockStyle DefaultDock {
113                         get { return DockStyle.Bottom; }
114                 }
115
116                 protected override Padding DefaultPadding {
117                         get { return new Padding (1, 0, 14, 0); }
118                 }
119
120                 protected override bool DefaultShowItemToolTips {
121                         get { return false; }
122                 }
123
124                 protected override Size DefaultSize {
125                         get { return new Size (200, 22); }
126                 }
127                 #endregion
128
129                 #region Protected Methods
130                 protected override AccessibleObject CreateAccessibilityInstance ()
131                 {
132                         return new StatusStripAccessibleObject ();
133                 }
134                 
135                 protected internal override ToolStripItem CreateDefaultItem (string text, Image image, EventHandler onClick)
136                 {
137                         if (text == "-")
138                                 return new ToolStripSeparator ();
139                                 
140                         return new ToolStripLabel (text, image, false, onClick);
141                 }
142
143                 protected override void Dispose (bool disposing)
144                 {
145                         base.Dispose (disposing);
146                 }
147
148                 protected override void OnLayout (LayoutEventArgs levent)
149                 {
150                         this.OnSpringTableLayoutCore ();
151                         this.Invalidate ();
152                 }
153
154                 protected override void OnPaintBackground (PaintEventArgs e)
155                 {
156                         base.OnPaintBackground (e);
157                         
158                         if (this.sizing_grip)
159                                 this.Renderer.DrawStatusStripSizingGrip (new ToolStripRenderEventArgs (e.Graphics, this, Bounds, SystemColors.Control));
160                 }
161
162                 protected virtual void OnSpringTableLayoutCore ()
163                 {
164                         if (!this.Created)
165                                 return;
166
167                         ToolStripItemOverflow[] overflow = new ToolStripItemOverflow[this.Items.Count];
168                         ToolStripItemPlacement[] placement = new ToolStripItemPlacement[this.Items.Count];
169                         Size proposedSize = new Size (0, Bounds.Height);
170                         int[] widths = new int[this.Items.Count];
171                         int total_width = 0;
172                         int toolstrip_width = DisplayRectangle.Width;
173                         int i = 0;
174                         int spring_count = 0;
175
176                         foreach (ToolStripItem tsi in this.Items) {
177                                 overflow[i] = tsi.Overflow;
178                                 widths[i] = tsi.GetPreferredSize (proposedSize).Width + tsi.Margin.Horizontal;
179                                 placement[i] = tsi.Overflow == ToolStripItemOverflow.Always ? ToolStripItemPlacement.None : ToolStripItemPlacement.Main;
180                                 placement[i] = tsi.Available && tsi.InternalVisible ? placement[i] : ToolStripItemPlacement.None;
181                                 total_width += placement[i] == ToolStripItemPlacement.Main ? widths[i] : 0;
182                                 if (tsi is ToolStripStatusLabel && (tsi as ToolStripStatusLabel).Spring)
183                                         spring_count++;
184                                         
185                                 i++;
186                         }
187
188                         while (total_width > toolstrip_width) {
189                                 bool removed_one = false;
190
191                                 // Start at the right, removing Overflow.AsNeeded first
192                                 for (int j = widths.Length - 1; j >= 0; j--)
193                                         if (overflow[j] == ToolStripItemOverflow.AsNeeded && placement[j] == ToolStripItemPlacement.Main) {
194                                                 placement[j] = ToolStripItemPlacement.None;
195                                                 total_width -= widths[j];
196                                                 removed_one = true;
197                                                 break;
198                                         }
199
200                                 // If we didn't remove any AsNeeded ones, we have to start removing Never ones
201                                 // These are not put on the Overflow, they are simply not shown
202                                 if (!removed_one)
203                                         for (int j = widths.Length - 1; j >= 0; j--)
204                                                 if (overflow[j] == ToolStripItemOverflow.Never && placement[j] == ToolStripItemPlacement.Main) {
205                                                         placement[j] = ToolStripItemPlacement.None;
206                                                         total_width -= widths[j];
207                                                         removed_one = true;
208                                                         break;
209                                                 }
210
211                                 // There's nothing left to remove, break or we will loop forever        
212                                 if (!removed_one)
213                                         break;
214                         }
215
216                         if (spring_count > 0) {
217                                 int per_item = (toolstrip_width - total_width) / spring_count;
218                                 i = 0;
219                                 
220                                 foreach (ToolStripItem tsi in this.Items) {
221                                         if (tsi is ToolStripStatusLabel && (tsi as ToolStripStatusLabel).Spring)
222                                                 widths[i] += per_item;
223                                                 
224                                         i++;
225                                 }
226                         }
227
228                         i = 0;
229                         Point layout_pointer = new Point (this.DisplayRectangle.Left, this.DisplayRectangle.Top);
230                         int button_height = this.DisplayRectangle.Height;
231
232                         // Now we should know where everything goes, so lay everything out
233                         foreach (ToolStripItem tsi in this.Items) {
234                                 tsi.SetPlacement (placement[i]);
235
236                                 if (placement[i] == ToolStripItemPlacement.Main) {
237                                         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));
238                                         layout_pointer.X += widths[i];
239                                 }
240
241                                 i++;
242                         }
243
244                         this.SetDisplayedItems ();
245                 }
246
247                 protected override void SetDisplayedItems ()
248                 {
249                         this.displayed_items.Clear ();
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 }
314 #endif