* ImageList.cs: When the image stream is set pull all the images
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / TrackBar.cs
1 //
2 // System.Windows.Forms.TrackBar.cs
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the
6 // "Software"), to deal in the Software without restriction, including
7 // without limitation the rights to use, copy, modify, merge, publish,
8 // distribute, sublicense, and/or sell copies of the Software, and to
9 // permit persons to whom the Software is furnished to do so, subject to
10 // the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
14 //
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 //
23 //
24 // Copyright (c) 2004-2005 Novell, Inc.
25 //
26 // Authors:
27 //      Jordi Mas i Hernandez, jordi@ximian.com
28 //
29 // TODO:
30 //              - The AutoSize functionality seems quite broken for vertical controls in .Net 1.1. Not
31 //              sure if we are implementing it the right way.
32 //
33
34
35 // NOT COMPLETE
36
37 using System.ComponentModel;
38 using System.ComponentModel.Design;
39 using System.Drawing;
40 using System.Drawing.Imaging;
41 using System.Drawing.Drawing2D;
42 using System.Timers;
43
44 namespace System.Windows.Forms
45 {       
46         [Designer("System.Windows.Forms.Design.TrackBarDesigner, " + Consts.AssemblySystem_Design)]
47         [DefaultEvent ("Scroll")]
48         [DefaultProperty("Value")]
49         public class TrackBar : Control, ISupportInitialize
50         {
51                 private int minimum;
52                 private int maximum;
53                 internal int tickFrequency;
54                 private bool autosize;
55                 private int position;
56                 private int smallChange;
57                 private int largeChange;
58                 private Orientation orientation;
59                 private TickStyle tickStyle;            
60                 private Rectangle thumb_pos = new Rectangle ();  /* Current position and size of the thumb */
61                 private Rectangle thumb_area = new Rectangle (); /* Area where the thumb can scroll */
62                 internal bool thumb_pressed = false;             
63                 private System.Timers.Timer holdclick_timer = new System.Timers.Timer ();
64                 internal int thumb_mouseclick;          
65                 private bool mouse_clickmove;
66
67                 #region events
68                 [Browsable (false)]
69                 [EditorBrowsable (EditorBrowsableState.Never)]
70                 public new event EventHandler BackgroundImageChanged;
71                 
72                 [Browsable (false)]
73                 [EditorBrowsable (EditorBrowsableState.Never)]
74                 public new event EventHandler Click;
75                 
76                 [Browsable (false)]
77                 [EditorBrowsable (EditorBrowsableState.Never)]
78                 public new event EventHandler DoubleClick;
79                 
80                 [Browsable (false)]
81                 [EditorBrowsable (EditorBrowsableState.Never)]
82                 public new event EventHandler FontChanged;
83                 
84                 [Browsable (false)]
85                 [EditorBrowsable (EditorBrowsableState.Never)]
86                 public new event EventHandler ForeColorChanged;
87                 
88                 [Browsable (false)]
89                 [EditorBrowsable (EditorBrowsableState.Never)]
90                 public new event EventHandler ImeModeChanged;
91                 
92                 [Browsable (false)]
93                 [EditorBrowsable (EditorBrowsableState.Never)]
94                 public new event PaintEventHandler Paint;
95                 
96                 public event EventHandler Scroll;
97                 
98                 [Browsable (false)]
99                 [EditorBrowsable (EditorBrowsableState.Never)]
100                 public new event EventHandler TextChanged;
101                 public event EventHandler ValueChanged;
102                 
103                 #endregion // Events
104
105                 public TrackBar ()
106                 {
107                         orientation = Orientation.Horizontal;
108                         minimum = 0;
109                         maximum = 10;
110                         tickFrequency = 1;
111                         autosize = true;
112                         position = 0;
113                         tickStyle = TickStyle.BottomRight;
114                         smallChange = 1;
115                         largeChange = 5;                        
116                         mouse_clickmove = false;                        
117                         MouseDown += new MouseEventHandler (OnMouseDownTB); 
118                         MouseUp += new MouseEventHandler (OnMouseUpTB); 
119                         MouseMove += new MouseEventHandler (OnMouseMoveTB);
120                         holdclick_timer.Elapsed += new ElapsedEventHandler (OnFirstClickTimer);
121
122                         SetStyle (ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
123                         SetStyle (ControlStyles.ResizeRedraw | ControlStyles.Opaque, true);                     
124                 }
125
126                 #region Private & Internal Properties
127                 internal Rectangle ThumbPos {
128                         get {
129                                 return thumb_pos;
130                         }
131
132                         set {
133                                 thumb_pos = value;
134                         }
135                 }
136
137                 internal Rectangle ThumbArea {
138                         get {
139                                 return thumb_area;
140                         }
141
142                         set {
143                                 thumb_area = value;
144                         }
145                 }
146                 #endregion      // Private & Internal Properties
147
148                 #region Public Properties
149
150                 [DefaultValue (true)]
151                 public bool AutoSize {
152                         get { return autosize; }
153                         set { autosize = value;}
154                 }
155
156                 [EditorBrowsable (EditorBrowsableState.Never)]
157                 [Browsable (false)]
158                 public override Image BackgroundImage {
159                         get { return base.BackgroundImage; }
160                         set { 
161                                 if (base.BackgroundImage == value)
162                                         return;
163
164                                 if (BackgroundImageChanged != null)
165                                         BackgroundImageChanged (this, EventArgs.Empty);
166
167                                 base.BackgroundImage = value; 
168                         }
169                 }
170
171                 protected override CreateParams CreateParams {
172                         get {
173                                 CreateParams createParams = base.CreateParams;
174                                 createParams.ClassName = XplatUI.DefaultClassName;
175
176                                 createParams.Style = (int) (
177                                         WindowStyles.WS_CHILD |
178                                         WindowStyles.WS_VISIBLE);
179
180                                 return createParams;
181                         }
182                 }
183
184                 protected override ImeMode DefaultImeMode {
185                         get {return ImeMode.Disable; }
186                 }
187
188                 protected override Size DefaultSize {
189                         get { return ThemeEngine.Current.TrackBarDefaultSize; }
190                 }       
191                 
192                 [Browsable(false)]
193                 [EditorBrowsable (EditorBrowsableState.Never)]
194                 public override Font Font {
195                         get { return base.Font; }
196                         set { base.Font = value; }
197                 }
198
199                 [EditorBrowsable (EditorBrowsableState.Never)]  
200                 [Browsable (false)]
201                 public override Color ForeColor {
202                         get { return base.ForeColor; }
203                         set {
204                                 if (value == base.ForeColor)
205                                         return;
206
207                                 if (ForeColorChanged != null)
208                                         ForeColorChanged (this, EventArgs.Empty);
209
210                                 Refresh ();
211                         }
212                 }               
213
214                 [EditorBrowsable (EditorBrowsableState.Never)]  
215                 [Browsable (false)]
216                 public new ImeMode ImeMode {
217                         get { return base.ImeMode; }
218                         set {
219                                 if (value == base.ImeMode)
220                                         return;
221
222                                 base.ImeMode = value;
223                                 if (ImeModeChanged != null)
224                                         ImeModeChanged (this, EventArgs.Empty);
225                         }
226                 }
227                 
228                 [DefaultValue (5)]
229                 public int LargeChange \r
230                 {
231                         get { return largeChange; }
232                         set {
233                                 if (value < 0)
234                                         throw new Exception( string.Format("Value '{0}' must be greater than or equal to 0.", value));
235
236                                 largeChange = value;                            
237                         }
238                 }
239
240                 [DefaultValue (10)]
241                 [RefreshProperties (RefreshProperties.All)]             
242                 public int Maximum {
243                         get { return maximum; }
244                         set {
245                                 if (maximum != value)  {
246                                         maximum = value;
247
248                                         if (maximum < minimum)
249                                                 minimum = maximum;
250
251                                         Refresh ();
252                                 }
253                         }
254                 }
255
256                 [DefaultValue (0)]
257                 [RefreshProperties (RefreshProperties.All)]             
258                 public int Minimum {
259                         get { return minimum; }
260                         set {
261
262                                 if (Minimum != value) {
263                                         minimum = value;
264
265                                         if (minimum > maximum)
266                                                 maximum = minimum;
267
268                                         Refresh ();
269                                 }
270                         }
271                 }
272
273                 [DefaultValue (Orientation.Horizontal)]
274                 [Localizable (true)]
275                 public Orientation Orientation {
276                         get { return orientation; }
277                         set {
278                                 if (!Enum.IsDefined (typeof (Orientation), value))
279                                         throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for Orientation", value));
280
281                                 /* Orientation can be changed once the control has been created */
282                                 if (orientation != value) {
283                                         orientation = value;
284                                 
285                                         int old_witdh = Width;
286                                         Width = Height;
287                                         Height = old_witdh;
288                                         Refresh (); 
289                                 }
290                         }
291                 }
292
293                 [DefaultValue (1)]
294                 public int SmallChange {
295                         get { return smallChange;}
296                         set {
297                                 if ( value < 0 )
298                                         throw new Exception( string.Format("Value '{0}' must be greater than or equal to 0.", value));
299
300                                 if (smallChange != value) {
301                                         smallChange = value;                                    
302                                 }
303                         }
304                 }
305
306                 [EditorBrowsable (EditorBrowsableState.Never)]
307                 [Bindable (false)]
308                 [Browsable (false)]
309                 public override string Text {
310                         get {   return base.Text; }                     
311                         set {
312                                 if (value == base.Text)
313                                         return;
314
315                                 if (TextChanged != null)
316                                         TextChanged (this, EventArgs.Empty);
317
318                                 Refresh ();
319                         }
320                 }
321
322                 [DefaultValue (1)]
323                 public int TickFrequency {
324                         get { return tickFrequency; }
325                         set {
326                                 if ( value > 0 ) {
327                                         tickFrequency = value;
328                                         Refresh ();
329                                 }
330                         }
331                 }
332
333                 [DefaultValue (TickStyle.BottomRight)]
334                 public TickStyle TickStyle {
335                         get { return tickStyle; }
336                         set {                           
337                                 if (!Enum.IsDefined (typeof (TickStyle), value))
338                                         throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for TickStyle", value));
339                                 
340                                 if (tickStyle != value) {
341                                         tickStyle = value;
342                                         Refresh ();
343                                 }
344                         }
345                 }
346                 
347                 [DefaultValue (0)]
348                 [Bindable (true)]
349                 public int Value {
350                         get { return position; }
351                         set {
352                                 if (value < Minimum || value > Maximum)
353                                         throw new ArgumentException(
354                                                 string.Format("'{0}' is not a valid value for 'Value'. 'Value' should be between 'Minimum' and 'Maximum'", value));
355                                 
356                                 if (position != value) {                                                                                                        
357                                         position = value;                                       
358                                         
359                                         if (ValueChanged != null)                               
360                                                 ValueChanged (this, new EventArgs ());
361                                                 
362                                         Invalidate (thumb_area);
363                                 }                               
364                         }
365                 }
366
367                 #endregion //Public Properties
368
369                 #region Public Methods
370
371                 public virtual void BeginInit ()                
372                 {
373
374                 }
375
376                 protected override void CreateHandle ()
377                 {
378                         base.CreateHandle ();
379                 }
380
381
382                 public virtual void EndInit ()          
383                 {
384
385                 }
386
387                 protected override bool IsInputKey (Keys keyData)
388                 {
389                         return base.IsInputKey (keyData);
390                 }
391
392                 protected override void OnBackColorChanged (EventArgs e)
393                 {
394                         base.OnBackColorChanged (e);
395                 }
396
397                 protected override void OnHandleCreated (EventArgs e)
398                 {       
399                         base.OnHandleCreated (e);
400                                         
401                         if (AutoSize)
402                                 if (Orientation == Orientation.Horizontal)
403                                         Size = new Size (Width, 40);
404                                 else
405                                         Size = new Size (50, Height);
406                         
407                         UpdatePos (Value, true);                        
408                 }
409         
410                 [EditorBrowsable (EditorBrowsableState.Advanced)]
411                 protected override void OnMouseWheel (MouseEventArgs e)
412                 {
413                         if (!Enabled) return;
414                         
415                         if (e.Delta > 0)
416                                 SmallDecrement ();
417                         else
418                                 SmallIncrement ();
419
420                         base.OnMouseWheel (e);
421                                         
422                 }
423
424                 protected virtual void OnScroll (EventArgs e) 
425                 {
426                         if (Scroll != null) 
427                                 Scroll (this, e);
428                 }
429
430                 protected virtual void OnValueChanged (EventArgs e) 
431                 {
432                         if (ValueChanged != null) 
433                                 ValueChanged (this, e);
434                 }
435
436                 public void SetRange (int minValue, int maxValue)
437                 {
438                         Minimum = minValue;
439                         Maximum = maxValue;                     
440                 }
441
442                 public override string ToString()
443                 {
444                         return string.Format("System.Windows.Forms.Trackbar, Minimum: {0}, Maximum: {1}, Value: {2}",
445                                                 Minimum, Maximum, Value);
446                 }
447                                                         
448
449                 protected override void WndProc (ref Message m)
450                 {
451                         switch ((Msg) m.Msg) {
452         
453                         case Msg.WM_PAINT: {                            
454                                 PaintEventArgs  paint_event;
455
456                                 paint_event = XplatUI.PaintEventStart (Handle);
457                                 OnPaintTB (paint_event);
458                                 XplatUI.PaintEventEnd (Handle);
459                                 return;
460                         }               
461
462                         case Msg.WM_KEYDOWN: 
463                                 OnKeyDownTB (new KeyEventArgs ((Keys)m.WParam.ToInt32 ()));
464                                 return;                 
465                                 
466                         case Msg.WM_ERASEBKGND:
467                                 m.Result = (IntPtr) 1; /* Disable background painting to avoid flickering */
468                                 return;
469                                 
470                         default:
471                                 break;
472                         }
473
474                         base.WndProc (ref m);
475                 }
476                 
477                 #endregion Public Methods
478
479                 #region Private Methods
480                 
481                 private void UpdatePos (int newPos, bool update_trumbpos)
482                 {
483                         if (newPos < minimum){
484                                 Value = minimum;
485                         }
486                         else {
487                                 if (newPos > maximum) {
488                                         Value = maximum;
489                                 }
490                                 else {
491                                         Value = newPos;
492                                 }
493                         }
494                 }
495                 
496                 private void LargeIncrement ()
497                 {                       
498                         UpdatePos (position + LargeChange, true);
499                         Invalidate (thumb_area);
500                         OnScroll (new EventArgs ());
501                 }
502
503                 private void LargeDecrement ()
504                 {
505                         UpdatePos (position - LargeChange, true);
506                         Invalidate (thumb_area);
507                         OnScroll (new EventArgs ());
508                 }
509
510                 private void SmallIncrement ()
511                 {                       
512                         UpdatePos (position + SmallChange, true);
513                         Invalidate (thumb_area);
514                         OnScroll (new EventArgs ());
515                 }
516
517                 private void SmallDecrement ()
518                 {
519                         UpdatePos (position - SmallChange, true);
520                         Invalidate (thumb_area);
521                         OnScroll (new EventArgs ());    
522                 }
523                 
524                 private void Draw (Rectangle clip)
525                 {                                       
526                         ThemeEngine.Current.DrawTrackBar (DeviceContext, clip, this);                   
527                 }               
528
529                 private void OnMouseUpTB (object sender, MouseEventArgs e)
530                 {       
531                         if (!Enabled) return;                   
532
533                         if (thumb_pressed == true || mouse_clickmove == true) { 
534                                 thumb_pressed = false;
535                                 holdclick_timer.Enabled = false;
536                                 this.Capture = false;
537                                 Invalidate (thumb_area);
538                         }
539                 }
540
541                 private void OnMouseDownTB (object sender, MouseEventArgs e)
542                 {
543                         if (!Enabled) return;                                           
544
545                         bool fire_timer = false;
546                         
547                         Point point = new Point (e.X, e.Y);
548
549                         if (orientation == Orientation.Horizontal) {
550                                 
551                                 if (thumb_pos.Contains (point)) {
552                                         this.Capture = true;
553                                         thumb_pressed = true;
554                                         thumb_mouseclick = e.X;
555                                         Invalidate (thumb_area);
556                                 }
557                                 else {
558                                         if (ClientRectangle.Contains (point)) {
559                                                 if (e.X > thumb_pos.X + thumb_pos.Width)
560                                                         LargeIncrement ();
561                                                 else
562                                                         LargeDecrement ();
563
564                                                 Invalidate (thumb_area);
565                                                 fire_timer = true;
566                                                 mouse_clickmove = true;
567                                         }
568                                 }
569                         }
570                         else {
571                                 if (thumb_pos.Contains (point)) {
572                                         this.Capture = true;
573                                         thumb_pressed = true;
574                                         thumb_mouseclick = e.Y;
575                                         Invalidate (thumb_area);
576                                         
577                                 }
578                                 else {
579                                         if (ClientRectangle.Contains (point)) {
580                                                 if (e.Y > thumb_pos.Y + thumb_pos.Height)
581                                                         LargeIncrement ();
582                                                 else
583                                                         LargeDecrement ();
584
585                                                 Invalidate (thumb_area);
586                                                 fire_timer = true;
587                                                 mouse_clickmove = true;
588                                         }
589                                 }
590                         }
591
592                         if (fire_timer) {                               \r
593                                 holdclick_timer.Interval = 300;\r
594                                 holdclick_timer.Enabled = true;                         
595                         }                       
596                 }
597
598                 private void OnMouseMoveTB (object sender, MouseEventArgs e)
599                 {                       
600                         if (!Enabled) return;
601                 
602                         /* Moving the thumb */
603                         if (thumb_pressed) {
604                                                                                                 
605                                 if (orientation == Orientation.Horizontal){
606                                         if (ClientRectangle.Contains (e.X, thumb_pos.Y))
607                                                 thumb_mouseclick = e.X; 
608                                 }
609                                 else {
610                                         if (ClientRectangle.Contains (thumb_pos.X, e.Y))
611                                                 thumb_mouseclick = e.Y;
612                                 }
613
614                                 Invalidate (thumb_area);
615                                 OnScroll (new EventArgs ());
616                         }
617                 }
618
619                 
620                 private void OnPaintTB (PaintEventArgs pevent)
621                 {               
622                         if (Paint != null) {
623                                 Paint (this, pevent);
624                         }
625                         
626                         if (Width <= 0 || Height <=  0 || Visible == false)
627                                 return;         
628
629                         /* Copies memory drawing buffer to screen */
630                         Draw (pevent.ClipRectangle);
631                         pevent.Graphics.DrawImage (ImageBuffer, pevent.ClipRectangle, pevent.ClipRectangle, GraphicsUnit.Pixel);
632                 }  
633
634                 private void OnKeyDownTB (KeyEventArgs e) \r
635                 {                       
636                         switch (e.KeyCode) {                    \r
637                         
638                         case Keys.Down:
639                         case Keys.Right:
640                                 SmallIncrement ();
641                                 break;
642                         
643                         case Keys.Up:
644                         case Keys.Left:
645                                 SmallDecrement ();
646                                 break;
647                                 
648                         case Keys.PageUp:
649                                 LargeDecrement ();
650                                 break;
651                                 
652                         case Keys.PageDown:
653                                 LargeIncrement ();
654                                 break;
655                                 
656                         case Keys.Home:
657                                 Value = Minimum;
658                                 break;
659                         
660                         case Keys.End:
661                                 Value = Maximum;
662                                 break;
663                         
664                         default:
665                                 break;
666                         }
667                 }
668
669                 private void OnFirstClickTimer (Object source, ElapsedEventArgs e)\r
670                 {                                               \r
671                         Point pnt;\r
672                         pnt = PointToClient (MousePosition);                    \r
673 \r
674                         if (thumb_area.Contains (pnt))  {\r
675                                 if (orientation == Orientation.Horizontal) {\r
676                                         if (pnt.X > thumb_pos.X + thumb_pos.Width)
677                                                 LargeIncrement ();
678
679                                         if (pnt.X < thumb_pos.X)
680                                                 LargeDecrement ();                                              \r
681                                 }\r
682                                 else                            {\r
683                                         if (pnt.Y > thumb_pos.Y + thumb_pos.Height)
684                                                 LargeIncrement ();
685
686                                         if (pnt.Y < thumb_pos.Y)
687                                                 LargeDecrement ();
688                                 }
689
690                                 Invalidate (thumb_area);
691 \r
692                         }                       \r
693                 }                                       
694
695                 protected override void SetBoundsCore (int x, int y,int width, int height, BoundsSpecified specified)
696                 {
697                         base.SetBoundsCore (x, y,width, height, specified);
698                 }
699
700                 
701                 #endregion // Private Methods
702         }
703 }
704