2007-06-04 Jonathan Pobst <monkey@jpobst.com>
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / PictureBox.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 //      Jackson Harper (jackson@ximian.com)
24 //
25
26 // COMPLETE
27
28 using System;
29 using System.ComponentModel;
30 using System.ComponentModel.Design;
31 using System.Drawing;
32 using System.Drawing.Imaging;
33 using System.Runtime.InteropServices;
34
35 namespace System.Windows.Forms {
36         [DefaultProperty("Image")]
37         [Designer("System.Windows.Forms.Design.PictureBoxDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
38 #if NET_2_0
39         [Docking (DockingBehavior.Ask)]
40         [ClassInterface (ClassInterfaceType.AutoDispatch)]
41         [ComVisible (true)]
42         [DefaultBindingProperty ("Image")]
43 #endif
44         public class PictureBox : Control 
45 #if NET_2_0
46                                         , ISupportInitialize
47 #endif
48         {
49                 #region Fields
50                 private Image   image;
51                 private PictureBoxSizeMode size_mode;
52                 //private bool  recalc;
53 #if NET_2_0
54                 private Image   initial_image;
55 #endif
56                 private int     no_update;
57                 #endregion      // Fields
58
59                 private EventHandler frame_handler;
60
61                 #region Public Constructor
62                 public PictureBox ()
63                 {
64                         //recalc = true;
65 #if NET_2_0
66                         SetStyle (ControlStyles.OptimizedDoubleBuffer, true);
67 #else
68                         SetStyle (ControlStyles.DoubleBuffer, true);
69 #endif
70                         SetStyle (ControlStyles.Opaque, false);
71                         SetStyle (ControlStyles.Selectable, false);
72                         SetStyle (ControlStyles.SupportsTransparentBackColor, true);
73                         HandleCreated += new EventHandler(PictureBox_HandleCreated);
74                 }
75                 #endregion      // Public Constructor
76
77                 #region Public Properties
78                 [DefaultValue(PictureBoxSizeMode.Normal)]
79                 [Localizable(true)]
80                 [RefreshProperties(RefreshProperties.Repaint)]
81                 public PictureBoxSizeMode SizeMode {
82                         get { return size_mode; }
83                         set {
84                                 if (size_mode == value)
85                                         return;
86                                 size_mode = value;
87                                 UpdateSize ();
88                                 if (no_update == 0) {
89                                         Redraw (true);
90                                         Invalidate ();
91                                 }
92
93                                 OnSizeModeChanged (EventArgs.Empty);
94                         }
95                 }
96
97 #if NET_2_0
98                 [Bindable (true)]
99 #else
100                 [DefaultValue(null)]
101 #endif
102                 [Localizable(true)]
103                 public Image Image {
104                         get { return image; }
105                         set {
106                                 StopAnimation ();
107
108                                 image = value;
109
110                                 if (IsHandleCreated) {
111                                         UpdateSize ();
112                                         if (image != null && ImageAnimator.CanAnimate (image)) {
113                                                 frame_handler = new EventHandler (OnAnimateImage);
114                                                 ImageAnimator.Animate (image, frame_handler);
115                                         }
116                                         if (no_update == 0) {
117                                                 Redraw (true);
118                                                 Invalidate ();
119                                         }
120                                 }
121                         }
122                 }
123
124                 [DefaultValue(BorderStyle.None)]
125                 [DispId(-504)]
126                 public BorderStyle BorderStyle {
127                         get { return InternalBorderStyle; }
128                         set { InternalBorderStyle = value; }
129                 }
130
131                 [Browsable(false)]
132                 [EditorBrowsable(EditorBrowsableState.Never)]
133                 public new bool CausesValidation {
134                         get { return base.CausesValidation; }
135                         set { base.CausesValidation = value; }
136                 }
137
138 #if NET_2_0
139                 [RefreshProperties (RefreshProperties.All)]
140                 [Localizable(true)]
141                 public Image InitialImage {
142                         get { return initial_image; }
143                         set { initial_image = value; }
144                 }
145 #endif
146
147                 [Browsable(false)]
148                 [EditorBrowsable(EditorBrowsableState.Never)]
149                 public new ImeMode ImeMode {
150                         get { return base.ImeMode; }
151                         set { base.ImeMode = value; }
152                 }
153
154                 [Browsable(false)]
155                 [EditorBrowsable(EditorBrowsableState.Never)]
156                 public override RightToLeft RightToLeft {
157                         get { return base.RightToLeft; }
158                         set { base.RightToLeft = value; }
159                 }
160
161                 [Browsable(false)]
162                 [EditorBrowsable(EditorBrowsableState.Never)]
163                 public new int TabIndex {
164                         get { return base.TabIndex; }
165                         set { base.TabIndex = value; }
166                 }
167
168                 [Browsable(false)]
169                 [EditorBrowsable(EditorBrowsableState.Never)]
170                 public new bool TabStop {
171                         get { return base.TabStop; }
172                         set { base.TabStop = value; }
173                 }
174
175                 [Bindable(false)]
176                 [Browsable(false)]
177                 [EditorBrowsable(EditorBrowsableState.Never)]
178                 public override string Text {
179                         get { return base.Text; }
180                         set { base.Text = value; }
181                 }
182
183                 protected override CreateParams CreateParams {
184                         get {
185                                 return base.CreateParams;
186                         }
187                 }
188
189                 protected override ImeMode DefaultImeMode {
190                         get { return base.DefaultImeMode; }
191                 }
192
193                 [Browsable(false)]
194                 [EditorBrowsable(EditorBrowsableState.Never)]
195                 public override Font Font {
196                         get { return base.Font; }
197                         set { base.Font = value; }
198                 }
199
200                 [Browsable(false)]
201                 [EditorBrowsable(EditorBrowsableState.Never)]
202                 public override Color ForeColor {
203                         get { return base.ForeColor; }
204                         set { base.ForeColor = value; }
205                 }
206
207                 [Browsable(false)]
208                 [EditorBrowsable(EditorBrowsableState.Never)]
209                 public override bool AllowDrop {
210                         get { return base.AllowDrop; }
211                         set { base.AllowDrop = value; }
212                 }
213                 #endregion      // Public Properties
214
215                 #region Protected Instance Methods
216                 protected override Size DefaultSize {
217                         get { return ThemeEngine.Current.PictureBoxDefaultSize; }
218                 }
219
220                 protected override void Dispose (bool disposing)
221                 {
222                         if (image != null) {
223                                 StopAnimation ();
224                                 image = null;
225                         }
226 #if NET_2_0
227                         initial_image = null;
228 #endif
229
230                         base.Dispose (disposing);
231                 }
232
233                 protected override void OnPaint (PaintEventArgs pe)
234                 {
235                         ThemeEngine.Current.DrawPictureBox (pe.Graphics, pe.ClipRectangle, this);
236                         base.OnPaint (pe);
237                 }
238
239                 protected override void OnVisibleChanged (EventArgs e)
240                 {
241                         base.OnVisibleChanged (e);
242                         Redraw (true);
243                 }
244
245                 protected virtual void OnSizeModeChanged (EventArgs e)
246                 {
247                         EventHandler eh = (EventHandler)(Events [SizeModeChangedEvent]);
248                         if (eh != null)
249                                 eh (this, e);
250                 }
251
252                 protected override void OnEnabledChanged (EventArgs e)
253                 {
254                         base.OnEnabledChanged (e);
255                 }
256
257                 protected override void OnParentChanged (EventArgs e)
258                 {
259                         base.OnParentChanged (e);
260                 }
261
262                 protected override void OnResize (EventArgs e)
263                 {
264                         base.OnResize (e);
265
266                         if (size_mode == PictureBoxSizeMode.CenterImage || size_mode == PictureBoxSizeMode.StretchImage)
267                                 Refresh ();
268 #if NET_2_0
269                         if (size_mode == PictureBoxSizeMode.Zoom)
270                                 Refresh ();
271 #endif
272                 }
273
274                 protected override void SetBoundsCore (int x, int y, int width, int height, BoundsSpecified specified)
275                 {
276                         if (size_mode == PictureBoxSizeMode.AutoSize && image != null) {
277                                 width = image.Width;
278                                 height = image.Height;
279                         }
280                         base.SetBoundsCore (x, y, width, height, specified);
281                 }
282                 #endregion      // Protected Instance Methods
283
284 #if NET_2_0
285                 #region ISupportInitialize Interface
286                 void System.ComponentModel.ISupportInitialize.BeginInit() {
287                         no_update++;
288                 }
289
290                 void System.ComponentModel.ISupportInitialize.EndInit() {
291                         if (no_update > 0) {
292                                 no_update--;
293                         }
294                         if (no_update == 0) {
295                                 Redraw (true);
296                                 Invalidate ();
297                         }
298                 }
299                 #endregion      // ISupportInitialize Interface
300 #endif
301
302                 #region Private Methods
303                 private void StopAnimation ()
304                 {
305                         if (frame_handler == null)
306                                 return;
307                         ImageAnimator.StopAnimate (image, frame_handler);
308                         frame_handler = null;
309                 }
310
311                 private void UpdateSize ()
312                 {
313                         if (image == null)
314                                 return;
315                         if (size_mode == PictureBoxSizeMode.AutoSize)
316                                 ClientSize = image.Size; 
317                 }
318
319                 private void Redraw (bool recalc)
320                 {
321                         //this.recalc = recalc;
322                 }
323
324                 private void OnAnimateImage (object sender, EventArgs e)
325                 {
326                         // This is called from a worker thread,BeginInvoke is used
327                         // so the control is updated from the correct thread
328                         BeginInvoke (new EventHandler (UpdateAnimatedImage), new object [] { this, e });
329                 }
330
331                 private void UpdateAnimatedImage (object sender, EventArgs e)
332                 {
333                         ImageAnimator.UpdateFrames (image);
334                         Redraw (false);
335                         Refresh ();
336                 }
337
338                 private void PictureBox_HandleCreated(object sender, EventArgs e) {
339                         UpdateSize ();
340                         if (image != null && ImageAnimator.CanAnimate (image)) {
341                                 frame_handler = new EventHandler (OnAnimateImage);
342                                 ImageAnimator.Animate (image, frame_handler);
343                         }
344                         if (no_update == 0) {
345                                 Redraw (true);
346                                 Invalidate ();
347                         }
348                 }
349                 #endregion      // Private Methods
350
351                 #region Public Instance Methods
352                 public override string ToString() {
353                         return String.Format("{0}, SizeMode: {1}", base.ToString (), SizeMode);
354                 }
355                 #endregion
356
357                 #region Events
358                 [Browsable(false)]
359                 [EditorBrowsable(EditorBrowsableState.Never)]
360                 public new event EventHandler CausesValidationChanged {
361                         add { base.CausesValidationChanged += value; }
362                         remove { base.CausesValidationChanged -= value; }
363                 }
364
365                 [Browsable(false)]
366                 [EditorBrowsable(EditorBrowsableState.Never)]
367                 public new event EventHandler Enter {
368                         add { base.Enter += value; }
369                         remove { base.Enter -= value; }
370                 }
371
372                 [Browsable(false)]
373                 [EditorBrowsable(EditorBrowsableState.Never)]
374                 public new event EventHandler FontChanged {
375                         add { base.FontChanged += value; }
376                         remove { base.FontChanged -= value; }
377                 }
378
379                 [Browsable(false)]
380                 [EditorBrowsable(EditorBrowsableState.Never)]
381                 public new event EventHandler ForeColorChanged {
382                         add { base.ForeColorChanged += value; }
383                         remove { base.ForeColorChanged -= value; }
384                 }
385
386                 [Browsable(false)]
387                 [EditorBrowsable(EditorBrowsableState.Never)]
388                 public new event EventHandler ImeModeChanged {
389                         add { base.ImeModeChanged += value; }
390                         remove { base.ImeModeChanged -= value; }
391                 }
392
393                 [Browsable(false)]
394                 [EditorBrowsable(EditorBrowsableState.Never)]
395                 public new event KeyEventHandler KeyDown {
396                         add { base.KeyDown += value; }
397                         remove { base.KeyDown -= value; }
398                 }
399
400                 [Browsable(false)]
401                 [EditorBrowsable(EditorBrowsableState.Never)]
402                 public new event KeyPressEventHandler KeyPress {
403                         add { base.KeyPress += value; }
404                         remove { base.KeyPress -= value; }
405                 }
406
407                 [Browsable(false)]
408                 [EditorBrowsable(EditorBrowsableState.Never)]
409                 public new event KeyEventHandler KeyUp {
410                         add { base.KeyUp += value; }
411                         remove { base.KeyUp -= value; }
412                 }
413
414                 [Browsable(false)]
415                 [EditorBrowsable(EditorBrowsableState.Never)]
416                 public new event EventHandler Leave {
417                         add { base.Leave += value; }
418                         remove { base.Leave -= value; }
419                 }
420
421                 [Browsable(false)]
422                 [EditorBrowsable(EditorBrowsableState.Never)]
423                 public new event EventHandler RightToLeftChanged {
424                         add { base.RightToLeftChanged += value; }
425                         remove { base.RightToLeftChanged -= value; }
426                 }
427
428                 [Browsable(false)]
429                 [EditorBrowsable(EditorBrowsableState.Never)]
430                 public new event EventHandler TabIndexChanged {
431                         add { base.TabIndexChanged += value; }
432                         remove { base.TabIndexChanged -= value; }
433                 }
434
435                 [Browsable(false)]
436                 [EditorBrowsable(EditorBrowsableState.Never)]
437                 public new event EventHandler TabStopChanged {
438                         add { base.TabStopChanged += value; }
439                         remove { base.TabStopChanged -= value; }
440                 }
441
442                 [Browsable(false)]
443                 [EditorBrowsable(EditorBrowsableState.Never)]
444                 public new event EventHandler TextChanged {
445                         add { base.TextChanged += value; }
446                         remove { base.TextChanged -= value; }
447                 }
448
449                 static object SizeModeChangedEvent = new object ();
450                 public event EventHandler SizeModeChanged {
451                         add { Events.AddHandler (SizeModeChangedEvent, value); }
452                         remove { Events.RemoveHandler (SizeModeChangedEvent, value); }
453                 }
454
455                 #endregion      // Events
456         }
457 }
458