* ListView.cs: When doing layout calculations don't use a ref
[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-2006 Novell, Inc.
25 //
26 // Authors:
27 //      Jordi Mas i Hernandez, jordi@ximian.com
28 //      Rolf Bjarne Kvinge, RKvinge@novell.com
29 // 
30 // TODO:
31 //              - The AutoSize functionality seems quite broken for vertical controls in .Net 1.1. Not
32 //              sure if we are implementing it the right way.
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 using System.Runtime.InteropServices;
44
45 namespace System.Windows.Forms
46 {       
47 #if NET_2_0
48         [DefaultBindingProperty ("Value")]
49         [ComVisible (true)]
50         [ClassInterface (ClassInterfaceType.AutoDispatch)]
51 #endif
52         [Designer("System.Windows.Forms.Design.TrackBarDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
53         [DefaultEvent ("Scroll")]
54         [DefaultProperty("Value")]
55         public class TrackBar : Control, ISupportInitialize
56         {
57                 private int minimum;
58                 private int maximum;
59                 internal int tickFrequency;
60                 private bool autosize;
61                 private int position;
62                 private int smallChange;
63                 private int largeChange;
64                 private Orientation orientation;
65                 private TickStyle tickStyle;            
66                 private Rectangle thumb_pos = new Rectangle ();  /* Current position and size of the thumb */
67                 private Rectangle thumb_area = new Rectangle (); /* Area where the thumb can scroll */
68                 internal bool thumb_pressed = false;             
69                 private System.Timers.Timer holdclick_timer = new System.Timers.Timer ();
70                 internal int thumb_mouseclick;          
71                 private bool mouse_clickmove;
72                 private bool is_moving_right; // which way the thumb should move when mouse is down (right=up, left=down) 
73                 internal int mouse_down_x_offset; // how far from left side of thumb was the mouse clicked.
74                 internal bool mouse_moved; // has the mouse moved since it was clicked?
75                 private const int size_of_autosize = 45;
76 #if NET_2_0
77                 private bool right_to_left_layout;
78 #endif
79         
80                 #region events
81 #if NET_2_0
82                 [EditorBrowsable (EditorBrowsableState.Always)]
83                 [Browsable (true)]
84                 public new event EventHandler AutoSizeChanged {
85                         add {base.AutoSizeChanged += value;}
86                         remove {base.AutoSizeChanged -= value;}
87                 }
88 #endif
89
90                 [Browsable (false)]
91                 [EditorBrowsable (EditorBrowsableState.Never)]
92                 public new event EventHandler BackgroundImageChanged {
93                         add { base.BackgroundImageChanged += value; }
94                         remove { base.BackgroundImageChanged -= value; }
95                 }
96                 
97 #if NET_2_0
98                 [EditorBrowsable (EditorBrowsableState.Never)]
99                 [Browsable (false)]
100                 public new event EventHandler BackgroundImageLayoutChanged
101                 {
102                         add { base.BackgroundImageLayoutChanged += value; }
103                         remove { base.BackgroundImageLayoutChanged -= value; }
104                 }
105 #endif
106
107                 [Browsable (false)]
108                 [EditorBrowsable (EditorBrowsableState.Never)]
109                 public new event EventHandler Click {
110                         add { base.Click += value; }
111                         remove { base.Click -= value; }
112                 }
113                 
114                 [Browsable (false)]
115                 [EditorBrowsable (EditorBrowsableState.Never)]
116                 public new event EventHandler DoubleClick {
117                         add { base.DoubleClick += value; }
118                         remove { base.DoubleClick -= value; }
119                 }
120                 
121                 [Browsable (false)]
122                 [EditorBrowsable (EditorBrowsableState.Never)]
123                 public new event EventHandler FontChanged {
124                         add { base.FontChanged += value; }
125                         remove { base.FontChanged -= value; }
126                 }
127                 
128                 [Browsable (false)]
129                 [EditorBrowsable (EditorBrowsableState.Never)]
130                 public new event EventHandler ForeColorChanged {
131                         add { base.ForeColorChanged += value; }
132                         remove { base.ForeColorChanged -= value; }
133                 }
134                 
135                 [Browsable (false)]
136                 [EditorBrowsable (EditorBrowsableState.Never)]
137                 public new event EventHandler ImeModeChanged {
138                         add { base.ImeModeChanged += value; }
139                         remove { base.ImeModeChanged -= value; }
140                 }
141                 
142 #if NET_2_0
143                 [Browsable (false)]
144                 [EditorBrowsable (EditorBrowsableState.Never)]
145                 public new event MouseEventHandler MouseClick {
146                         add {base.MouseClick += value;}
147                         remove {base.MouseClick -= value;}
148                 }
149                 
150                 [Browsable (false)]
151                 [EditorBrowsable (EditorBrowsableState.Never)]
152                 public new event MouseEventHandler MouseDoubleClick
153                 {
154                         add { base.MouseDoubleClick += value; }
155                         remove { base.MouseDoubleClick -= value; }
156                 }
157                 
158                 [Browsable (false)]
159                 [EditorBrowsable (EditorBrowsableState.Never)]
160                 public new event EventHandler PaddingChanged
161                 {
162                         add { base.PaddingChanged += value; }
163                         remove { base.PaddingChanged -= value; }
164                 }
165                 
166 #endif
167                 
168                 [Browsable (false)]
169                 [EditorBrowsable (EditorBrowsableState.Never)]
170                 public new event PaintEventHandler Paint {
171                         add { base.Paint += value; }
172                         remove { base.Paint -= value; }
173                 }
174
175 #if NET_2_0
176                 public new event EventHandler RightToLeftLayoutChanged {
177                         add {Events.AddHandler (RightToLeftLayoutChangedEvent, value);}
178                         remove {Events.RemoveHandler (RightToLeftLayoutChangedEvent, value);}
179                 }
180 #endif
181
182                 [Browsable (false)]
183                 [EditorBrowsable (EditorBrowsableState.Never)]
184                 public new event EventHandler TextChanged {
185                         add { base.TextChanged += value; }
186                         remove { base.TextChanged -= value; }
187                 }
188
189 #if NET_2_0
190                 static object RightToLeftLayoutChangedEvent = new object ();
191 #endif
192                 static object ScrollEvent = new object ();
193                 static object ValueChangedEvent = new object ();
194
195                 public event EventHandler Scroll {
196                         add { Events.AddHandler (ScrollEvent, value); }
197                         remove { Events.RemoveHandler (ScrollEvent, value); }
198                 }
199
200                 public event EventHandler ValueChanged {
201                         add { Events.AddHandler (ValueChangedEvent, value); }
202                         remove { Events.RemoveHandler (ValueChangedEvent, value); }
203                 }
204                 
205                 #endregion // Events
206
207                 public TrackBar ()
208                 {
209                         orientation = Orientation.Horizontal;
210                         minimum = 0;
211                         maximum = 10;
212                         tickFrequency = 1;
213                         autosize = true;
214                         position = 0;
215                         tickStyle = TickStyle.BottomRight;
216                         smallChange = 1;
217                         largeChange = 5;                        
218                         mouse_clickmove = false;                        
219                         MouseDown += new MouseEventHandler (OnMouseDownTB); 
220                         MouseUp += new MouseEventHandler (OnMouseUpTB); 
221                         MouseMove += new MouseEventHandler (OnMouseMoveTB);
222                         KeyDown += new KeyEventHandler (OnKeyDownTB);
223                         LostFocus += new EventHandler (OnLostFocusTB);
224                         GotFocus += new EventHandler (OnGotFocusTB);
225                         holdclick_timer.Elapsed += new ElapsedEventHandler (OnFirstClickTimer);
226
227                         SetStyle (ControlStyles.UserPaint | ControlStyles.Opaque
228 #if NET_2_0
229                                 | ControlStyles.UseTextForAccessibility
230 #endif
231                                 , false);
232                 }
233
234                 #region Private & Internal Properties
235                 internal Rectangle ThumbPos {
236                         get {
237                                 return thumb_pos;
238                         }
239
240                         set {
241                                 thumb_pos = value;
242                         }
243                 }
244
245                 internal Rectangle ThumbArea {
246                         get {
247                                 return thumb_area;
248                         }
249
250                         set {
251                                 thumb_area = value;
252                         }
253                 }
254                 #endregion      // Private & Internal Properties
255
256                 #region Public Properties
257
258 #if NET_2_0
259                 [Browsable (true)]
260                 [EditorBrowsable (EditorBrowsableState.Always)]
261                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Visible)]
262 #endif
263                 [DefaultValue (true)]
264 #if NET_2_0
265                 public override bool AutoSize {
266 #else
267                 public new bool AutoSize {
268 #endif
269                         get { return autosize; }
270                         set { autosize = value;}
271                 }
272
273                 [EditorBrowsable (EditorBrowsableState.Never)]
274                 [Browsable (false)]
275                 public override Image BackgroundImage {
276                         get { return base.BackgroundImage; }
277                         set { base.BackgroundImage = value; }
278                 }
279
280 #if NET_2_0
281                 [EditorBrowsable (EditorBrowsableState.Never)]
282                 [Browsable (false)]
283                 public override ImageLayout BackgroundImageLayout {
284                         get {
285                                 return base.BackgroundImageLayout;
286                         }
287                         set {
288                                 base.BackgroundImageLayout = value;
289                         }
290                 }
291 #endif
292
293                 protected override CreateParams CreateParams {
294                         get {
295                                 return base.CreateParams;
296                         }
297                 }
298
299                 protected override ImeMode DefaultImeMode {
300                         get {return ImeMode.Disable; }
301                 }
302
303                 protected override Size DefaultSize {
304                         get { return ThemeEngine.Current.TrackBarDefaultSize; }
305                 }       
306                 
307 #if NET_2_0
308                 [EditorBrowsable (EditorBrowsableState.Never)]
309                 protected override bool DoubleBuffered {
310                         get {
311                                 return base.DoubleBuffered;
312                         }
313                         set {
314                                 base.DoubleBuffered = value;
315                         }
316                 }
317 #endif
318
319                 [Browsable(false)]
320                 [EditorBrowsable (EditorBrowsableState.Never)]
321                 public override Font Font {
322                         get { return base.Font; }
323                         set { base.Font = value; }
324                 }
325
326                 [EditorBrowsable (EditorBrowsableState.Never)]  
327                 [Browsable (false)]
328                 public override Color ForeColor {
329                         get { return base.ForeColor; }
330                         set { base.ForeColor = value; }
331                 }               
332
333                 [EditorBrowsable (EditorBrowsableState.Never)]  
334                 [Browsable (false)]
335                 public new ImeMode ImeMode {
336                         get { return base.ImeMode; }
337                         set { base.ImeMode = value; }
338                 }
339                 
340                 [DefaultValue (5)]
341                 public int LargeChange 
342                 {
343                         get { return largeChange; }
344                         set {
345 #if NET_2_0
346                                 if (value < 0)
347                                         throw new ArgumentOutOfRangeException (string.Format ("Value '{0}' must be greater than or equal to 0.", value));
348 #else
349                                 if ( value < 0 )
350                                         throw new ArgumentException( string.Format("Value '{0}' must be greater than or equal to 0.", value));
351 #endif
352                                 
353                                 largeChange = value;                            
354                         }
355                 }
356
357                 [DefaultValue (10)]
358                 [RefreshProperties (RefreshProperties.All)]             
359                 public int Maximum {
360                         get { return maximum; }
361                         set {
362                                 if (maximum != value)  {
363                                         maximum = value;
364
365                                         if (maximum < minimum)
366                                                 minimum = maximum;
367
368                                         Refresh ();
369                                 }
370                         }
371                 }
372
373                 [DefaultValue (0)]
374                 [RefreshProperties (RefreshProperties.All)]             
375                 public int Minimum {
376                         get { return minimum; }
377                         set {
378
379                                 if (Minimum != value) {
380                                         minimum = value;
381
382                                         if (minimum > maximum)
383                                                 maximum = minimum;
384
385                                         Refresh ();
386                                 }
387                         }
388                 }
389
390                 [DefaultValue (Orientation.Horizontal)]
391                 [Localizable (true)]
392                 public Orientation Orientation {
393                         get { return orientation; }
394                         set {
395                                 if (!Enum.IsDefined (typeof (Orientation), value))
396                                         throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for Orientation", value));
397
398                                 /* Orientation can be changed once the control has been created */
399                                 if (orientation != value) {
400                                         orientation = value;
401                                         
402                                         if (this.IsHandleCreated) {
403                                                 Size = new Size (Height, Width);
404                                                 Refresh (); 
405                                         }
406                                 }
407                         }
408                 }
409
410 #if NET_2_0
411                 [Browsable (false)]
412                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
413                 [EditorBrowsable (EditorBrowsableState.Never)]
414                 public new Padding Padding {
415                         get {
416                                 return base.Padding;
417                         }
418                         set {
419                                 base.Padding = value;
420                         }
421                 }
422                 
423                 [Localizable (true)]
424                 [DefaultValue (false)]
425                 public virtual bool RightToLeftLayout {
426                         get {
427                                 return right_to_left_layout;
428                         }
429                         set {
430                                 if (value != right_to_left_layout) {
431                                         right_to_left_layout = value;
432                                         OnRightToLeftLayoutChanged (EventArgs.Empty);
433                                 }
434                         }
435                 }
436 #endif
437
438                 [DefaultValue (1)]
439                 public int SmallChange {
440                         get { return smallChange;}
441                         set {
442 #if NET_2_0
443                                 if (value < 0)
444                                         throw new ArgumentOutOfRangeException (string.Format ("Value '{0}' must be greater than or equal to 0.", value));
445 #else
446                                 if ( value < 0 )
447                                         throw new ArgumentException( string.Format("Value '{0}' must be greater than or equal to 0.", value));
448 #endif
449                                 if (smallChange != value) {
450                                         smallChange = value;                                    
451                                 }
452                         }
453                 }
454
455                 [EditorBrowsable (EditorBrowsableState.Never)]
456                 [Bindable (false)]
457                 [Browsable (false)]
458                 public override string Text {
459                         get {   return base.Text; }                     
460                         set { base.Text = value; }
461                 }
462
463                 [DefaultValue (1)]
464                 public int TickFrequency {
465                         get { return tickFrequency; }
466                         set {
467                                 if ( value > 0 ) {
468                                         tickFrequency = value;
469                                         Refresh ();
470                                 }
471                         }
472                 }
473
474                 [DefaultValue (TickStyle.BottomRight)]
475                 public TickStyle TickStyle {
476                         get { return tickStyle; }
477                         set {                           
478                                 if (!Enum.IsDefined (typeof (TickStyle), value))
479                                         throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for TickStyle", value));
480                                 
481                                 if (tickStyle != value) {
482                                         tickStyle = value;
483                                         Refresh ();
484                                 }
485                         }
486                 }
487                 
488                 [DefaultValue (0)]
489                 [Bindable (true)]
490                 public int Value {
491                         get { return position; }
492                         set {
493                                 if (value < Minimum || value > Maximum)
494                                         throw new ArgumentException(
495                                                 string.Format("'{0}' is not a valid value for 'Value'. 'Value' should be between 'Minimum' and 'Maximum'", value));
496                                 
497                                 if (position != value) {                                                                                                        
498                                         position = value;                                       
499
500                                         // XXX any reason we don't call OnValueChanged here?
501                                         EventHandler eh = (EventHandler)(Events [ValueChangedEvent]);
502                                         if (eh != null)
503                                                 eh (this, EventArgs.Empty);
504
505                                         Invalidate (thumb_area);
506                                 }                               
507                         }
508                 }
509
510                 #endregion //Public Properties
511
512                 #region Public Methods
513
514                 public void BeginInit ()                
515                 {
516
517                 }
518
519                 protected override void CreateHandle ()
520                 {
521                         base.CreateHandle ();
522                 }
523
524                 protected override void SetBoundsCore (int x, int y,int width, int height, BoundsSpecified specified)
525                 {
526                         if (AutoSize) {
527                                 if (orientation == Orientation.Vertical) {
528                                         width = size_of_autosize;
529                                 } else {
530                                         height = size_of_autosize;
531                                 }
532                         }
533                         base.SetBoundsCore (x, y, width, height, specified);
534                 }
535
536                 public void EndInit ()          
537                 {
538
539                 }
540
541                 protected override bool IsInputKey (Keys keyData)
542                 {
543                         if ((keyData & Keys.Alt) == 0) {
544                                 switch (keyData & Keys.KeyCode) {
545                                 case Keys.Down:
546                                 case Keys.Right:
547                                 case Keys.Up:
548                                 case Keys.Left:
549                                 case Keys.PageUp:
550                                 case Keys.PageDown:
551                                 case Keys.Home:
552                                 case Keys.End:
553                                         return true;
554                                 }
555                         }
556                         return base.IsInputKey (keyData);
557                 }
558
559                 protected override void OnBackColorChanged (EventArgs e)
560                 {
561                         base.OnBackColorChanged (e);
562                 }
563
564                 protected override void OnHandleCreated (EventArgs e)
565                 {       
566                         base.OnHandleCreated (e);
567                                         
568                         if (AutoSize)
569                                 if (Orientation == Orientation.Horizontal)
570                                         Size = new Size (Width, 40);
571                                 else
572                                         Size = new Size (50, Height);
573                         
574                         UpdatePos (Value, true);                        
575                 }
576         
577                 [EditorBrowsable (EditorBrowsableState.Advanced)]
578                 protected override void OnMouseWheel (MouseEventArgs e)
579                 {
580                         base.OnMouseWheel (e);
581                         
582                         if (!Enabled) return;
583                         
584                         if (e.Delta > 0)
585                                 SmallDecrement ();
586                         else
587                                 SmallIncrement ();                                      
588                 }
589
590 #if NET_2_0
591                 [EditorBrowsable (EditorBrowsableState.Advanced)]
592                 protected virtual void OnRightToLeftLayoutChanged (EventArgs e)
593                 {
594                         EventHandler eh = (EventHandler)Events [RightToLeftLayoutChangedEvent];
595                         if (eh != null)
596                                 eh (this, e);
597                 }
598 #endif
599
600                 protected virtual void OnScroll (EventArgs e) 
601                 {
602                         EventHandler eh = (EventHandler)(Events [ScrollEvent]);
603                         if (eh != null)
604                                 eh (this, e);
605                 }
606
607 #if NET_2_0
608                 protected override void OnSystemColorsChanged (EventArgs e)
609                 {
610                         base.OnSystemColorsChanged (e);
611                         Invalidate ();
612                 }
613 #endif
614                 protected virtual void OnValueChanged (EventArgs e) 
615                 {
616                         EventHandler eh = (EventHandler)(Events [ValueChangedEvent]);
617                         if (eh != null)
618                                 eh (this, e);
619                 }
620
621                 public void SetRange (int minValue, int maxValue)
622                 {
623                         Minimum = minValue;
624                         Maximum = maxValue;                     
625                 }
626
627                 public override string ToString()
628                 {
629                         return string.Format("System.Windows.Forms.TrackBar, Minimum: {0}, Maximum: {1}, Value: {2}",
630                                                 Minimum, Maximum, Value);
631                 }
632                                                         
633
634                 protected override void WndProc (ref Message m)
635                 {
636                         base.WndProc (ref m);
637                 }
638                 
639                 #endregion Public Methods
640
641                 #region Private Methods
642                 
643                 private void UpdatePos (int newPos, bool update_trumbpos)
644                 {
645                         if (newPos < minimum){
646                                 Value = minimum;
647                         }
648                         else {
649                                 if (newPos > maximum) {
650                                         Value = maximum;
651                                 }
652                                 else {
653                                         Value = newPos;
654                                 }
655                         }
656                 }
657                 
658                 private void LargeIncrement ()
659                 {                       
660                         UpdatePos (position + LargeChange, true);
661                         Invalidate (thumb_area);
662                         OnScroll (new EventArgs ());
663                 }
664
665                 private void LargeDecrement ()
666                 {
667                         UpdatePos (position - LargeChange, true);
668                         Invalidate (thumb_area);
669                         OnScroll (new EventArgs ());
670                 }
671
672                 private void SmallIncrement ()
673                 {                       
674                         UpdatePos (position + SmallChange, true);
675                         Invalidate (thumb_area);
676                         OnScroll (new EventArgs ());
677                 }
678
679                 private void SmallDecrement ()
680                 {
681                         UpdatePos (position - SmallChange, true);
682                         Invalidate (thumb_area);
683                         OnScroll (new EventArgs ());    
684                 }
685                 
686                 private void OnMouseUpTB (object sender, MouseEventArgs e)
687                 {       
688                         if (!Enabled) return;                   
689
690                         if (thumb_pressed == true || mouse_clickmove == true) { 
691                                 thumb_pressed = false;
692                                 holdclick_timer.Enabled = false;
693                                 this.Capture = false;
694                                 Invalidate (thumb_area);
695                         }
696                 }
697
698                 private void OnMouseDownTB (object sender, MouseEventArgs e)
699                 {
700                         if (!Enabled) return;                                           
701
702                         mouse_moved = false;
703
704                         bool fire_timer = false;
705                         
706                         Point point = new Point (e.X, e.Y);
707
708                         if (orientation == Orientation.Horizontal) {
709                                 
710                                 if (thumb_pos.Contains (point)) {
711                                         this.Capture = true;
712                                         thumb_pressed = true;
713                                         thumb_mouseclick = e.X;
714                                         mouse_down_x_offset = e.X - thumb_pos.X;
715                                         Invalidate (thumb_area);
716                                 }
717                                 else {
718                                         if (ClientRectangle.Contains (point)) {
719                                                 is_moving_right = e.X > thumb_pos.X + thumb_pos.Width; 
720                                                 if (is_moving_right)
721                                                         LargeIncrement ();
722                                                 else
723                                                         LargeDecrement ();
724
725                                                 Invalidate (thumb_area);
726                                                 fire_timer = true;
727                                                 mouse_clickmove = true;
728                                         }
729                                 }
730                         }
731                         else {
732                                 Rectangle vertical_thumb_pos = thumb_pos;
733                                 vertical_thumb_pos.Width = thumb_pos.Height;
734                                 vertical_thumb_pos.Height = thumb_pos.Width;
735                                 if (vertical_thumb_pos.Contains (point)) {
736                                         this.Capture = true;
737                                         thumb_pressed = true;
738                                         thumb_mouseclick = e.Y;
739                                         mouse_down_x_offset = e.Y - thumb_pos.Y;
740                                         Invalidate (thumb_area);
741                                 }
742                                 else {
743                                         if (ClientRectangle.Contains (point)) {
744                                                 is_moving_right = e.Y > thumb_pos.Y + thumb_pos.Width;
745                                                 if (is_moving_right)
746                                                         LargeDecrement ();
747                                                 else
748                                                         LargeIncrement ();
749
750                                                 Invalidate (thumb_area);
751                                                 fire_timer = true;
752                                                 mouse_clickmove = true;
753                                         }
754                                 }
755                         }
756
757                         if (fire_timer) {                               
758                                 holdclick_timer.Interval = 300;
759                                 holdclick_timer.Enabled = true;                         
760                         }                       
761                 }
762
763                 private void OnMouseMoveTB (object sender, MouseEventArgs e)
764                 {                       
765                         if (!Enabled) return;
766                 
767                         mouse_moved = true;
768
769                         /* Moving the thumb */
770                         if (thumb_pressed) {
771                                 Value = ThemeEngine.Current.TrackBarValueFromMousePosition (e.X, e.Y, this);                    
772                                 OnScroll (new EventArgs ());
773                         }
774                 }
775
776                 internal override void OnPaintInternal (PaintEventArgs pevent)
777                 {               
778                         ThemeEngine.Current.DrawTrackBar (pevent.Graphics, pevent.ClipRectangle, this);
779                 }
780
781                 private void OnLostFocusTB (object sender, EventArgs e)
782                 {
783                         Invalidate();
784                 }
785
786                 private void OnGotFocusTB (object sender, EventArgs e)
787                 {
788                         Invalidate();
789                 }
790                 private void OnKeyDownTB (object sender, KeyEventArgs e) 
791                 {
792                         switch (e.KeyCode) {
793                         
794                         case Keys.Down:
795                         case Keys.Right:
796                                 SmallDecrement ();
797                                 break;
798
799                         case Keys.Up:
800                         case Keys.Left:
801                                 SmallIncrement ();
802                                 break;
803
804                         case Keys.PageUp:
805                                 LargeIncrement ();
806                                 break;
807
808                         case Keys.PageDown:
809                                 LargeDecrement ();
810                                 break;
811
812                         case Keys.Home:
813                                 Value = Maximum;
814                                 break;
815
816                         case Keys.End:
817                                 Value = Minimum;
818                                 break;
819
820                         default:
821                                 break;
822                         }
823                 }
824
825                 private void OnFirstClickTimer (Object source, ElapsedEventArgs e)
826                 {                                               
827                         Point pnt;
828                         pnt = PointToClient (MousePosition);                    
829                         /*
830                                 On Win32 the thumb only moves in one direction after a click, 
831                                 if the thumb passes the clicked point it will never go in the 
832                                 other way unless the mouse is released and clicked again. This
833                                 is also true if the mouse moves while beeing hold down.
834                         */
835                 
836                         if (thumb_area.Contains (pnt))  {
837                                 bool invalidate = false;
838                                 if (orientation == Orientation.Horizontal) {
839                                         if (pnt.X > thumb_pos.X + thumb_pos.Width && is_moving_right) {
840                                                 LargeIncrement ();
841                                                 invalidate = true;
842                                         } else if (pnt.X < thumb_pos.X && !is_moving_right) {
843                                                 LargeDecrement ();                      
844                                                 invalidate = true;
845                                         }                                       
846                                 } else {
847                                         if (pnt.Y > thumb_pos.Y + thumb_pos.Width && is_moving_right) {
848                                                 LargeDecrement ();              
849                                                 invalidate = true;
850                                         } else if (pnt.Y < thumb_pos.Y && !is_moving_right) {
851                                                 LargeIncrement ();              
852                                                 invalidate = true;
853                                         }
854                                 }
855                                 if (invalidate)
856                                         // A Refresh is necessary because the mouse is down and if we just invalidate
857                                         // we'll only get paint events once in a while.
858                                         Refresh();
859                         }                       
860                 }                                       
861                 #endregion // Private Methods
862         }
863 }
864