2010-04-27 Carlos Alberto Cortez <calberto.cortez@gmail.com>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ToolStripSplitButton.cs
1 //
2 // ToolStripSplitButton.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.Windows.Forms.Design;
34
35 namespace System.Windows.Forms
36 {
37         [DefaultEvent ("ButtonClick")]
38         [ToolStripItemDesignerAvailability (ToolStripItemDesignerAvailability.ToolStrip | ToolStripItemDesignerAvailability.StatusStrip)]
39         public class ToolStripSplitButton : ToolStripDropDownItem
40         {
41                 private bool button_pressed;
42                 private ToolStripItem default_item;
43                 private bool drop_down_button_selected;
44                 private int drop_down_button_width;
45                 
46                 #region Public Constructors
47                 public ToolStripSplitButton()
48                         : this (string.Empty, null, null, string.Empty)
49                 {
50                 }
51                 
52                 public ToolStripSplitButton (Image image)
53                         : this (string.Empty, image, null, string.Empty)
54                 {
55                 }
56                 
57                 public ToolStripSplitButton (string text)
58                         : this (text, null, null, string.Empty)
59                 {
60                 }
61                 
62                 public ToolStripSplitButton (string text, Image image)
63                         : this (text, image, null, string.Empty)
64                 {
65                 }
66                 
67                 public ToolStripSplitButton (string text, Image image, EventHandler onClick)
68                         : this (text, image, onClick, string.Empty)
69                 {
70                 }
71                 
72                 public ToolStripSplitButton (string text, Image image, params ToolStripItem[] dropDownItems)
73                         : base (text, image, dropDownItems)
74                 {
75                         this.ResetDropDownButtonWidth ();
76                 }
77
78                 public ToolStripSplitButton (string text, Image image, EventHandler onClick, string name)
79                         : base (text, image, onClick, name)
80                 {
81                         this.ResetDropDownButtonWidth ();
82                 }
83                 #endregion
84
85                 #region Public Properties
86                 [DefaultValue (true)]
87                 public new bool AutoToolTip {
88                         get { return base.AutoToolTip; }
89                         set { base.AutoToolTip = value; }
90                 }
91
92                 [Browsable (false)]
93                 public Rectangle ButtonBounds {
94                         get { return new Rectangle (Bounds.Left, Bounds.Top, this.Bounds.Width - this.drop_down_button_width - 1, this.Height); }
95                 }
96
97                 [Browsable (false)]
98                 public bool ButtonPressed {
99                         get { return this.button_pressed; }
100                 }
101
102                 [Browsable (false)]
103                 public bool ButtonSelected {
104                         get { return base.Selected; }
105                 }
106
107                 [Browsable (false)]
108                 [DefaultValue (null)]
109                 public ToolStripItem DefaultItem {
110                         get { return this.default_item; }
111                         set {
112                                 if (this.default_item != value) {
113                                         this.default_item = value;
114                                         this.OnDefaultItemChanged (EventArgs.Empty);
115                                 }
116                         }
117                 }
118                 
119                 [Browsable (false)]
120                 public Rectangle DropDownButtonBounds {
121                         get { return new Rectangle (this.Bounds.Right - this.drop_down_button_width, 0, this.drop_down_button_width, this.Bounds.Height); }
122                 }
123
124                 [Browsable (false)]
125                 public bool DropDownButtonPressed {
126                         get { return this.drop_down_button_selected || (this.HasDropDownItems && this.DropDown.Visible); }
127                 }
128
129                 [Browsable (false)]
130                 public bool DropDownButtonSelected {
131                         get { return base.Selected; }
132                 }
133                 
134                 public int DropDownButtonWidth {
135                         get { return this.drop_down_button_width; }
136                         set { 
137                                 if (value < 0)
138                                         throw new ArgumentOutOfRangeException ();
139                                 if (this.drop_down_button_width != value) {
140                                         this.drop_down_button_width = value;
141                                         CalculateAutoSize ();
142                                 }
143                         }
144                 }
145
146                 [Browsable (false)]
147                 public Rectangle SplitterBounds {
148                         get { return new Rectangle (this.Bounds.Width - this.drop_down_button_width - 1, 0, 1, this.Height); }
149                 }
150                 #endregion
151
152                 #region Protected Properties
153                 protected override bool DefaultAutoToolTip {
154                         get { return true; }
155                 }
156
157                 protected internal override bool DismissWhenClicked {
158                         get { return true; }
159                 }
160                 #endregion
161
162                 #region Public Methods
163                 public override Size GetPreferredSize (Size constrainingSize)
164                 {
165                         // base should calculate the button part for us, add the splitter
166                         // and drop down arrow part to that
167                         Size s = base.GetPreferredSize (constrainingSize);
168
169                         if (s.Width < 23)
170                                 s.Width = 23;
171
172                         // If we are a fixed size, we can't add more in for the drop down
173                         // button, but we can for autosize
174                         if (AutoSize)
175                                 s.Width += (this.drop_down_button_width - 2);
176                         
177                         return s;
178                 }
179                 
180                 public virtual void OnButtonDoubleClick (EventArgs e)
181                 {
182                         EventHandler eh = (EventHandler)(Events [ButtonDoubleClickEvent]);
183                         if (eh != null)
184                                 eh (this, e);
185                 }
186                 
187                 public void PerformButtonClick ()
188                 {
189                         if (this.Enabled)
190                                 this.OnButtonClick (EventArgs.Empty);
191                 }
192                 
193                 [EditorBrowsable (EditorBrowsableState.Never)]
194                 public virtual void ResetDropDownButtonWidth ()
195                 {
196                         this.DropDownButtonWidth = 11;
197                 }
198                 #endregion
199
200                 #region Protected Methods
201                 protected override AccessibleObject CreateAccessibilityInstance ()
202                 {
203                         return new ToolStripSplitButtonAccessibleObject (this);
204                 }
205                 
206                 protected override ToolStripDropDown CreateDefaultDropDown ()
207                 {
208                         ToolStripDropDownMenu tsddm = new ToolStripDropDownMenu ();
209                         tsddm.OwnerItem = this;
210                         return tsddm;
211                 }
212                 
213                 protected virtual void OnButtonClick (EventArgs e)
214                 {
215                         EventHandler eh = (EventHandler)Events [ButtonClickEvent];
216                         if (eh != null)
217                                 eh (this, e);
218                 }
219                 
220                 protected virtual void OnDefaultItemChanged (EventArgs e)
221                 {
222                         EventHandler eh = (EventHandler)Events [DefaultItemChangedEvent];
223                         if (eh != null)
224                                 eh (this, e);
225                 }
226
227                 protected override void OnMouseDown (MouseEventArgs e)
228                 {
229                         if (this.ButtonBounds.Contains (e.Location))
230                         {
231                                 this.button_pressed = true;
232                                 this.Invalidate ();
233                                 base.OnMouseDown (e);
234                         }
235                         else if (this.DropDownButtonBounds.Contains (e.Location))
236                         {
237                                 if (this.DropDown.Visible)
238                                         this.HideDropDown (ToolStripDropDownCloseReason.ItemClicked);
239                                 else
240                                         this.ShowDropDown ();
241                         
242                                 this.Invalidate ();
243                                 base.OnMouseDown (e);
244                         }
245                 }
246
247                 protected override void OnMouseLeave (EventArgs e)
248                 {
249                         this.drop_down_button_selected = false;
250                         this.button_pressed = false;
251                         
252                         this.Invalidate ();
253                         
254                         base.OnMouseLeave (e);
255                 }
256
257                 protected override void OnMouseUp (MouseEventArgs e)
258                 {
259                         this.button_pressed = false;
260                         this.Invalidate ();
261                         
262                         base.OnMouseUp (e);
263                 }
264                 
265                 protected override void OnPaint (PaintEventArgs e)
266                 {
267                         base.OnPaint (e);
268
269                         if (this.Owner != null) {
270                                 Color font_color = this.Enabled ? this.ForeColor : SystemColors.GrayText;
271                                 Image draw_image = this.Enabled ? this.Image : ToolStripRenderer.CreateDisabledImage (this.Image);
272
273                                 this.Owner.Renderer.DrawSplitButton (new System.Windows.Forms.ToolStripItemRenderEventArgs (e.Graphics, this));
274
275                                 Rectangle text_layout_rect;
276                                 Rectangle image_layout_rect;
277
278                                 Rectangle r = this.ContentRectangle;
279                                 r.Width -= (this.drop_down_button_width + 1);
280                                 
281                                 this.CalculateTextAndImageRectangles (r, out text_layout_rect, out image_layout_rect);
282
283                                 if (text_layout_rect != Rectangle.Empty)
284                                         this.Owner.Renderer.DrawItemText (new System.Windows.Forms.ToolStripItemTextRenderEventArgs (e.Graphics, this, this.Text, text_layout_rect, font_color, this.Font, this.TextAlign));
285                                 if (image_layout_rect != Rectangle.Empty)
286                                         this.Owner.Renderer.DrawItemImage (new System.Windows.Forms.ToolStripItemImageRenderEventArgs (e.Graphics, this, draw_image, image_layout_rect));
287
288                                 this.Owner.Renderer.DrawArrow (new ToolStripArrowRenderEventArgs (e.Graphics, this, new Rectangle (this.Width - 9, 1, 6, this.Height), Color.Black, ArrowDirection.Down));
289                                 
290                                 return;
291                         }
292                 }
293
294                 protected override void OnRightToLeftChanged (EventArgs e)
295                 {
296                         base.OnRightToLeftChanged (e);
297                 }
298                 
299                 protected internal override bool ProcessDialogKey (Keys keyData)
300                 {
301                         if (this.Selected && keyData == Keys.Enter && this.DefaultItem != null) {
302                                 this.DefaultItem.FireEvent (EventArgs.Empty, ToolStripItemEventType.Click);
303                                 return true;
304                         }
305
306                         return base.ProcessDialogKey (keyData);
307                 }
308
309                 protected internal override bool ProcessMnemonic (char charCode)
310                 {
311                         if (!this.Selected)
312                                 this.Parent.ChangeSelection (this);
313
314                         if (this.HasDropDownItems)
315                                 this.ShowDropDown ();
316                         else
317                                 this.PerformClick ();
318
319                         return true;
320                 }
321                 #endregion
322
323                 #region Internal Methods
324                 internal override void HandleClick (int mouse_clicks, EventArgs e)
325                 {
326                         base.HandleClick (mouse_clicks, e);
327
328                         MouseEventArgs mea = e as MouseEventArgs;
329                         
330                         if (mea != null)
331                                 if (ButtonBounds.Contains (mea.Location))
332                                         OnButtonClick (EventArgs.Empty);
333                 }
334                 #endregion
335                 
336                 #region Public Events
337                 static object ButtonClickEvent = new object ();
338                 static object ButtonDoubleClickEvent = new object ();
339                 static object DefaultItemChangedEvent = new object ();
340
341                 public event EventHandler ButtonClick {
342                         add { Events.AddHandler (ButtonClickEvent, value); }
343                         remove {Events.RemoveHandler (ButtonClickEvent, value); }
344                 }
345                 public event EventHandler ButtonDoubleClick {
346                         add { Events.AddHandler (ButtonDoubleClickEvent, value); }
347                         remove {Events.RemoveHandler (ButtonDoubleClickEvent, value); }
348                 }
349                 public event EventHandler DefaultItemChanged {
350                         add { Events.AddHandler (DefaultItemChangedEvent, value); }
351                         remove {Events.RemoveHandler (DefaultItemChangedEvent, value); }
352                 }
353                 #endregion
354
355                 #region ToolStripSplitButtonAccessibleObject Class
356                 public class ToolStripSplitButtonAccessibleObject : ToolStripItemAccessibleObject
357                 {
358                         #region Public Constructor
359                         public ToolStripSplitButtonAccessibleObject (ToolStripSplitButton item) : base (item)
360                         {
361                         }
362                         #endregion
363
364                         #region Public Method
365                         public override void DoDefaultAction ()
366                         {
367                                 (owner_item as ToolStripSplitButton).PerformButtonClick ();
368                         }
369                         #endregion
370                 }
371                 #endregion
372         }
373 }
374 #endif