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