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 && Parent.Visible) {
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 == text)
257                                         return;
258
259                                 text = value;
260                                 if (Parent != null)
261                                         Parent.Redraw (true);
262                         }
263                 }
264
265                 [DefaultValue ("")]
266                 [Localizable (true)]
267                 public string ToolTipText {
268                         get { return tooltip; }
269                         set { tooltip = value; }
270                 }
271
272                 [DefaultValue (true)]
273                 [Localizable (true)]
274                 public bool Visible {
275                         get { return visible; }
276                         set {
277                                 if (value == visible)
278                                         return;
279
280                                 visible = value;
281                                 if (Parent != null)
282                                         Parent.Redraw (true);
283                         }
284                 }
285                 #endregion
286
287                 #region internal methods
288                 internal void SetParent (ToolBar parent)
289                 {
290                         if (Parent == parent)
291                                 return;
292
293                         if (Parent != null)
294                                 Parent.Buttons.Remove (this);
295
296                         this.parent = parent;
297                 }
298
299                 internal bool Layout ()
300                 {
301                         if (Parent == null || !Visible)
302                                 return false;
303
304                         Size psize = Parent.ButtonSize;
305                         Size size = psize;
306                         if (!Parent.SizeSpecified) {
307                                 size = CalculateSize ();
308                                 if (size.Width == 0 || size.Height == 0)
309                                         size = psize;
310                         }
311                         return Layout (size);
312                 }
313
314                 internal bool Layout (Size size)
315                 {
316                         if (Parent == null || !Visible)
317                                 return false;
318
319                         bounds.Size = size;
320
321                         Size image_size = (Parent.ImageSize == Size.Empty) ? new Size (16, 16) : Parent.ImageSize;
322                         int grip = ThemeEngine.Current.ToolBarImageGripWidth;
323
324                         Rectangle new_image_rect, new_text_rect;
325                         
326                         if (Parent.TextAlign == ToolBarTextAlign.Underneath) {
327                                 new_image_rect = new Rectangle ((bounds.Size.Width - image_size.Width) / 2 - grip, 0, image_size.Width + 2 + grip, image_size.Height + 2 * grip);
328                                 new_text_rect = new Rectangle (0, new_image_rect.Height, bounds.Size.Width, bounds.Size.Height - new_image_rect.Height);
329                         } else {
330                                 new_image_rect = new Rectangle (0, 0, image_size.Width + 2 * grip, image_size.Height + 2 * grip);
331                                 new_text_rect = new Rectangle (new_image_rect.Width, 0, bounds.Size.Width - new_image_rect.Width, bounds.Size.Height);
332                         }
333
334                         bool changed = false;
335
336                         if (new_image_rect != image_rect || new_text_rect != text_rect)
337                                 changed = true;
338
339                         image_rect = new_image_rect;
340                         text_rect = new_text_rect;
341
342                         return changed;
343                 }
344
345                 const int text_padding = 3;
346
347                 Size TextSize {
348                         get {
349                                 SizeF sz = Parent.DeviceContext.MeasureString (Text, Parent.Font);
350                                 if (sz == SizeF.Empty)
351                                         return Size.Empty;
352                                 return new Size ((int) Math.Ceiling (sz.Width) + 2 * text_padding, (int) Math.Ceiling (sz.Height));
353                         }
354                 }
355
356                 Size CalculateSize ()
357                 {
358                         if (Parent == null)
359                                 return Size.Empty;
360
361                         Theme theme = ThemeEngine.Current;
362
363                         int ht = Parent.ButtonSize.Height + 2 * theme.ToolBarGripWidth;
364
365                         if (Style == ToolBarButtonStyle.Separator)
366                                 return new Size (theme.ToolBarSeparatorWidth, ht);
367
368                         Size size = TextSize;
369                         Size image_size = (Parent.ImageSize == Size.Empty) ? new Size (16, 16) : Parent.ImageSize;
370
371                         int image_width = image_size.Width + 2 * theme.ToolBarImageGripWidth; 
372                         int image_height = image_size.Height + 2 * theme.ToolBarImageGripWidth; 
373
374                         if (Parent.TextAlign == ToolBarTextAlign.Right) {
375                                 size.Width =  image_width + size.Width;
376                                 size.Height = (size.Height > image_height) ? size.Height : image_height;
377                         } else {
378                                 size.Height = image_height + size.Height;
379                                 size.Width = (size.Width > image_width) ? size.Width : image_width;
380                         }
381
382                         size.Width += theme.ToolBarGripWidth;
383                         size.Height += theme.ToolBarGripWidth;
384                         return size;
385                 }
386
387                 internal void InvalidateBorder ()
388                 {
389                         if (ThemeEngine.Current.ToolBarInvalidateEntireButton) {
390                                 Invalidate ();
391                         }
392                         else {
393                                 if (Rectangle == Rectangle.Empty)
394                                         return;
395
396                                 /* invalidate the four sides of our border */
397                                 Parent.Invalidate (new Rectangle (Rectangle.X - 2, Rectangle.Y - 2,
398                                                                   Rectangle.Width + 4, 4));
399                                 Parent.Invalidate (new Rectangle (Rectangle.X - 2, Rectangle.Y - 2,
400                                                                   4, Rectangle.Height + 4));
401                                 Parent.Invalidate (new Rectangle (Rectangle.X - 2, Rectangle.Y + Rectangle.Height - 2,
402                                                                   Rectangle.Width + 4, 4));
403                                 Parent.Invalidate (new Rectangle (Rectangle.X + Rectangle.Width - 2, Rectangle.Y - 2,
404                                                                   4, Rectangle.Height + 4));
405                         }
406                 }
407
408                 void Invalidate ()
409                 {
410                         if (Parent != null)
411                                 Parent.Invalidate (Rectangle);
412                 }
413
414                 #endregion Internal Methods
415
416                 #region methods
417                 protected override void Dispose (bool disposing)
418                 {
419                         base.Dispose (disposing);
420                 }
421
422                 public override string ToString ()
423                 {
424                         return string.Format ("ToolBarButton: {0}, Style: {1}", text, style);
425                 }
426                 #endregion
427         }
428 }