New test.
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / Label.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-2006 Novell, Inc.
21 //
22 // Authors:
23 //      Jordi Mas i Hernandez, jordi@ximian.com
24 //      Peter Bartok, pbartok@novell.com
25 //
26 //
27
28 // COMPLETE
29
30 using System.ComponentModel;
31 using System.ComponentModel.Design;
32 using System.Drawing;
33 using System.Drawing.Text;
34 using System.Drawing.Imaging;
35 using System.Runtime.InteropServices;
36
37 namespace System.Windows.Forms
38 {
39         [DefaultProperty("Text")]
40         [Designer ("System.Windows.Forms.Design.LabelDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
41         public class Label : Control
42         {
43                 private bool autosize;
44                 private Image image;
45                 private bool render_transparent;
46                 private FlatStyle flat_style;
47                 private int preferred_height;
48                 private int preferred_width;
49                 private bool use_mnemonic;
50                 private int image_index = -1;
51                 private ImageList image_list;
52                 internal ContentAlignment image_align;
53                 internal StringFormat string_format;
54                 internal ContentAlignment text_align;
55                 static SizeF req_witdthsize = new SizeF (0,0);
56
57                 #region Events
58                 public event EventHandler AutoSizeChanged;
59
60                 [Browsable(false)]
61                 [EditorBrowsable(EditorBrowsableState.Never)]
62                 public new event EventHandler BackgroundImageChanged {
63                         add {
64                                 base.BackgroundImageChanged += value;
65                         }
66                         remove {
67                                 base.BackgroundImageChanged -= value;
68                         }
69                 }
70
71                 [Browsable(false)]
72                 [EditorBrowsable(EditorBrowsableState.Never)]
73                 public new event EventHandler ImeModeChanged {
74                         add {
75                                 base.ImeModeChanged += value;
76                         }
77                         remove {
78                                 base.ImeModeChanged -= value;
79                         }
80                 }
81
82                 [Browsable(false)]
83                 [EditorBrowsable(EditorBrowsableState.Never)]
84                 public new event KeyEventHandler KeyDown {
85                         add {
86                                 base.KeyDown += value;
87                         }
88                         remove {
89                                 base.KeyDown -= value;
90                         }
91                 }
92
93
94                 [Browsable(false)]
95                 [EditorBrowsable(EditorBrowsableState.Never)]
96                 public new event KeyPressEventHandler KeyPress {
97                         add {
98                                 base.KeyPress += value;
99                         }
100                         remove {
101                                 base.KeyPress -= value;
102                         }
103                 }
104
105
106                 [Browsable(false)]
107                 [EditorBrowsable(EditorBrowsableState.Never)]
108                 public new event KeyEventHandler KeyUp {
109                         add {
110                                 base.KeyUp += value;
111                         }
112                         remove {
113                                 base.KeyUp -= value;
114                         }
115                 }
116
117
118                 [Browsable(false)]
119                 [EditorBrowsable(EditorBrowsableState.Never)]
120                 public new event EventHandler TabStopChanged {
121                         add {
122                                 base.TabStopChanged += value;
123                         }
124                         remove {
125                                 base.TabStopChanged -= value;
126                         }
127                 }
128
129                 public event EventHandler TextAlignChanged;
130                 #endregion
131
132                 public Label ()
133                 {
134                         // Defaults in the Spec
135                         autosize = false;
136                         tab_stop = false;
137                         string_format = new StringFormat();
138                         TextAlign = ContentAlignment.TopLeft;
139                         image = null;
140                         UseMnemonic = true;
141                         image_list = null;
142                         image_align = ContentAlignment.MiddleCenter;
143                         SetUseMnemonic (UseMnemonic);
144                         flat_style = FlatStyle.Standard;
145
146                         CalcPreferredHeight ();
147                         CalcPreferredWidth ();
148
149                         AutoSizeChanged = null;
150                         TextAlignChanged = null;
151
152                         SetStyle (ControlStyles.Selectable, false);
153                         SetStyle (ControlStyles.ResizeRedraw | 
154                                 ControlStyles.UserPaint | 
155                                 ControlStyles.AllPaintingInWmPaint |
156                                 ControlStyles.SupportsTransparentBackColor |
157                                 ControlStyles.DoubleBuffer, true);
158                         
159                         HandleCreated += new EventHandler (OnHandleCreatedLB);
160                 }
161
162                 #region Public Properties
163                 [DefaultValue(false)]
164                 [Localizable(true)]
165                 [RefreshProperties(RefreshProperties.All)]
166                 public virtual bool AutoSize {
167                         get { return autosize; }
168                         set {
169                                 if (autosize == value)
170                                         return;
171
172                                 autosize = value;
173                                 CalcAutoSize ();
174                                 Refresh ();
175
176                                 OnAutoSizeChanged (EventArgs.Empty);                                    
177                         }
178                 }
179
180                 [Browsable(false)]
181                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
182                 [EditorBrowsable(EditorBrowsableState.Never)]
183                 public override Image BackgroundImage {
184                         get {
185                                 return base.BackgroundImage;
186                         }
187                         set {
188                                 base.BackgroundImage = value;
189                                 Refresh ();
190                         }
191                 }
192
193                 [DefaultValue(BorderStyle.None)]
194                 [DispId(-504)]
195                 public virtual BorderStyle BorderStyle {
196                         get { return InternalBorderStyle; }
197                         set { InternalBorderStyle = value; }
198                 }
199
200                 protected override CreateParams CreateParams {
201                         get { return base.CreateParams;}
202                 }
203
204                 protected override ImeMode DefaultImeMode {
205                         get { return ImeMode.Disable;}
206                 }
207
208                 protected override Size DefaultSize {
209                         get {return ThemeEngine.Current.LabelDefaultSize;}
210                 }
211
212                 [DefaultValue(FlatStyle.Standard)]
213                 public FlatStyle FlatStyle {
214                         get {
215                                 return flat_style;
216                         }
217                         set {
218                                 if (!Enum.IsDefined (typeof (FlatStyle), value))
219                                         throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for FlatStyle", value));
220
221                                 if (flat_style == value)
222                                         return;
223
224                                 flat_style = value;
225                                 Refresh ();
226                         }
227                 }
228
229                 [Localizable(true)]
230                 public Image Image {
231                         get {
232                                 if (image != null) {
233                                         return image;
234                                 }
235                                 
236                                 if (image_list != null && ImageIndex >= 0) {
237                                         return image_list.Images[ImageIndex];
238                                 }
239                                 
240                                 return null;
241                         }
242                         set {
243                                 if (image == value)
244                                         return;
245
246                                 image = value;
247                                 Refresh ();
248                         }
249                 }
250
251                 [DefaultValue(ContentAlignment.MiddleCenter)]
252                 [Localizable(true)]
253                 public ContentAlignment ImageAlign {
254                         get {
255                                 return image_align;
256                         }
257                         set {
258                                 if (!Enum.IsDefined (typeof (ContentAlignment), value))
259                                         throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for ContentAlignment", value));
260
261                                 if (image_align == value)
262                                         return;
263
264                                 image_align = value;
265                                 Refresh ();
266                         }
267                 }
268
269                 [DefaultValue (-1)]
270                 [Editor ("System.Windows.Forms.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))]
271                 [Localizable (true)]
272                 [TypeConverter (typeof (ImageIndexConverter))]
273                 public int ImageIndex {
274                         get { 
275                                 if (ImageList == null) {
276                                         return -1;
277                                 }
278                                 
279                                 if (image_index >= image_list.Images.Count) {
280                                         return image_list.Images.Count - 1;
281                                 }
282                                 
283                                 return image_index;
284                         }
285                         set {
286
287                                 if (value < -1)
288                                         throw new ArgumentException ();
289
290                                 if (image_index == value)
291                                         return;
292
293                                 image_index = value;
294
295                                 if (ImageList != null && image_index !=-1)
296                                         Image = null;
297
298                                 Refresh ();
299                         }
300                 }
301
302                 [DefaultValue(null)]
303                 public ImageList ImageList {
304                         get { return image_list;}
305                         set {
306                                 if (image_list == value)
307                                         return;
308                                         
309                                 image_list = value;
310
311                                 if (image_list != null && image_index !=-1)
312                                         Image = null;
313
314                                 Refresh ();
315                         }
316                 }
317
318                 [Browsable(false)]
319                 [EditorBrowsable(EditorBrowsableState.Never)]
320                 public new ImeMode ImeMode {
321                         get { return base.ImeMode; }
322                         set { base.ImeMode = value; }
323                 }
324
325                 [Browsable(false)]
326                 [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
327                 [EditorBrowsable(EditorBrowsableState.Advanced)]
328                 public virtual int PreferredHeight {
329                         get { return preferred_height; }
330                 }
331
332                 [Browsable(false)]
333                 [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden)]
334                 [EditorBrowsable(EditorBrowsableState.Advanced)]
335                 public virtual int PreferredWidth {
336                         get {return preferred_width; }
337                 }
338
339                 protected virtual bool RenderTransparent {
340                         get { return render_transparent; }
341                         set { render_transparent = value;}
342                 }
343                 
344                 [Browsable(false)]
345                 [DefaultValue(false)]
346                 [EditorBrowsable(EditorBrowsableState.Never)]
347                 public new bool TabStop  {
348                         get { return base.TabStop; }
349                         set { base.TabStop = value; }
350                 }
351
352                 [DefaultValue(ContentAlignment.TopLeft)]
353                 [Localizable(true)]
354                 public virtual ContentAlignment TextAlign {
355                         get { return text_align; }
356
357                         set {
358                                 if (!Enum.IsDefined (typeof (ContentAlignment), value))
359                                         throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for ContentAlignment", value));
360
361                                 if (text_align != value) {
362
363                                         text_align = value;
364
365                                         switch (value) {
366
367                                         case ContentAlignment.BottomLeft:
368                                                 string_format.LineAlignment = StringAlignment.Far;
369                                                 string_format.Alignment = StringAlignment.Near;
370                                                 break;
371                                         case ContentAlignment.BottomCenter:
372                                                 string_format.LineAlignment = StringAlignment.Far;
373                                                 string_format.Alignment = StringAlignment.Center;
374                                                 break;
375                                         case ContentAlignment.BottomRight:
376                                                 string_format.LineAlignment = StringAlignment.Far;
377                                                 string_format.Alignment = StringAlignment.Far;
378                                                 break;
379                                         case ContentAlignment.TopLeft:
380                                                 string_format.LineAlignment = StringAlignment.Near;
381                                                 string_format.Alignment = StringAlignment.Near;
382                                                 break;
383                                         case ContentAlignment.TopCenter:
384                                                 string_format.LineAlignment = StringAlignment.Near;
385                                                 string_format.Alignment = StringAlignment.Center;
386                                                 break;
387                                         case ContentAlignment.TopRight:
388                                                 string_format.LineAlignment = StringAlignment.Near;
389                                                 string_format.Alignment = StringAlignment.Far;
390                                                 break;
391                                         case ContentAlignment.MiddleLeft:
392                                                 string_format.LineAlignment = StringAlignment.Center;
393                                                 string_format.Alignment = StringAlignment.Near;
394                                                 break;
395                                         case ContentAlignment.MiddleRight:
396                                                 string_format.LineAlignment = StringAlignment.Center;
397                                                 string_format.Alignment = StringAlignment.Far;
398                                                 break;
399                                         case ContentAlignment.MiddleCenter:
400                                                 string_format.LineAlignment = StringAlignment.Center;
401                                                 string_format.Alignment = StringAlignment.Center;
402                                                 break;
403                                         default:
404                                                 break;
405                                         }
406
407                                         OnTextAlignChanged (EventArgs.Empty);
408                                         Refresh();
409                                 }
410                         }
411                 }
412
413                 [DefaultValue(true)]
414                 public bool UseMnemonic {
415                         get { return use_mnemonic; }
416                         set {
417                                 if (use_mnemonic != value) {
418                                         use_mnemonic = value;
419                                         SetUseMnemonic (use_mnemonic);
420                                         Refresh ();
421                                 }
422                         }
423                 }
424
425                 #endregion
426
427
428                 #region Public Methods
429
430                 protected Rectangle CalcImageRenderBounds (Image image, Rectangle area, ContentAlignment img_align)
431                 {
432                         Rectangle rcImageClip = area;
433                         rcImageClip.Inflate (-2,-2);
434
435                         int X = area.X;
436                         int Y = area.Y;
437
438                         if (img_align == ContentAlignment.TopCenter ||
439                                 img_align == ContentAlignment.MiddleCenter ||
440                                 img_align == ContentAlignment.BottomCenter) {
441                                 X += (area.Width - image.Width) / 2;
442                         }
443                         else if (img_align == ContentAlignment.TopRight ||
444                                 img_align == ContentAlignment.MiddleRight||
445                                 img_align == ContentAlignment.BottomRight) {
446                                 X += (area.Width - image.Width);
447                         }
448
449                         if( img_align == ContentAlignment.BottomCenter ||
450                                 img_align == ContentAlignment.BottomLeft ||
451                                 img_align == ContentAlignment.BottomRight) {
452                                 Y += area.Height - image.Height;
453                         }
454                         else if(img_align == ContentAlignment.MiddleCenter ||
455                                         img_align == ContentAlignment.MiddleLeft ||
456                                         img_align == ContentAlignment.MiddleRight) {
457                                 Y += (area.Height - image.Height) / 2;
458                         }
459
460                         rcImageClip.X = X;
461                         rcImageClip.Y = Y;
462                         rcImageClip.Width = image.Width;
463                         rcImageClip.Height = image.Height;
464
465                         return rcImageClip;
466                 }
467
468                 
469                 protected override AccessibleObject CreateAccessibilityInstance ()
470                 {
471                         return base.CreateAccessibilityInstance ();
472                 }
473
474                 protected override void Dispose(bool disposing)
475                 {
476                         base.Dispose (disposing);
477
478                         if (disposing)
479                                 string_format.Dispose ();
480                 }
481
482                 protected void DrawImage (Graphics g, Image image, Rectangle area, ContentAlignment img_align)
483                 {
484                         if (image == null || g == null)
485                                 return;
486
487                         Rectangle rcImageClip = CalcImageRenderBounds (image, area, img_align);
488
489                         if (Enabled)
490                                 g.DrawImage (image, rcImageClip.X, rcImageClip.Y, rcImageClip.Width, rcImageClip.Height);
491                         else
492                                 ControlPaint.DrawImageDisabled (g, image, rcImageClip.X, rcImageClip.Y, BackColor);
493                 }
494
495                 protected virtual void OnAutoSizeChanged (EventArgs e)
496                 {
497                         if (AutoSizeChanged != null)
498                                 AutoSizeChanged (this, e);
499                 }
500
501                 protected override void OnEnabledChanged (EventArgs e)
502                 {
503                         base.OnEnabledChanged (e);
504                 }
505
506                 protected override void OnFontChanged (EventArgs e)
507                 {
508                         base.OnFontChanged (e);
509                         if (autosize) {
510                                 CalcAutoSize();
511                         } else {
512                                 CalcPreferredHeight ();
513                         }
514                         Refresh ();
515                 }
516
517                 protected override void OnPaint (PaintEventArgs pevent)
518                 {
519                         ThemeEngine.Current.DrawLabel (pevent.Graphics, ClientRectangle, this);
520                         DrawImage (pevent.Graphics, Image, ClientRectangle, image_align);
521                         base.OnPaint(pevent);
522                 }
523
524                 protected override void OnParentChanged (EventArgs e)
525                 {
526                         base.OnParentChanged (e);
527                 }
528
529                 protected virtual void OnTextAlignChanged (EventArgs e)
530                 {
531                         if (TextAlignChanged != null)
532                                 TextAlignChanged (this, e);
533                 }
534
535                 protected override void OnTextChanged (EventArgs e)
536                 {
537                         base.OnTextChanged (e);                 
538                         if (autosize) {
539                                 CalcAutoSize ();
540                         } else {
541                                 CalcPreferredWidth ();
542                         }
543                         Refresh ();
544                 }
545
546                 protected override void OnVisibleChanged (EventArgs e)
547                 {
548                         base.OnVisibleChanged (e);
549                 }
550
551                 protected override bool ProcessMnemonic (char charCode)
552                 {
553                         if (IsMnemonic(charCode, Text) == true) {
554                                 // Select item next in line in tab order
555                                 if (this.parent != null) {
556                                         parent.SelectNextControl(this, true, false, false, false);
557                                 }
558                                 return true;
559                         }
560                         
561                         return base.ProcessMnemonic (charCode);
562                 }
563
564                 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
565                 {
566                         base.SetBoundsCore (x, y, width, height, specified);
567                 }
568
569                 public override string ToString()
570                 {
571                         return base.ToString () + ", Text: " + Text;
572                 }
573
574                 protected override void WndProc (ref Message m)
575                 {
576                         switch ((Msg) m.Msg) {
577                                 case Msg.WM_DRAWITEM: {
578                                         m.Result = (IntPtr)1;
579                                 }
580                                         break;
581                                 default:
582                                         base.WndProc (ref m);
583                                         break;
584                         }
585                 }
586
587                 #endregion Public Methods
588
589                 #region Private Methods
590
591                 private void CalcAutoSize ()
592                 {
593                         if (IsHandleCreated == false || AutoSize == false)
594                                 return;
595
596                         CalcPreferredWidth ();
597                         CalcPreferredHeight ();
598
599                         Width =  PreferredWidth;
600                         Height =  PreferredHeight;                      
601                 }
602
603                 private void CalcPreferredHeight ()
604                 {
605                         preferred_height = Font.Height;
606
607                         switch (border_style) {
608                         case BorderStyle.None:
609                                 preferred_height += 3;
610                                 break;
611                         case BorderStyle.FixedSingle:
612                         case BorderStyle.Fixed3D:
613                                 preferred_height += 6;
614                                 break;
615                         default:
616                                 break;
617                         }
618
619                 }
620
621                 private void CalcPreferredWidth ()
622                 {
623                         SizeF size;
624                         size = DeviceContext.MeasureString (Text, Font, req_witdthsize, string_format);
625                         preferred_width = (int) size.Width + 3;
626                 }
627
628                 private void OnHandleCreatedLB (Object o, EventArgs e)
629                 {
630                         if (autosize)
631                                 CalcAutoSize ();
632                 }
633
634                 private void SetUseMnemonic (bool use)
635                 {
636                         if (use)
637                                 string_format.HotkeyPrefix = HotkeyPrefix.Show;
638                         else
639                                 string_format.HotkeyPrefix = HotkeyPrefix.None;
640                 }
641
642                 #endregion Private Methods
643 #if NET_2_0
644
645                 public bool UseCompatibleTextRendering {
646                         get {
647                                 return use_compatible_text_rendering;
648                         }
649
650                         set {
651                                 use_compatible_text_rendering = value;
652                         }
653                 }
654 #endif
655
656         }
657 }