Merge pull request #2223 from lobrien/master
[mono.git] / mcs / class / System.Windows.Forms / System.Windows.Forms / ProgressBar.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 Dennis Bartok     pbartok@novell.com
25 //
26 //
27
28 using System.Drawing;
29 using System.ComponentModel;
30 using System.Drawing.Imaging;
31 using System.Drawing.Drawing2D;
32 using System.Runtime.InteropServices;
33
34 namespace System.Windows.Forms
35 {
36         [DefaultProperty ("Value")]
37         [DefaultBindingProperty ("Value")]
38         [ClassInterface (ClassInterfaceType.AutoDispatch)]
39         [ComVisible (true)]
40         public class ProgressBar : Control
41         {
42                 #region Local Variables
43                 private int maximum;
44                 private int minimum;
45                 internal int step;
46                 internal int val;
47                 internal DateTime start = DateTime.Now;
48                 internal Rectangle client_area = new Rectangle ();
49                 internal ProgressBarStyle style;
50                 Timer marquee_timer;
51                 bool right_to_left_layout;
52                 private static readonly Color defaultForeColor = SystemColors.Highlight;
53                 #endregion      // Local Variables
54
55                 #region events
56                 static object RightToLeftLayoutChangedEvent = new object ();
57                 
58                 [Browsable (false)]
59                 [EditorBrowsable (EditorBrowsableState.Never)]
60                 public new event EventHandler BackgroundImageChanged {
61                         add { base.BackgroundImageChanged += value; }
62                         remove { base.BackgroundImageChanged -= value; }
63                 }
64                 
65                 [Browsable(false)]
66                 [EditorBrowsable(EditorBrowsableState.Never)]
67                 public new event EventHandler BackgroundImageLayoutChanged {
68                         add     { base.BackgroundImageLayoutChanged += value; }
69                         remove { base.BackgroundImageLayoutChanged -= value; }
70                 }
71                 
72                 [Browsable (false)]
73                 [EditorBrowsable (EditorBrowsableState.Never)]
74                 public new event EventHandler CausesValidationChanged {
75                         add { base.CausesValidationChanged += value; }
76                         remove { base.CausesValidationChanged -= value; }
77                 }
78                 
79                 [Browsable (false)]
80                 [EditorBrowsable (EditorBrowsableState.Never)]
81                 public new event EventHandler DoubleClick {
82                         add { base.DoubleClick += value; }
83                         remove { base.DoubleClick -= value; }
84                 }
85                 
86                 [Browsable (false)]
87                 [EditorBrowsable (EditorBrowsableState.Never)]
88                 public new event EventHandler Enter {
89                         add { base.Enter += value; }
90                         remove { base.Enter -= value; }
91                 }
92                 
93                 [Browsable (false)]
94                 [EditorBrowsable (EditorBrowsableState.Never)]
95                 public new event EventHandler FontChanged {
96                         add { base.FontChanged += value; }
97                         remove { base.FontChanged -= value; }
98                 }
99                 
100                 [Browsable (false)]
101                 [EditorBrowsable (EditorBrowsableState.Never)]
102                 public new event EventHandler ImeModeChanged {
103                         add { base.ImeModeChanged += value; }
104                         remove { base.ImeModeChanged -= value; }
105                 }
106                 
107                 [Browsable (false)]
108                 [EditorBrowsable (EditorBrowsableState.Never)]
109                 public new event KeyEventHandler KeyDown {
110                         add { base.KeyDown += value; }
111                         remove { base.KeyDown -= value; }
112                 }
113                 
114                 [Browsable (false)]
115                 [EditorBrowsable (EditorBrowsableState.Never)]
116                 public new event KeyPressEventHandler KeyPress {
117                         add { base.KeyPress += value; }
118                         remove { base.KeyPress -= value; }
119                 }
120                 
121                 [Browsable (false)]
122                 [EditorBrowsable (EditorBrowsableState.Never)]
123                 public new event KeyEventHandler KeyUp {
124                         add { base.KeyUp += value; }
125                         remove { base.KeyUp -= value; }
126                 }
127                 
128                 [Browsable (false)]
129                 [EditorBrowsable (EditorBrowsableState.Never)]
130                 public new event EventHandler Leave {
131                         add { base.Leave += value; }
132                         remove { base.Leave -= value; }
133                 }
134                 
135                 [EditorBrowsable(EditorBrowsableState.Never)]
136                 [Browsable(false)]
137                 public new event MouseEventHandler MouseDoubleClick {
138                         add { base.MouseDoubleClick += value; }
139                         remove { base.MouseDoubleClick -= value; }
140                 }
141                 
142                 [Browsable(false)]
143                 [EditorBrowsable(EditorBrowsableState.Never)]
144                 public new event EventHandler PaddingChanged {
145                         add { base.PaddingChanged += value; }
146                         remove { base.PaddingChanged -= value; }
147                 }
148                 
149                 [Browsable (false)]
150                 [EditorBrowsable (EditorBrowsableState.Never)]
151                 public new event PaintEventHandler Paint {
152                         add { base.Paint += value; }
153                         remove { base.Paint -= value; }
154                 }
155                 
156                 public event EventHandler RightToLeftLayoutChanged {
157                         add { Events.AddHandler (RightToLeftLayoutChangedEvent, value); }
158                         remove { Events.RemoveHandler (RightToLeftLayoutChangedEvent, value); }
159                 }
160                 
161                 [Browsable (false)]
162                 [EditorBrowsable (EditorBrowsableState.Never)]
163                 public new event EventHandler TabStopChanged {
164                         add { base.TabStopChanged += value; }
165                         remove { base.TabStopChanged -= value; }
166                 }
167                 
168                 [Browsable (false)]
169                 [EditorBrowsable (EditorBrowsableState.Never)]
170                 public new event EventHandler TextChanged {
171                         add { base.TextChanged += value; }
172                         remove { base.TextChanged -= value; }
173                 }
174                 #endregion Events
175
176                 #region Public Constructors
177                 public ProgressBar()
178                 {
179                         maximum = 100;
180                         minimum = 0;
181                         step = 10;
182                         val = 0;
183
184                         base.Resize += new EventHandler (OnResizeTB);
185
186                         SetStyle (ControlStyles.UserPaint | 
187                                 ControlStyles.Selectable | 
188                                 ControlStyles.ResizeRedraw | 
189                                 ControlStyles.Opaque |
190                                 ControlStyles.UseTextForAccessibility
191                                 , false);
192
193                         force_double_buffer = true;
194                         
195                         ForeColor = defaultForeColor;
196                 }
197                 #endregion      // Public Constructors
198
199                 #region Public Instance Properties
200
201                 [Browsable (false)]
202                 [EditorBrowsable (EditorBrowsableState.Never)]
203                 public override bool AllowDrop
204                 {
205                         get { return base.AllowDrop; }
206                         set {
207                                 base.AllowDrop = value;
208                         }
209                 }
210
211                 // Setting this property in MS .Net 1.1 does not have any visual effect and it
212                 // does not fire a BackgroundImageChanged event
213                 [Browsable (false)]
214                 [EditorBrowsable (EditorBrowsableState.Never)]
215                 public override Image BackgroundImage
216                 {
217                         get { return base.BackgroundImage; }
218                         set { base.BackgroundImage = value; }
219                 }
220
221                 [Browsable(false)]
222                 [EditorBrowsable(EditorBrowsableState.Never)]
223                 public override ImageLayout BackgroundImageLayout {
224                                 get     { return base.BackgroundImageLayout; }
225                                 set { base.BackgroundImageLayout = value; }
226                 }
227
228                 [Browsable (false)]
229                 [EditorBrowsable (EditorBrowsableState.Never)]
230                 public new bool CausesValidation
231                 {
232                         get { return base.CausesValidation; }
233                         set { base.CausesValidation = value; }
234                 }
235
236                 protected override CreateParams CreateParams
237                 {
238                         get { return base.CreateParams; }
239                 }
240
241                 protected override ImeMode DefaultImeMode
242                 {
243                         get { return base.DefaultImeMode; }
244                 }
245
246                 protected override Size DefaultSize
247                 {
248                         get { return ThemeEngine.Current.ProgressBarDefaultSize; }
249                 }
250
251                 [EditorBrowsable(EditorBrowsableState.Never)]
252                 protected override bool DoubleBuffered {
253                                 get { return base.DoubleBuffered; }
254                                 set { base.DoubleBuffered = value; }
255                 }
256
257                 // Setting this property in MS .Net 1.1 does not have any visual effect and it
258                 // does not fire a FontChanged event
259                 [Browsable (false)]
260                 [EditorBrowsable (EditorBrowsableState.Never)]
261                 public override Font Font
262                 {
263                         get { return base.Font; }
264                         set { base.Font = value; }
265                 }
266
267                 [Browsable (false)]
268                 [EditorBrowsable (EditorBrowsableState.Never)]
269                 public new ImeMode ImeMode
270                 {
271                         get { return base.ImeMode; }
272                         set { base.ImeMode = value; }
273                 }
274
275                 [RefreshProperties(RefreshProperties.Repaint)]
276                 [DefaultValue (100)]
277                 public int Maximum
278                 {
279                         get {
280                                 return maximum;
281                         }
282                         set {
283                                 if (value < 0)
284                                         throw new ArgumentOutOfRangeException ("Maximum", 
285                                                 string.Format("Value '{0}' must be greater than or equal to 0.", value ));
286
287                                 maximum = value;
288                                 minimum = Math.Min (minimum, maximum);
289                                 val = Math.Min (val, maximum);
290                                 Refresh ();
291                         }
292                 }
293
294                 [RefreshProperties(RefreshProperties.Repaint)]
295                 [DefaultValue (0)]
296                 public int Minimum {
297                         get {
298                                 return minimum;
299                         }
300                         set {
301                                 if (value < 0)
302                                         throw new ArgumentOutOfRangeException ("Minimum", 
303                                                 string.Format("Value '{0}' must be greater than or equal to 0.", value ));
304
305                                 minimum = value;
306                                 maximum = Math.Max (maximum, minimum);
307                                 val = Math.Max (val, minimum);
308                                 Refresh ();
309                         }
310                 }
311
312                 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
313                 [Browsable(false)]
314                 [EditorBrowsable(EditorBrowsableState.Never)]
315                 public new Padding Padding {
316                         get { return base.Padding; }
317                         set { base.Padding = value; }
318                 }
319                         
320                 [Localizable(true)]
321                 [DefaultValue(false)]
322                 [MonoTODO ("RTL is not supported")]
323                 public virtual bool RightToLeftLayout {
324                                 get { return right_to_left_layout;}
325                                 set     { 
326                                         if (right_to_left_layout != value) {
327                                                 right_to_left_layout = value;
328                                                 OnRightToLeftLayoutChanged (EventArgs.Empty);
329                                         }
330                                 }               
331                 }
332
333                 [DefaultValue (10)]
334                 public int Step
335                 {
336                         get { return step; }
337                         set {
338                                 step = value;
339                                 Refresh ();
340                         }
341                 }
342
343                 [Browsable (true)]
344                 [DefaultValue (ProgressBarStyle.Blocks)]
345                 [EditorBrowsable (EditorBrowsableState.Always)]
346                 public ProgressBarStyle Style {
347                         get {
348                                 return style;
349                         }
350
351                         set {
352                                 if (value != ProgressBarStyle.Blocks && value != ProgressBarStyle.Continuous
353                                                 && value != ProgressBarStyle.Marquee)
354                                         throw new InvalidEnumArgumentException ("value", unchecked((int)value), typeof (ProgressBarStyle));
355                                 if (style != value) {
356                                         style = value;
357
358                                         if (style == ProgressBarStyle.Marquee) {
359                                                 if (marquee_timer == null) {
360                                                         marquee_timer = new Timer ();
361                                                         marquee_timer.Interval = 10;
362                                                         marquee_timer.Tick += new EventHandler (marquee_timer_Tick);
363                                                 }
364                                                 marquee_timer.Start ();
365                                         } else {
366                                                 if (marquee_timer != null) {
367                                                         marquee_timer.Stop ();
368                                                 }
369                                                 Refresh ();
370                                         }
371                                 }
372                         }
373                 }
374
375                 void marquee_timer_Tick (object sender, EventArgs e)
376                 {
377                         Invalidate ();
378                 }
379                 
380                 int marquee_animation_speed = 100;
381                 [DefaultValue (100)]
382                 public int MarqueeAnimationSpeed {
383                         get {
384                                 return marquee_animation_speed;
385                         }
386
387                         set {
388                                 marquee_animation_speed = value;
389                         }
390                 }
391
392                 [Browsable (false)]
393                 [EditorBrowsable (EditorBrowsableState.Never)]
394                 public new bool TabStop
395                 {
396                         get { return base.TabStop; }
397                         set { base.TabStop = value; }
398                 }
399
400                 [Browsable (false)]
401                 [EditorBrowsable (EditorBrowsableState.Never)]
402                 [Bindable(false)]
403                 public override string Text
404                 {
405                         get { return base.Text; }
406                         set { base.Text = value; }
407                 }
408
409                 [Bindable(true)]
410                 [DefaultValue (0)]
411                 public int Value
412                 {
413                         get {
414                                 return val;
415                         }
416                         set {
417                                 if (value < Minimum || value > Maximum)
418                                         throw new ArgumentOutOfRangeException ("Value", string.Format("'{0}' is not a valid value for 'Value'. 'Value' should be between 'Minimum' and 'Maximum'", value));
419                                 val = value;
420                                 Refresh ();
421                         }
422                 }
423
424
425                 #endregion      // Protected Instance Properties
426
427                 #region Public Instance Methods
428                 
429                 protected override void CreateHandle ()
430                 {
431                         base.CreateHandle ();
432                 }
433
434                 public void Increment (int value)
435                 {
436                         if (Style == ProgressBarStyle.Marquee)
437                                 throw new InvalidOperationException ("Increment should not be called if the style is Marquee.");
438
439                         int newValue = Value + value;
440
441                         if (newValue < Minimum)
442                                 newValue = Minimum;
443
444                         if (newValue > Maximum)
445                                 newValue = Maximum;
446
447                         Value = newValue;
448                         Refresh ();
449                 }
450
451                 protected override void OnHandleCreated (EventArgs e)
452                 {
453                         base.OnHandleCreated (e);
454
455                         UpdateAreas ();
456                 }
457
458                 protected override void OnBackColorChanged (EventArgs e)
459                 {
460                         base.OnBackColorChanged (e);
461                 }
462                         
463                 protected override void OnForeColorChanged (EventArgs e)
464                 {
465                         base.OnForeColorChanged (e);
466                 }
467                         
468                 protected override void OnHandleDestroyed (EventArgs e)
469                 {
470                         base.OnHandleDestroyed (e);
471                 }
472                         
473                 [EditorBrowsable(EditorBrowsableState.Advanced)]
474                 protected virtual void OnRightToLeftLayoutChanged(EventArgs e)
475                 {
476                         EventHandler eh = (EventHandler) Events [RightToLeftLayoutChangedEvent];
477                         if (eh != null)
478                                 eh (this, e);
479                 }
480                         
481                 public void PerformStep ()
482                 {
483                         if (Style == ProgressBarStyle.Marquee)
484                                 throw new InvalidOperationException ("PerformStep should not be called if the style is Marquee.");
485
486                         Increment (Step);
487                 }
488
489                 [EditorBrowsable (EditorBrowsableState.Never)]
490                 public override void ResetForeColor ()
491                 {
492                         ForeColor = defaultForeColor;
493                 }
494
495                 public override string ToString()
496                 {
497                         return string.Format ("{0}, Minimum: {1}, Maximum: {2}, Value: {3}",
498                                 GetType().FullName,
499                                 Minimum.ToString (),
500                                 Maximum.ToString (),
501                                 Value.ToString () );
502                 }
503
504                 #endregion      // Public Instance Methods
505
506                 #region Private Instance Methods
507
508                 private void UpdateAreas ()
509                 {
510                         client_area.X = client_area.Y = 2;
511                         client_area.Width = Width - 4;
512                         client_area.Height = Height - 4;
513                 }
514
515                 private void OnResizeTB (Object o, EventArgs e)
516                 {
517                         if (Width <= 0 || Height <= 0)
518                                 return;
519
520                         UpdateAreas ();
521                         Invalidate();   // Invalidate the full surface, blocks will not match
522                 }
523
524                 internal override void OnPaintInternal (PaintEventArgs pevent)
525                 {
526                         ThemeEngine.Current.DrawProgressBar (pevent.Graphics, pevent.ClipRectangle, this);
527                 }
528
529                 #endregion
530         }
531 }