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