* ImageList.cs: When the image stream is set pull all the images
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ButtonBase.cs
1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
8 // 
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 // 
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 //
20 // Copyright (c) 2004-2005 Novell, Inc.
21 //
22 // Authors:
23 //      Peter Bartok    pbartok@novell.com
24 //
25
26 // COMPLETE
27
28 using System.ComponentModel;
29 using System.ComponentModel.Design;
30 using System.Drawing;
31 using System.Drawing.Text;
32
33 namespace System.Windows.Forms {
34         public abstract class ButtonBase : Control {
35                 #region Local Variables
36                 internal FlatStyle              flat_style;
37                 internal int                    image_index;
38                 internal Image                  image;
39                 internal ImageList              image_list;
40                 internal ContentAlignment       image_alignment;
41                 internal ContentAlignment       text_alignment;
42                 private bool                    is_default;
43                 internal bool                   is_pressed;
44                 internal bool                   enter_state;
45                 internal bool                   redraw;
46                 internal StringFormat           text_format;
47                 #endregion      // Local Variables
48
49                 #region Private Properties and Methods
50                 internal ButtonState ButtonState {
51                         get {
52                                 ButtonState     ret = ButtonState.Normal;
53
54                                 if (Enabled) {
55                                         // Popup style is only followed as long as the mouse isn't "in" the control
56                                         if (is_entered) {
57                                                 if (flat_style == FlatStyle.Flat) {
58                                                         ret |= ButtonState.Flat;
59                                                 }
60                                         } else {
61                                                 if (flat_style == FlatStyle.Flat || flat_style == FlatStyle.Popup) {
62                                                         ret |= ButtonState.Flat;
63                                                 }
64                                         }
65
66                                         if (is_entered && is_pressed) {
67                                                 ret |= ButtonState.Pushed;
68                                         }
69                                 } else {
70                                         ret |= ButtonState.Inactive;
71                                         if ((flat_style == FlatStyle.Flat) || (flat_style == FlatStyle.Popup)) {
72                                                 ret |= ButtonState.Flat;
73                                         }
74                                 }
75                                 return ret;
76                         }
77                 }
78
79                 [MonoTODO("Make the FillRectangle use a global brush instead of creating one every time")]
80                 internal void Redraw() {
81                         redraw = true;
82                         Refresh ();
83                 }
84
85                 // Derived classes should override Draw method and we dont want
86                 // to break the control signature, hence this approach.
87                 internal virtual void Draw (PaintEventArgs pevent) {
88                         if (redraw) {
89                                 ThemeEngine.Current.DrawButtonBase(this.DeviceContext, pevent.ClipRectangle, this);
90                                 redraw = false;
91                         }
92                 }
93
94                 internal virtual void HaveDoubleClick() {
95                         // override me
96                 }
97
98                 private void RedrawEvent(object sender, System.EventArgs e) {
99                         Redraw();
100                 }
101
102                 #endregion      // Private Properties and Methods
103
104                 #region Public Constructors
105                 protected ButtonBase() : base() {
106                         flat_style      = FlatStyle.Standard;
107                         image_index     = -1;
108                         image           = null;
109                         image_list      = null;
110                         image_alignment = ContentAlignment.MiddleCenter;
111                         text_alignment  = ContentAlignment.MiddleCenter;
112                         ime_mode        = ImeMode.Inherit;
113                         is_default      = false;
114                         is_entered      = false;
115                         is_pressed      = false;
116                         has_focus       = false;
117                         redraw          = true;
118                         text_format     = new StringFormat();
119                         text_format.Alignment = StringAlignment.Center;
120                         text_format.LineAlignment = StringAlignment.Center;
121                         text_format.HotkeyPrefix = HotkeyPrefix.Show;
122
123                         TextChanged+=new System.EventHandler(RedrawEvent);
124                         ForeColorChanged+=new EventHandler(RedrawEvent);
125                         BackColorChanged+=new System.EventHandler(RedrawEvent);
126                         FontChanged+=new EventHandler(RedrawEvent);
127                         SizeChanged+=new EventHandler(RedrawEvent);
128
129                         SetStyle(ControlStyles.UserPaint, true);
130                         SetStyle(ControlStyles.AllPaintingInWmPaint, true);
131                         SetStyle(ControlStyles.ResizeRedraw, true);
132                         SetStyle(ControlStyles.StandardClick | ControlStyles.StandardDoubleClick, false);
133                 }
134                 #endregion      // Public Constructors
135
136                 #region Public Instance Properties
137                 [Localizable(true)]
138                 [DefaultValue(FlatStyle.Standard)]
139                 public FlatStyle FlatStyle {
140                         get {
141                                 return flat_style;
142                         }
143
144                         set { 
145                                 flat_style = value; 
146                                 Redraw();
147                         }
148                 }
149                 
150                 [Localizable(true)]
151                 public Image Image {
152                         get {
153                                 return image;
154                         }
155
156                         set { 
157                                 image = value;
158                                 Redraw();
159                         }
160                 }
161
162                 [Localizable(true)]
163                 [DefaultValue(ContentAlignment.MiddleCenter)]
164                 public ContentAlignment ImageAlign {
165                         get {
166                                 return image_alignment;
167                         }
168
169                         set {
170                                 image_alignment=value;
171                                 Redraw();
172                         }
173                 }
174
175                 [Localizable(true)]
176                 [DefaultValue(-1)]
177                 [Editor("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design, typeof(System.Drawing.Design.UITypeEditor))]
178                 [TypeConverter(typeof(ImageIndexConverter))]
179                 public int ImageIndex {
180                         get {
181                                 if (image_list==null) {
182                                         return -1;
183                                 }
184                                 return image_index;
185                         }
186
187                         set {
188                                 image_index=value;
189                                 Redraw();
190                         }
191                 }
192
193                 [DefaultValue(null)]
194                 public ImageList ImageList {
195                         get {
196                                 return image_list;
197                         }
198
199                         set {
200                                 if (image_list != null) {
201                                         image_list.Dispose();
202                                 }
203
204                                 image_list = value;
205                                 if (value != null) {
206                                         if (image != null) {
207                                                 image=null;
208                                         }
209                                         if (image_list.Images.Count >= image_index) {
210                                                 image_index=image_list.Images.Count-1;
211                                         }
212                                 }
213                                 Redraw();
214                         }
215                 }
216
217                 [Browsable(false)]
218                 [EditorBrowsable (EditorBrowsableState.Never)]
219                 public new ImeMode ImeMode {
220                         get {
221                                 return ime_mode;
222                         }
223
224                         set {
225                                 if (ime_mode != value) {
226                                         ime_mode = value;
227
228                                         if (ImeModeChanged != null) {
229                                                 ImeModeChanged(this, EventArgs.Empty);
230                                         }
231                                 }
232                         }
233                 }
234
235                 [Localizable(true)]
236                 [DefaultValue(ContentAlignment.MiddleCenter)]
237                 public virtual ContentAlignment TextAlign {
238                         get {
239                                 return text_alignment;
240                         }
241
242                         set {
243                                 if (text_alignment != value) {
244                                         text_alignment = value;
245                                         switch(text_alignment) {
246                                                 case ContentAlignment.TopLeft: {
247                                                         text_format.Alignment=StringAlignment.Near;
248                                                         text_format.LineAlignment=StringAlignment.Near;
249                                                         break;
250                                                 }
251
252                                                 case ContentAlignment.TopCenter: {
253                                                         text_format.Alignment=StringAlignment.Center;
254                                                         text_format.LineAlignment=StringAlignment.Near;
255                                                         break;
256                                                 }
257
258                                                 case ContentAlignment.TopRight: {
259                                                         text_format.Alignment=StringAlignment.Far;
260                                                         text_format.LineAlignment=StringAlignment.Near;
261                                                         break;
262                                                 }
263
264                                                 case ContentAlignment.MiddleLeft: {
265                                                         text_format.Alignment=StringAlignment.Near;
266                                                         text_format.LineAlignment=StringAlignment.Center;
267                                                         break;
268                                                 }
269
270                                                 case ContentAlignment.MiddleCenter: {
271                                                         text_format.Alignment=StringAlignment.Center;
272                                                         text_format.LineAlignment=StringAlignment.Center;
273                                                         break;
274                                                 }
275
276                                                 case ContentAlignment.MiddleRight: {
277                                                         text_format.Alignment=StringAlignment.Far;
278                                                         text_format.LineAlignment=StringAlignment.Center;
279                                                         break;
280                                                 }
281
282                                                 case ContentAlignment.BottomLeft: {
283                                                         text_format.Alignment=StringAlignment.Near;
284                                                         text_format.LineAlignment=StringAlignment.Far;
285                                                         break;
286                                                 }
287
288                                                 case ContentAlignment.BottomCenter: {
289                                                         text_format.Alignment=StringAlignment.Center;
290                                                         text_format.LineAlignment=StringAlignment.Far;
291                                                         break;
292                                                 }
293
294                                                 case ContentAlignment.BottomRight: {
295                                                         text_format.Alignment=StringAlignment.Far;
296                                                         text_format.LineAlignment=StringAlignment.Far;
297                                                         break;
298                                                 }
299                                         }       
300                                         Redraw();
301                                 }
302                         }
303                 }
304
305                 #endregion      // Public Instance Properties
306
307                 #region Protected Instance Properties
308                 protected override CreateParams CreateParams {
309                         get { 
310                                 CreateParams    cp;
311
312                                 cp=base.CreateParams;
313
314                                 cp.Style=(int)(WindowStyles.WS_VISIBLE | WindowStyles.WS_CHILD | WindowStyles.WS_CLIPSIBLINGS | WindowStyles.WS_CLIPCHILDREN);
315
316                                 return cp;
317                         }
318                 }
319
320                 protected override ImeMode DefaultImeMode {
321                         get {
322                                 return ImeMode.Inherit;
323                         }
324                 }
325
326                 protected override Size DefaultSize {
327                         get {
328                                 return ThemeEngine.Current.ButtonBaseDefaultSize;
329                         }
330                 }
331
332                 protected bool IsDefault {
333                         get {
334                                 return is_default;
335                         }
336
337                         set {
338                                 if (is_default != value) {
339                                         is_default = true;
340                                         Redraw();
341                                 }
342                         }
343                 }
344                 #endregion      // Public Instance Properties
345
346                 #region Protected Instance Methods
347                 [MonoTODO("Finish setting properties of the AccessibleObject")]
348                 protected override AccessibleObject CreateAccessibilityInstance() {
349                         AccessibleObject ao;
350                         ao=base.CreateAccessibilityInstance();
351                         ao.description="Button";
352
353                         return ao;
354                 }
355
356                 protected override void Dispose(bool Disposing) {
357                         base.Dispose(Disposing);
358                 }
359
360                 protected override void OnEnabledChanged(EventArgs e) {
361                         Redraw();
362                         base.OnEnabledChanged(e);
363                 }
364
365                 protected override void OnGotFocus(EventArgs e) {
366                         has_focus=true;
367                         Redraw();
368                         base.OnGotFocus(e);
369                 }
370
371                 protected override void OnKeyDown(KeyEventArgs kevent) {
372                         if (is_enabled && (kevent.KeyData == Keys.Space)) {
373                                 enter_state = is_entered;
374                                 is_entered = true;
375                                 OnMouseDown(new MouseEventArgs(MouseButtons.Left, 1, 2, 2, 0));
376                                 kevent.Handled=true;
377                         }
378                         base.OnKeyDown(kevent);
379                 }
380
381                 protected override void OnKeyUp(KeyEventArgs kevent) {
382                         if (is_enabled && (kevent.KeyData == Keys.Space)) {
383                                 OnMouseUp(new MouseEventArgs(MouseButtons.Left, 1, 2, 2, 0));
384                                 is_entered = enter_state;
385                                 kevent.Handled=true;
386                         }
387                         base.OnKeyUp(kevent);
388                 }
389
390                 protected override void OnLostFocus(EventArgs e) {
391                         has_focus=false;
392                         Redraw();
393                         base.OnLostFocus(e);
394                 }
395
396                 protected override void OnMouseDown(MouseEventArgs mevent) {
397                         if (is_enabled && (mevent.Button == MouseButtons.Left)) {
398                                 is_pressed = true;
399                                 this.Capture = true;
400                                 Redraw();
401                         }
402
403                         base.OnMouseDown(mevent);
404                 }
405
406                 protected override void OnMouseEnter(EventArgs e) {
407                         is_entered=true;
408                         if ((this.flat_style == FlatStyle.Flat) || (this.flat_style == FlatStyle.Popup)) {
409                                 Redraw();
410                         }
411                         base.OnMouseEnter(e);
412                 }
413
414                 protected override void OnMouseLeave(EventArgs e) {
415                         is_entered=false;
416                         if ((this.flat_style == FlatStyle.Flat) || (this.flat_style == FlatStyle.Popup)) {
417                                 Redraw();
418                         }
419                         base.OnMouseLeave(e);
420                 }
421
422                 protected override void OnMouseMove(MouseEventArgs mevent) {
423                         bool    inside = false;
424                         bool    redraw = false;
425
426                         if (mevent.X>=0 && mevent.Y>=0 && mevent.X<this.client_size.Width && mevent.Y<=this.client_size.Height) {
427                                 inside = true;
428                         }
429
430                         // If the button was pressed and we leave, release the button press and vice versa
431                         if (this.Capture && (inside != is_pressed)) {
432                                 is_pressed = inside;
433                                 redraw = true;
434                         }
435
436                         if (is_entered != inside) {
437                                 is_entered = inside;
438                                 redraw = true;
439                         }
440
441                         if (redraw) {
442                                 Redraw();
443                         }
444
445                         base.OnMouseMove(mevent);
446                 }
447
448                 protected override void OnMouseUp(MouseEventArgs mevent) {
449                         if (this.Capture && mevent.Button == MouseButtons.Left) {
450                                 this.Capture = false;
451                                 if (is_pressed) {
452                                         is_pressed = false;
453                                         Redraw();
454                                 } else if ((this.flat_style == FlatStyle.Flat) || (this.flat_style == FlatStyle.Popup)) {
455                                         Redraw();
456                                 }
457
458                                 if (mevent.X>=0 && mevent.Y>=0 && mevent.X<this.client_size.Width && mevent.Y<=this.client_size.Height) {
459                                         OnClick(EventArgs.Empty);
460                                 }
461                         }
462                         base.OnMouseUp(mevent);
463                 }
464
465                 protected override void OnPaint(PaintEventArgs pevent) {
466                         Draw (pevent);
467                         pevent.Graphics.DrawImage(this.ImageBuffer, pevent.ClipRectangle, pevent.ClipRectangle, GraphicsUnit.Pixel);
468                         base.OnPaint (pevent);
469                 }
470
471                 protected override void OnParentChanged(EventArgs e) {
472                         base.OnParentChanged(e);
473                 }
474
475                 protected override void OnTextChanged(EventArgs e) {
476                         Redraw();
477                         base.OnTextChanged(e);
478                 }
479
480                 protected override void OnVisibleChanged(EventArgs e) {
481                         if (!Visible) {
482                                 is_pressed = false;
483                                 has_focus = false;
484                                 is_entered = false;
485                         }
486                         base.OnVisibleChanged(e);
487                 }
488
489                 protected void ResetFlagsandPaint() {
490                         // Nothing to do; MS internal
491                         // Should we do Redraw (); ?
492                 }
493
494                 protected override void WndProc(ref Message m) {
495                         switch((Msg)m.Msg) {
496                                 case Msg.WM_LBUTTONDBLCLK: {
497                                         HaveDoubleClick();
498                                         break;
499                                 }
500
501                                 case Msg.WM_MBUTTONDBLCLK: {
502                                         HaveDoubleClick();
503                                         break;
504                                 }
505
506                                 case Msg.WM_RBUTTONDBLCLK: {
507                                         HaveDoubleClick();
508                                         break;
509                                 }
510                         }
511                         base.WndProc (ref m);
512                 }
513                 #endregion      // Public Instance Properties
514
515                 #region Events
516                 [Browsable(false)]
517                 [EditorBrowsable (EditorBrowsableState.Never)]
518                 public new event EventHandler ImeModeChanged;
519                 #endregion      // Events
520         }
521 }