New test.
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ToolBarButton.cs
1 // System.Windows.Forms.ToolBarButton.cs
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining
4 // a copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to
8 // permit persons to whom the Software is furnished to do so, subject to
9 // the following conditions:
10 // 
11 // The above copyright notice and this permission notice shall be
12 // included in all copies or substantial portions of the Software.
13 // 
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 //
22 // Copyright (C) 2004-2006 Novell, Inc. (http://www.novell.com)
23 //
24 // Authors:
25 //      Ravindra (rkumar@novell.com)
26 //      Mike Kestner <mkestner@novell.com>
27
28
29 using System.ComponentModel;
30 using System.ComponentModel.Design;
31 using System.Drawing;
32 using System.Drawing.Imaging;
33
34 namespace System.Windows.Forms
35 {
36         [DefaultProperty ("Text")]
37         [Designer ("System.Windows.Forms.Design.ToolBarButtonDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
38         [DesignTimeVisible (false)]
39         [ToolboxItem (false)]
40         public class ToolBarButton : Component
41         {
42                 #region instance variable
43                 private bool enabled = true;
44                 private int image_index = -1;
45                 private ContextMenu menu;
46                 private ToolBar parent;
47                 private bool partial_push = false;
48                 private bool pushed = false;
49                 private ToolBarButtonStyle style = ToolBarButtonStyle.PushButton;
50                 private object tag;
51                 private string text = "";
52                 private string tooltip = "";
53                 private bool visible = true;
54                 internal bool dd_pressed = false; // to check for a mouse down on dropdown rect
55                 internal bool hilight = false;    // to hilight buttons in flat style
56                 internal bool inside = false;     // to handle the mouse move event with mouse pressed
57                 internal bool pressed = false;    // this is to check for mouse down on a button
58                 #endregion
59
60                 #region constructors
61                 public ToolBarButton () { }
62
63                 public ToolBarButton (string text)
64                 {
65                         this.text = text;
66                 }
67                 #endregion
68
69                 #region internal properties
70                 internal bool Hilight {
71                         get { return hilight; }
72                         set {
73                                 if (hilight == value)
74                                         return;
75
76                                 hilight = value;
77                                 InvalidateBorder ();
78                         }
79                 }
80
81                 internal Image Image {
82                         get {
83                                 if (Parent == null || Parent.ImageList == null)
84                                         return null;
85
86                                 ImageList list = Parent.ImageList;
87                                 if (ImageIndex > -1 && ImageIndex < list.Images.Count)
88                                         return list.Images [ImageIndex];
89
90                                 return null;
91                         }
92                 }
93
94                 Rectangle image_rect;
95                 internal Rectangle ImageRectangle {
96                         get {
97                                 Rectangle result = image_rect;
98                                 result.X += bounds.X;
99                                 result.Y += bounds.Y;
100                                 return result; 
101                         }
102                 }
103
104                 Rectangle text_rect;
105                 internal Rectangle TextRectangle {
106                         get { 
107                                 Rectangle result = text_rect;
108                                 result.X += bounds.X;
109                                 result.Y += bounds.Y;
110                                 return result; 
111                         }
112                 }
113
114                 Rectangle bounds;
115                 internal Point Location {
116                         get { return bounds.Location; }
117                         set { 
118                                 if (bounds.Location == value)
119                                         return;
120
121                                 if (bounds != Rectangle.Empty)
122                                         Invalidate ();
123
124                                 bounds.Location = value;
125                                 Invalidate ();
126                         }
127                 }
128
129                 internal bool Pressed {
130                         get {
131                                 if (pressed && inside)
132                                         return true;
133                                 else
134                                         return false;
135                         }
136                         set { pressed = value; }
137                 }
138                 #endregion internal properties
139
140                 #region properties
141                 [DefaultValue (null)]
142                 [TypeConverter (typeof (ReferenceConverter))]
143                 public Menu DropDownMenu {
144                         get { return menu; }
145
146                         set {
147                                 if (value is ContextMenu)
148                                         menu = (ContextMenu) value;
149                                 else
150                                         throw new ArgumentException ("DropDownMenu must be of type ContextMenu.");
151                         }
152                 }
153
154                 [DefaultValue (true)]
155                 [Localizable (true)]
156                 public bool Enabled {
157                         get { return enabled; }
158                         set {
159                                 if (value == enabled)
160                                         return;
161
162                                 enabled = value;
163                                 Invalidate ();
164                         }
165                 }
166
167                 [DefaultValue (-1)]
168                 [Editor ("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
169                 [Localizable (true)]
170                 [TypeConverter (typeof (ImageIndexConverter))]
171                 public int ImageIndex {
172                         get { return image_index; }
173                         set {
174                                 if (value < -1)
175                                         throw new ArgumentException ("ImageIndex value must be above or equal to -1.");
176
177                                 if (value == image_index)
178                                         return;
179
180                                 image_index = value;
181                                 if (bounds.Size != CalculateSize ())
182                                         Parent.Redraw (true);
183                                 else
184                                         Invalidate ();
185                         }
186                 }
187
188                 [Browsable (false)]
189                 public ToolBar Parent {
190                         get { return parent; }
191                 }
192
193                 [DefaultValue (false)]
194                 public bool PartialPush {
195                         get { return partial_push; }
196                         set {
197                                 if (value == partial_push)
198                                         return;
199
200                                 partial_push = value;
201                                 Invalidate ();
202                         }
203                 }
204
205                 [DefaultValue (false)]
206                 public bool Pushed {
207                         get { return pushed; }
208                         set {
209                                 if (value == pushed)
210                                         return;
211
212                                 pushed = value;
213                                 Invalidate ();
214                         }
215                 }
216
217                 public Rectangle Rectangle {
218                         get {
219                                 if (Visible && Parent != null) {
220                                         Rectangle result = bounds;
221                                         if (Style == ToolBarButtonStyle.DropDownButton && Parent.DropDownArrows)
222                                                 result.Width += ThemeEngine.Current.ToolBarDropDownWidth;
223                                         return result;
224                                 } else
225                                         return Rectangle.Empty;
226                         }
227                 }
228
229                 [DefaultValue (ToolBarButtonStyle.PushButton)]
230                 [RefreshProperties (RefreshProperties.Repaint)]
231                 public ToolBarButtonStyle Style {
232                         get { return style; }
233                         set {
234                                 if (value == style)
235                                         return;
236
237                                 style = value;
238                                 Invalidate ();
239                         }
240                 }
241
242                 [Bindable (true)]
243                 [DefaultValue (null)]
244                 [Localizable (false)]
245                 [TypeConverter (typeof (StringConverter))]
246                 public object Tag {
247                         get { return tag; }
248                         set { tag = value; }
249                 }
250
251                 [DefaultValue ("")]
252                 [Localizable (true)]
253                 public string Text {
254                         get { return text; }
255                         set {
256                                 if (value == null) value = "";
257
258                                 if (value == text)
259                                         return;
260
261                                 text = value;
262                                 if (Parent != null)
263                                         Parent.Redraw (true);
264                         }
265                 }
266
267                 [DefaultValue ("")]
268                 [Localizable (true)]
269                 public string ToolTipText {
270                         get { return tooltip; }
271                         set {
272                                 if (value == null) value = "";
273                                 tooltip = value;
274                         }
275                 }
276
277                 [DefaultValue (true)]
278                 [Localizable (true)]
279                 public bool Visible {
280                         get { return visible; }
281                         set {
282                                 if (value == visible)
283                                         return;
284
285                                 visible = value;
286                                 if (Parent != null)
287                                         Parent.Redraw (true);
288                         }
289                 }
290                 #endregion
291
292                 #region internal methods
293                 internal void SetParent (ToolBar parent)
294                 {
295                         if (Parent == parent)
296                                 return;
297
298                         if (Parent != null)
299                                 Parent.Buttons.Remove (this);
300
301                         this.parent = parent;
302                 }
303
304                 internal bool Layout ()
305                 {
306                         if (Parent == null || !Visible)
307                                 return false;
308
309                         Size psize = Parent.ButtonSize;
310                         Size size = psize;
311                         if ((!Parent.SizeSpecified) || (Style == ToolBarButtonStyle.Separator)) {
312                                 size = CalculateSize ();
313                                 if (size.Width == 0 || size.Height == 0)
314                                         size = psize;
315                         }
316                         return Layout (size);
317                 }
318
319                 internal bool Layout (Size size)
320                 {
321                         if (Parent == null || !Visible)
322                                 return false;
323
324                         bounds.Size = size;
325
326                         Size image_size = (Parent.ImageSize == Size.Empty) ? new Size (16, 16) : Parent.ImageSize;
327                         int grip = ThemeEngine.Current.ToolBarImageGripWidth;
328
329                         Rectangle new_image_rect, new_text_rect;
330                         
331                         if (Parent.TextAlign == ToolBarTextAlign.Underneath) {
332                                 new_image_rect = new Rectangle ((bounds.Size.Width - image_size.Width) / 2 - grip, 0, image_size.Width + 2 + grip, image_size.Height + 2 * grip);
333                                 new_text_rect = new Rectangle (0, new_image_rect.Height, bounds.Size.Width, bounds.Size.Height - new_image_rect.Height);
334                         } else {
335                                 new_image_rect = new Rectangle (0, 0, image_size.Width + 2 * grip, image_size.Height + 2 * grip);
336                                 new_text_rect = new Rectangle (new_image_rect.Width, 0, bounds.Size.Width - new_image_rect.Width, bounds.Size.Height);
337                         }
338
339                         bool changed = false;
340
341                         if (new_image_rect != image_rect || new_text_rect != text_rect)
342                                 changed = true;
343
344                         image_rect = new_image_rect;
345                         text_rect = new_text_rect;
346
347                         return changed;
348                 }
349
350                 const int text_padding = 3;
351
352                 Size TextSize {
353                         get {
354                                 SizeF sz = Parent.DeviceContext.MeasureString (Text, Parent.Font);
355                                 if (sz == SizeF.Empty)
356                                         return Size.Empty;
357                                 return new Size ((int) Math.Ceiling (sz.Width) + 2 * text_padding, (int) Math.Ceiling (sz.Height));
358                         }
359                 }
360
361                 Size CalculateSize ()
362                 {
363                         if (Parent == null)
364                                 return Size.Empty;
365
366                         Theme theme = ThemeEngine.Current;
367
368                         int ht = Parent.ButtonSize.Height + 2 * theme.ToolBarGripWidth;
369
370                         if (Style == ToolBarButtonStyle.Separator)
371                                 return new Size (theme.ToolBarSeparatorWidth, ht);
372
373                         Size size = TextSize;
374                         Size image_size = (Parent.ImageSize == Size.Empty) ? new Size (16, 16) : Parent.ImageSize;
375
376                         int image_width = image_size.Width + 2 * theme.ToolBarImageGripWidth; 
377                         int image_height = image_size.Height + 2 * theme.ToolBarImageGripWidth; 
378
379                         if (Parent.TextAlign == ToolBarTextAlign.Right) {
380                                 size.Width =  image_width + size.Width;
381                                 size.Height = (size.Height > image_height) ? size.Height : image_height;
382                         } else {
383                                 size.Height = image_height + size.Height;
384                                 size.Width = (size.Width > image_width) ? size.Width : image_width;
385                         }
386
387                         size.Width += theme.ToolBarGripWidth;
388                         size.Height += theme.ToolBarGripWidth;
389                         return size;
390                 }
391
392                 internal void InvalidateBorder ()
393                 {
394                         if (ThemeEngine.Current.ToolBarInvalidateEntireButton) {
395                                 Invalidate ();
396                         }
397                         else {
398                                 if (Rectangle == Rectangle.Empty)
399                                         return;
400
401                                 /* invalidate the four sides of our border */
402                                 Parent.Invalidate (new Rectangle (Rectangle.X - 2, Rectangle.Y - 2,
403                                                                   Rectangle.Width + 4, 4));
404                                 Parent.Invalidate (new Rectangle (Rectangle.X - 2, Rectangle.Y - 2,
405                                                                   4, Rectangle.Height + 4));
406                                 Parent.Invalidate (new Rectangle (Rectangle.X - 2, Rectangle.Y + Rectangle.Height - 2,
407                                                                   Rectangle.Width + 4, 4));
408                                 Parent.Invalidate (new Rectangle (Rectangle.X + Rectangle.Width - 2, Rectangle.Y - 2,
409                                                                   4, Rectangle.Height + 4));
410                                 
411                                 if ((Style == ToolBarButtonStyle.DropDownButton) && Parent.DropDownArrows)
412                                         Parent.Invalidate (new Rectangle (Rectangle.X + (Rectangle.Width - ThemeEngine.Current.ToolBarDropDownWidth - 1),
413                                                             Rectangle.Y, 2, Rectangle.Height));
414                         }
415                 }
416
417                 internal void Invalidate ()
418                 {
419                         if (Parent != null)
420                                 Parent.Invalidate (Rectangle);
421                 }
422
423                 #endregion Internal Methods
424
425                 #region methods
426                 protected override void Dispose (bool disposing)
427                 {
428                         base.Dispose (disposing);
429                 }
430
431                 public override string ToString ()
432                 {
433                         return string.Format ("ToolBarButton: {0}, Style: {1}", text, style);
434                 }
435                 #endregion
436         }
437 }