2006-03-21 Mike Kestner <mkestner@novell.com>
[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 (! pushed)
74                                         hilight = value;
75                                 else
76                                         hilight = false;        
77                         }
78                 }
79
80                 internal Image Image {
81                         get {
82                                 if (Parent == null || Parent.ImageList == null)
83                                         return null;
84
85                                 ImageList list = Parent.ImageList;
86                                 if (ImageIndex > -1 && ImageIndex < list.Images.Count)
87                                         return list.Images [ImageIndex];
88
89                                 return null;
90                         }
91                 }
92
93                 Rectangle image_rect;
94                 internal Rectangle ImageRectangle {
95                         get {
96                                 Rectangle result = image_rect;
97                                 result.X += bounds.X;
98                                 result.Y += bounds.Y;
99                                 return result; 
100                         }
101                 }
102
103                 Rectangle text_rect;
104                 internal Rectangle TextRectangle {
105                         get { 
106                                 Rectangle result = text_rect;
107                                 result.X += bounds.X;
108                                 result.Y += bounds.Y;
109                                 return result; 
110                         }
111                 }
112
113                 Rectangle bounds;
114                 internal Point Location {
115                         //get { return location; }
116                         set { 
117                                 if (bounds.Location == value)
118                                         return;
119
120                                 if (bounds != Rectangle.Empty)
121                                         Invalidate ();
122
123                                 bounds.Location = value;
124                                 Invalidate ();
125                         }
126                 }
127
128                 internal bool Pressed {
129                         get {
130                                 if (pressed && inside)
131                                         return true;
132                                 else
133                                         return false;
134                         }
135                         set { pressed = value; }
136                 }
137                 #endregion internal properties
138
139                 #region properties
140                 [DefaultValue (null)]
141                 [TypeConverter (typeof (ReferenceConverter))]
142                 public Menu DropDownMenu {
143                         get { return menu; }
144
145                         set {
146                                 if (value is ContextMenu)
147                                         menu = (ContextMenu) value;
148                                 else
149                                         throw new ArgumentException ("DropDownMenu must be of type ContextMenu.");
150                         }
151                 }
152
153                 [DefaultValue (true)]
154                 [Localizable (true)]
155                 public bool Enabled {
156                         get { return enabled; }
157                         set {
158                                 if (value == enabled)
159                                         return;
160
161                                 enabled = value;
162                                 Invalidate ();
163                         }
164                 }
165
166                 [DefaultValue (-1)]
167                 [Editor ("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
168                 [Localizable (true)]
169                 [TypeConverter (typeof (ImageIndexConverter))]
170                 public int ImageIndex {
171                         get { return image_index; }
172                         set {
173                                 if (value < -1)
174                                         throw new ArgumentException ("ImageIndex value must be above or equal to -1.");
175
176                                 if (value == image_index)
177                                         return;
178
179                                 image_index = value;
180                                 Invalidate ();
181                         }
182                 }
183
184                 [Browsable (false)]
185                 public ToolBar Parent {
186                         get { return parent; }
187                 }
188
189                 [DefaultValue (false)]
190                 public bool PartialPush {
191                         get { return partial_push; }
192                         set {
193                                 if (value == partial_push)
194                                         return;
195
196                                 partial_push = value;
197                                 Invalidate ();
198                         }
199                 }
200
201                 [DefaultValue (false)]
202                 public bool Pushed {
203                         get { return pushed; }
204                         set {
205                                 if (value == pushed)
206                                         return;
207
208                                 pushed = value;
209                                 if (pushed)
210                                         hilight = false;
211                                 Invalidate ();
212                         }
213                 }
214
215                 public Rectangle Rectangle {
216                         get {
217                                 if (Visible && Parent != null && Parent.Visible) {
218                                         Rectangle result = bounds;
219                                         if (Style == ToolBarButtonStyle.DropDownButton && Parent.DropDownArrows)
220                                                 result.Width += ThemeEngine.Current.ToolBarDropDownWidth;
221                                         return result;
222                                 } else
223                                         return Rectangle.Empty;
224                         }
225                 }
226
227                 [DefaultValue (ToolBarButtonStyle.PushButton)]
228                 [RefreshProperties (RefreshProperties.Repaint)]
229                 public ToolBarButtonStyle Style {
230                         get { return style; }
231                         set {
232                                 if (value == style)
233                                         return;
234
235                                 style = value;
236                                 Invalidate ();
237                         }
238                 }
239
240                 [Bindable (true)]
241                 [DefaultValue (null)]
242                 [Localizable (false)]
243                 [TypeConverter (typeof (StringConverter))]
244                 public object Tag {
245                         get { return tag; }
246                         set { tag = value; }
247                 }
248
249                 [DefaultValue ("")]
250                 [Localizable (true)]
251                 public string Text {
252                         get { return text; }
253                         set {
254                                 if (value == text)
255                                         return;
256
257                                 text = value;
258                                 Invalidate ();
259                         }
260                 }
261
262                 [DefaultValue ("")]
263                 [Localizable (true)]
264                 public string ToolTipText {
265                         get { return tooltip; }
266                         set { tooltip = value; }
267                 }
268
269                 [DefaultValue (true)]
270                 [Localizable (true)]
271                 public bool Visible {
272                         get { return visible; }
273                         set {
274                                 if (value == visible)
275                                         return;
276
277                                 visible = value;
278                                 if (Parent != null)
279                                         Parent.Redraw (true);
280                         }
281                 }
282                 #endregion
283
284                 #region internal methods
285                 internal void SetParent (ToolBar parent)
286                 {
287                         if (Parent == parent)
288                                 return;
289
290                         if (Parent != null)
291                                 Parent.Buttons.Remove (this);
292
293                         this.parent = parent;
294                 }
295
296                 internal void Layout ()
297                 {
298                         if (Parent == null || !Visible)
299                                 return;
300
301                         Size sz = CalculateSize ();
302                         Layout (sz);
303                 }
304
305                 internal void Layout (Size size)
306                 {
307                         if (Parent == null || !Visible)
308                                 return;
309
310                         bounds.Size = size;
311
312                         Image image = Image;
313                         if (image == null) {
314                                 text_rect = new Rectangle (Point.Empty, size);
315                                 image_rect = Rectangle.Empty;
316                                 return;
317                         }
318
319                         int grip = ThemeEngine.Current.ToolBarImageGripWidth;
320
321                         if (Parent.TextAlign == ToolBarTextAlign.Underneath) {
322                                 image_rect = new Rectangle ((size.Width - image.Width) / 2 - grip, 0, image.Width + 2 + grip, image.Height + 2 * grip);
323
324                                 text_rect = new Rectangle (0, image_rect.Bottom, size.Width, size.Height - image_rect.Height);
325                         } else {
326                                 image_rect = new Rectangle (0, 0, image.Width + 2 * grip, image.Height + 2 * grip);
327
328                                 text_rect = new Rectangle (image_rect.Right, 0, size.Width - image_rect.Width, size.Height);
329                         }
330                 }
331
332                 const int text_padding = 3;
333
334                 Size CalculateSize ()
335                 {
336                         Theme theme = ThemeEngine.Current;
337
338                         int ht = Parent.ButtonSize.Height + 2 * theme.ToolBarGripWidth;
339
340                         if (Style == ToolBarButtonStyle.Separator)
341                                 return new Size (theme.ToolBarSeparatorWidth, ht);
342
343                         SizeF sz = Parent.DeviceContext.MeasureString (Text, Parent.Font);
344                         Size size = new Size ((int) Math.Ceiling (sz.Width) + 2 * text_padding, 
345                                               (int) Math.Ceiling (sz.Height));
346
347                         Image image = Image;
348
349                         if (image == null)
350                                 return size;
351
352                         int image_width = image.Width + 2 * theme.ToolBarImageGripWidth; 
353                         int image_height = image.Height + 2 * theme.ToolBarImageGripWidth; 
354
355                         if (Parent.TextAlign == ToolBarTextAlign.Right) {
356                                 size.Width =  image_width + size.Width;
357                                 size.Height = (size.Height > image_height) ? size.Height : image_height;
358                         } else {
359                                 size.Height = image_height + size.Height;
360                                 size.Width = (size.Width > image_width) ? size.Width : image_width;
361                         }
362
363                         size.Width += theme.ToolBarGripWidth;
364                         size.Height += theme.ToolBarGripWidth;
365                         return size;
366                 }
367
368                 void Invalidate ()
369                 {
370                         if (Parent != null)
371                                 Parent.Invalidate (Rectangle);
372                 }
373
374                 #endregion Internal Methods
375
376                 #region methods
377                 protected override void Dispose (bool disposing)
378                 {
379                         base.Dispose (disposing);
380                 }
381
382                 public override string ToString ()
383                 {
384                         return string.Format ("ToolBarButton: {0}, Style: {1}", text, style);
385                 }
386                 #endregion
387         }
388 }