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