2 // System.Windows.Forms.ScrollBar.cs
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:
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
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.
23 // Copyright (C) 2004-2005, Novell, Inc.
26 // Jordi Mas i Hernandez jordi@ximian.com
33 using System.Drawing.Imaging;
34 using System.Drawing.Drawing2D;
35 using System.ComponentModel;
36 using System.Runtime.InteropServices;
38 namespace System.Windows.Forms
40 [DefaultEvent ("Scroll")]
41 [DefaultProperty ("Value")]
42 public abstract class ScrollBar : Control
44 #region Local Variables
48 private int large_change;
49 private int small_change;
50 internal int scrollbutton_height;
51 internal int scrollbutton_width;
52 private ScrollBars type;
53 private Rectangle first_arrow_area = new Rectangle (); // up or left
54 private Rectangle second_arrow_area = new Rectangle (); // down or right
55 private Rectangle thumb_pos = new Rectangle ();
56 private Rectangle thumb_area = new Rectangle ();
57 internal ButtonState firstbutton_state = ButtonState.Normal;
58 internal ButtonState secondbutton_state = ButtonState.Normal;
59 private bool firstbutton_pressed = false;
60 private bool secondbutton_pressed = false;
61 private bool thumb_pressed = false;
62 private float pixel_per_pos = 0;
63 private Timer timer = new Timer ();
64 private TimerType timer_type;
65 private int thumb_pixel_click_move;
66 private int thumb_pixel_click_move_prev;
67 private int thumb_size = 40;
68 private const int thumb_min_size = 8;
69 private const int thumb_notshown_size = 40;
71 private int lastclick_pos; // Position of the last button-down event
72 private int lastclick_pos_thumb; // Position of the last button-down event relative to the thumb
73 private bool outside_thumbarea_right = false;
74 private bool outside_thumbarea_left = false;
76 private Rectangle dirty;
78 internal ThumbMoving thumb_moving = ThumbMoving.None;
79 #endregion // Local Variables
81 private enum TimerType
89 internal enum ThumbMoving
99 [EditorBrowsable (EditorBrowsableState.Never)]
100 public new event EventHandler BackColorChanged;
103 [EditorBrowsable (EditorBrowsableState.Never)]
104 public new event EventHandler BackgroundImageChanged;
107 [EditorBrowsable (EditorBrowsableState.Never)]
108 public new event EventHandler Click;
111 [EditorBrowsable (EditorBrowsableState.Never)]
112 public new event EventHandler DoubleClick;
115 [EditorBrowsable (EditorBrowsableState.Never)]
116 public new event EventHandler FontChanged;
119 [EditorBrowsable (EditorBrowsableState.Never)]
120 public new event EventHandler ForeColorChanged;
123 [EditorBrowsable (EditorBrowsableState.Never)]
124 public new event EventHandler ImeModeChanged;
127 [EditorBrowsable (EditorBrowsableState.Never)]
128 public new event MouseEventHandler MouseDown;
131 [EditorBrowsable (EditorBrowsableState.Never)]
132 public new event MouseEventHandler MouseMove;
135 [EditorBrowsable (EditorBrowsableState.Never)]
136 public new event MouseEventHandler MouseUp;
139 [EditorBrowsable (EditorBrowsableState.Never)]
140 public new event PaintEventHandler Paint;
142 public event ScrollEventHandler Scroll;
145 [EditorBrowsable (EditorBrowsableState.Never)]
146 public new event EventHandler TextChanged;
148 public event EventHandler ValueChanged;
159 timer.Tick += new EventHandler (OnTimer);
160 base.KeyDown += new KeyEventHandler (OnKeyDownSB);
161 base.MouseDown += new MouseEventHandler (OnMouseDownSB);
162 base.MouseUp += new MouseEventHandler (OnMouseUpSB);
163 base.MouseMove += new MouseEventHandler (OnMouseMoveSB);
164 base.Resize += new EventHandler (OnResizeSB);
165 base.TabStop = false;
167 SetStyle (ControlStyles.UserPaint | ControlStyles.StandardClick, false);
170 #region Internal & Private Properties
171 internal Rectangle FirstArrowArea {
173 return this.first_arrow_area;
177 this.first_arrow_area = value;
181 internal Rectangle SecondArrowArea {
183 return this.second_arrow_area;
187 this.second_arrow_area = value;
191 internal Rectangle ThumbPos {
200 #endregion // Internal & Private Properties
202 #region Public Properties
204 [EditorBrowsable (EditorBrowsableState.Never)]
206 public override Color BackColor
208 get { return base.BackColor; }
210 if (base.BackColor == value)
213 if (BackColorChanged != null)
214 BackColorChanged (this, EventArgs.Empty);
216 base.BackColor = value;
221 [EditorBrowsable (EditorBrowsableState.Never)]
223 public override Image BackgroundImage
225 get { return base.BackgroundImage; }
227 if (base.BackgroundImage == value)
230 if (BackgroundImageChanged != null)
231 BackgroundImageChanged (this, EventArgs.Empty);
233 base.BackgroundImage = value;
237 protected override CreateParams CreateParams
239 get { return base.CreateParams; }
242 protected override ImeMode DefaultImeMode
244 get { return ImeMode.Disable; }
247 [EditorBrowsable (EditorBrowsableState.Never)]
249 public override Font Font
251 get { return base.Font; }
253 if (base.Font.Equals (value))
256 if (FontChanged != null)
257 FontChanged (this, EventArgs.Empty);
263 [EditorBrowsable (EditorBrowsableState.Never)]
265 public override Color ForeColor
267 get { return base.ForeColor; }
269 if (base.ForeColor == value)
272 if (ForeColorChanged != null)
273 ForeColorChanged (this, EventArgs.Empty);
275 base.ForeColor = value;
280 [EditorBrowsable (EditorBrowsableState.Never)]
282 public new ImeMode ImeMode
284 get { return base.ImeMode; }
286 if (base.ImeMode == value)
289 if (ImeModeChanged != null)
290 ImeModeChanged (this, EventArgs.Empty);
292 base.ImeMode = value;
297 [RefreshProperties(RefreshProperties.Repaint)]
298 [MWFDescription("Scroll amount when clicking in the scroll area"), MWFCategory("Behaviour")]
299 public int LargeChange {
301 if (large_change > maximum)
302 return (maximum + 1);
308 throw new Exception( string.Format("Value '{0}' must be greater than or equal to 0.", value));
310 if (large_change != value) {
311 large_change = value;
313 // thumb area depends on large change value,
314 // so we need to recalculate it.
316 UpdatePos (Value, true);
323 [RefreshProperties(RefreshProperties.Repaint)]
324 [MWFDescription("Highest value for scrollbar"), MWFCategory("Behaviour")]
326 get { return maximum; }
328 if (maximum == value)
333 if (maximum < minimum)
336 // thumb area depends on maximum value,
337 // so we need to recalculate it.
339 UpdatePos (Value, true);
345 [RefreshProperties(RefreshProperties.Repaint)]
346 [MWFDescription("Smallest value for scrollbar"), MWFCategory("Behaviour")]
348 get { return minimum; }
350 if (minimum == value)
355 if (minimum > maximum)
358 // thumb area depends on minimum value,
359 // so we need to recalculate it.
361 UpdatePos (Value, true);
367 [MWFDescription("Scroll amount when clicking scroll arrows"), MWFCategory("Behaviour")]
368 public int SmallChange {
369 get { return small_change; }
372 throw new Exception( string.Format("Value '{0}' must be greater than or equal to 0.", value));
374 if (small_change != value) {
375 small_change = value;
376 UpdatePos (Value, true);
382 [DefaultValue (false)]
383 public new bool TabStop {
384 get { return base.TabStop; }
385 set { base.TabStop = value; }
388 [EditorBrowsable (EditorBrowsableState.Never)]
391 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
392 public override string Text {
393 get { return base.Text; }
394 set { base.Text = value; }
399 [MWFDescription("Current value for scrollbar"), MWFCategory("Behaviour")]
401 get { return position; }
403 if ( value < minimum || value > maximum )
404 throw new ArgumentException(
405 string.Format("'{0}' is not a valid value for 'Value'. 'Value' should be between 'Minimum' and 'Maximum'", value));
407 if (position != value){
410 OnValueChanged (EventArgs.Empty);
414 if (IsHandleCreated) {
415 UpdateThumbPos (thumb_area.Y + (int)(((float)(position - minimum)) * pixel_per_pos), false);
423 #endregion //Public Properties
425 #region Public Methods
427 protected override void OnEnabledChanged (EventArgs e)
429 base.OnEnabledChanged (e);
432 firstbutton_state = secondbutton_state = ButtonState.Normal;
434 firstbutton_state = secondbutton_state = ButtonState.Inactive;
439 protected override void OnHandleCreated (System.EventArgs e)
441 base.OnHandleCreated (e);
445 UpdateThumbPos (thumb_area.Y + (int)(((float)(position - minimum)) * pixel_per_pos), false);
448 protected virtual void OnScroll (ScrollEventArgs event_args)
453 if (event_args.NewValue < Minimum) {
454 event_args.NewValue = Minimum;
457 if (event_args.NewValue > Maximum) {
458 event_args.NewValue = Maximum;
461 Scroll (this, event_args);
464 protected virtual void OnValueChanged (EventArgs e)
466 if (ValueChanged != null)
467 ValueChanged (this, e);
470 public override string ToString()
472 return string.Format("{0}, Minimum: {1}, Maximum: {2}, Value: {3}",
473 GetType( ).FullName.ToString( ), minimum, maximum, position);
476 protected void UpdateScrollInfo ()
481 protected override void WndProc (ref Message m)
487 PaintEventArgs paint_event;
489 paint_event = XplatUI.PaintEventStart (Handle, true);
490 OnPaintSB (paint_event);
491 XplatUI.PaintEventEnd (Handle, true);
495 case Msg.WM_ERASEBKGND:
496 m.Result = (IntPtr) 1; /// Disable background painting to avoid flickering
503 base.WndProc (ref m);
506 #endregion //Public Methods
508 #region Private Methods
510 private void CalcButtonSizes ()
513 if (Height < ThemeEngine.Current.ScrollBarButtonSize * 2)
514 scrollbutton_height = Height /2;
516 scrollbutton_height = ThemeEngine.Current.ScrollBarButtonSize;
519 if (Width < ThemeEngine.Current.ScrollBarButtonSize * 2)
520 scrollbutton_width = Width /2;
522 scrollbutton_width = ThemeEngine.Current.ScrollBarButtonSize;
526 private void CalcThumbArea ()
531 thumb_area.Height = Height - scrollbutton_height - scrollbutton_height;
533 thumb_area.Y = scrollbutton_height;
534 thumb_area.Width = Width;
536 if (Height < thumb_notshown_size)
539 double per = ((double) this.LargeChange / (double)((1 + maximum - minimum)));
540 thumb_size = 1 + (int) (thumb_area.Height * per);
542 if (thumb_size < thumb_min_size)
543 thumb_size = thumb_min_size;
546 pixel_per_pos = ((float)(thumb_area.Height - thumb_size) / (float) ((maximum - minimum - this.LargeChange) + 1));
551 thumb_area.X = scrollbutton_width;
552 thumb_area.Height = Height;
553 thumb_area.Width = Width - scrollbutton_width - scrollbutton_width;
555 if (Width < thumb_notshown_size)
558 double per = ((double) this.LargeChange / (double)((1 + maximum - minimum)));
559 thumb_size = 1 + (int) (thumb_area.Width * per);
561 if (thumb_size < thumb_min_size)
562 thumb_size = thumb_min_size;
565 pixel_per_pos = ((float)(thumb_area.Width - thumb_size) / (float) ((maximum - minimum - this.LargeChange) + 1));
569 private void LargeIncrement ()
571 ScrollEventArgs event_args;
572 int pos = position + large_change;
574 event_args = new ScrollEventArgs (ScrollEventType.LargeIncrement, pos);
575 OnScroll (event_args);
576 pos = event_args.NewValue;
578 event_args = new ScrollEventArgs (ScrollEventType.EndScroll, pos);
579 OnScroll (event_args);
580 pos = event_args.NewValue;
582 UpdatePos (pos, true);
585 private void LargeDecrement ()
587 ScrollEventArgs event_args;
588 int pos = position - large_change;
590 event_args = new ScrollEventArgs (ScrollEventType.LargeDecrement, pos);
591 OnScroll (event_args);
592 pos = event_args.NewValue;
594 event_args = new ScrollEventArgs (ScrollEventType.EndScroll, pos);
595 OnScroll (event_args);
596 pos = event_args.NewValue;
599 UpdatePos (pos, true);
602 private void OnResizeSB (Object o, EventArgs e)
604 if (Width <= 0 || Height <= 0)
609 UpdatePos (position, true);
612 private void OnPaintSB (PaintEventArgs pevent)
615 Paint (this, pevent);
617 ThemeEngine.Current.DrawScrollBar (pevent.Graphics, pevent.ClipRectangle, this);
620 private void OnTimer (Object source, EventArgs e)
624 switch (timer_type) {
626 case TimerType.HoldButton:
627 SetRepeatButtonTimer ();
630 case TimerType.RepeatButton:
632 if ((firstbutton_state & ButtonState.Pushed) == ButtonState.Pushed &&
636 if ((secondbutton_state & ButtonState.Pushed) == ButtonState.Pushed &&
643 case TimerType.HoldThumbArea:
644 SetRepeatThumbAreaTimer ();
647 case TimerType.RepeatThumbArea:
649 Point pnt, pnt_screen;
650 Rectangle thumb_area_screen = thumb_area;
652 pnt_screen = PointToScreen (new Point (thumb_area.X, thumb_area.Y));
653 thumb_area_screen.X = pnt_screen.X;
654 thumb_area_screen.Y = pnt_screen.Y;
656 if (thumb_area_screen.Contains (MousePosition) == false) {
657 timer.Enabled = false;
658 thumb_moving = ThumbMoving.None;
663 pnt = PointToClient (MousePosition);
666 lastclick_pos = pnt.Y;
668 lastclick_pos = pnt.X;
670 if (thumb_moving == ThumbMoving.Forward) {
671 if ((vert && (thumb_pos.Y + thumb_size > lastclick_pos)) ||
672 (!vert && (thumb_pos.X + thumb_size > lastclick_pos)) ||
673 (thumb_area.Contains (pnt) == false)){
674 timer.Enabled = false;
675 thumb_moving = ThumbMoving.None;
683 if ((vert && (thumb_pos.Y < lastclick_pos)) ||
684 (!vert && (thumb_pos.X < lastclick_pos))){
685 timer.Enabled = false;
686 thumb_moving = ThumbMoving.None;
701 private void OnMouseMoveSB (object sender, MouseEventArgs e)
703 if (MouseMove != null) {
707 if (Enabled == false || thumb_size == 0)
710 if (firstbutton_pressed) {
711 if (!first_arrow_area.Contains (e.X, e.Y) && ((firstbutton_state & ButtonState.Pushed) == ButtonState.Pushed)) {
712 firstbutton_state = ButtonState.Normal;
713 Invalidate (first_arrow_area);
715 } else if (first_arrow_area.Contains (e.X, e.Y) && ((firstbutton_state & ButtonState.Normal) == ButtonState.Normal)) {
716 firstbutton_state = ButtonState.Pushed;
717 Invalidate (first_arrow_area);
720 } else if (secondbutton_pressed) {
721 if (!second_arrow_area.Contains (e.X, e.Y) && ((secondbutton_state & ButtonState.Pushed) == ButtonState.Pushed)) {
722 secondbutton_state = ButtonState.Normal;
723 Invalidate (second_arrow_area);
725 } else if (second_arrow_area.Contains (e.X, e.Y) && ((secondbutton_state & ButtonState.Normal) == ButtonState.Normal)) {
726 secondbutton_state = ButtonState.Pushed;
727 Invalidate (second_arrow_area);
730 } else if (thumb_pressed == true) {
735 int mouse_click = e.Y;
736 int outside_curpos = thumb_area.Y + thumb_area.Height - thumb_size + lastclick_pos_thumb;
739 if (mouse_click > thumb_area.Y + thumb_area.Height) {
740 outside_thumbarea_right = true;
741 mouse_click = thumb_area.Y + thumb_area.Height;
744 if (mouse_click < thumb_area.Y) {
745 outside_thumbarea_left = true;
746 mouse_click = thumb_area.Y;
749 if (outside_thumbarea_right && mouse_click < outside_curpos) {
750 outside_thumbarea_right = false;
751 thumb_pixel_click_move_prev =
752 thumb_pixel_click_move = outside_curpos;
755 if (outside_thumbarea_left && mouse_click > thumb_area.Y + lastclick_pos_thumb) {
756 outside_thumbarea_left = false;
757 thumb_pixel_click_move_prev =
758 thumb_pixel_click_move = thumb_area.Y + lastclick_pos_thumb;
761 if (outside_thumbarea_right == false && outside_thumbarea_left == false) {
762 pixel_pos = thumb_pos.Y + (thumb_pixel_click_move - thumb_pixel_click_move_prev);
763 thumb_pixel_click_move_prev = thumb_pixel_click_move;
764 thumb_pixel_click_move = mouse_click;
766 UpdateThumbPos (pixel_pos, true);
767 OnScroll (new ScrollEventArgs (ScrollEventType.ThumbTrack, position));
772 int mouse_click = e.X;
773 int outside_curpos = thumb_area.X + thumb_area.Width - thumb_size + lastclick_pos_thumb;
775 if (mouse_click > thumb_area.X + thumb_area.Width) {
776 outside_thumbarea_right = true;
777 mouse_click = thumb_area.X + thumb_area.Width;
780 if (mouse_click < thumb_area.X) {
781 outside_thumbarea_left = true;
782 mouse_click = thumb_area.X;
785 if (outside_thumbarea_right && mouse_click < outside_curpos) {
786 outside_thumbarea_right = false;
787 thumb_pixel_click_move_prev =
788 thumb_pixel_click_move = outside_curpos;
791 if (outside_thumbarea_left && mouse_click > thumb_area.X + lastclick_pos_thumb) {
792 outside_thumbarea_left = false;
793 thumb_pixel_click_move_prev =
794 thumb_pixel_click_move = thumb_area.X + lastclick_pos_thumb;
797 if (outside_thumbarea_right == false && outside_thumbarea_left == false) {
798 pixel_pos = thumb_pos.X + (thumb_pixel_click_move - thumb_pixel_click_move_prev);
799 thumb_pixel_click_move_prev = thumb_pixel_click_move;
800 thumb_pixel_click_move = mouse_click;
801 UpdateThumbPos (pixel_pos, true);
802 OnScroll (new ScrollEventArgs (ScrollEventType.ThumbTrack, position));
812 private void OnMouseDownSB (object sender, MouseEventArgs e)
816 if (e.Button == MouseButtons.Right) {
817 if (MouseDown != null) {
822 if (Enabled == false)
825 if (firstbutton_state != ButtonState.Inactive && first_arrow_area.Contains (e.X, e.Y)) {
827 firstbutton_state = ButtonState.Pushed;
828 firstbutton_pressed = true;
829 Invalidate (first_arrow_area);
830 if (!timer.Enabled) {
831 SetHoldButtonClickTimer ();
832 timer.Enabled = true;
836 if (secondbutton_state != ButtonState.Inactive && second_arrow_area.Contains (e.X, e.Y)) {
838 secondbutton_state = ButtonState.Pushed;
839 secondbutton_pressed = true;
840 Invalidate (second_arrow_area);
841 if (!timer.Enabled) {
842 SetHoldButtonClickTimer ();
843 timer.Enabled = true;
847 if (thumb_size > 0 && thumb_pos.Contains (e.X, e.Y)) {
848 thumb_pressed = true;
851 lastclick_pos_thumb = e.Y - thumb_pos.Y;
853 thumb_pixel_click_move_prev = thumb_pixel_click_move = e.Y;
856 lastclick_pos_thumb = e.X - thumb_pos.X;
858 thumb_pixel_click_move_prev = thumb_pixel_click_move = e.X;
861 if (thumb_size > 0 && thumb_area.Contains (e.X, e.Y)) {
864 lastclick_pos_thumb = e.Y - thumb_pos.Y;
867 if (e.Y > thumb_pos.Y + thumb_pos.Height) {
869 thumb_moving = ThumbMoving.Forward;
870 Dirty (new Rectangle (0, thumb_pos.Y + thumb_pos.Height,
871 ClientRectangle.Width,
872 ClientRectangle.Height - (thumb_pos.Y + thumb_pos.Height) -
873 scrollbutton_height));
876 thumb_moving = ThumbMoving.Backwards;
877 Dirty (new Rectangle (0, scrollbutton_height,
878 ClientRectangle.Width,
879 thumb_pos.Y - scrollbutton_height));
883 lastclick_pos_thumb = e.X - thumb_pos.X;
886 if (e.X > thumb_pos.X + thumb_pos.Width) {
887 thumb_moving = ThumbMoving.Forward;
889 Dirty (new Rectangle (thumb_pos.X + thumb_pos.Width, 0,
890 ClientRectangle.Width - (thumb_pos.X + thumb_pos.Width) -
892 ClientRectangle.Height));
894 thumb_moving = ThumbMoving.Backwards;
896 Dirty (new Rectangle (scrollbutton_width, 0,
897 thumb_pos.X - scrollbutton_width,
898 ClientRectangle.Height));
902 SetHoldThumbAreaTimer ();
903 timer.Enabled = true;
909 private void OnMouseUpSB (object sender, MouseEventArgs e)
913 if (e.Button == MouseButtons.Right) {
914 if (MouseUp != null) {
919 if (Enabled == false)
922 timer.Enabled = false;
923 if (thumb_moving != ThumbMoving.None) {
925 thumb_moving = ThumbMoving.None;
927 this.Capture = false;
929 if (firstbutton_pressed) {
930 firstbutton_state = ButtonState.Normal;
931 if (first_arrow_area.Contains (e.X, e.Y)) {
934 firstbutton_pressed = false;
935 Dirty (first_arrow_area);
936 } else if (secondbutton_pressed) {
937 secondbutton_state = ButtonState.Normal;
938 if (second_arrow_area.Contains (e.X, e.Y)) {
941 Dirty (second_arrow_area);
942 secondbutton_pressed = false;
943 } else if (thumb_pressed == true) {
944 OnScroll (new ScrollEventArgs (ScrollEventType.ThumbPosition, position));
945 OnScroll (new ScrollEventArgs (ScrollEventType.EndScroll, position));
946 thumb_pressed = false;
954 private void OnKeyDownSB (Object o, KeyEventArgs key)
956 if (Enabled == false)
961 switch (key.KeyCode){
999 private void SetEndPosition ()
1001 ScrollEventArgs event_args;
1004 event_args = new ScrollEventArgs (ScrollEventType.Last, pos);
1005 OnScroll (event_args);
1006 pos = event_args.NewValue;
1008 event_args = new ScrollEventArgs (ScrollEventType.EndScroll, pos);
1009 OnScroll (event_args);
1010 pos = event_args.NewValue;
1015 private void SetHomePosition ()
1017 ScrollEventArgs event_args;
1020 event_args = new ScrollEventArgs (ScrollEventType.First, pos);
1021 OnScroll (event_args);
1022 pos = event_args.NewValue;
1024 event_args = new ScrollEventArgs (ScrollEventType.EndScroll, pos);
1025 OnScroll (event_args);
1026 pos = event_args.NewValue;
1031 private void SmallIncrement ()
1033 ScrollEventArgs event_args;
1034 int pos = position + small_change;
1036 event_args = new ScrollEventArgs (ScrollEventType.SmallIncrement, pos);
1037 OnScroll (event_args);
1038 pos = event_args.NewValue;
1040 event_args = new ScrollEventArgs (ScrollEventType.EndScroll, pos);
1041 OnScroll (event_args);
1042 pos = event_args.NewValue;
1044 UpdatePos (pos, true);
1047 private void SmallDecrement ()
1049 ScrollEventArgs event_args;
1050 int pos = position - small_change;
1052 event_args = new ScrollEventArgs (ScrollEventType.SmallDecrement, pos);
1053 OnScroll (event_args);
1054 pos = event_args.NewValue;
1056 event_args = new ScrollEventArgs (ScrollEventType.EndScroll, pos);
1057 OnScroll (event_args);
1058 pos = event_args.NewValue;
1060 UpdatePos (pos, true);
1063 private void SetHoldButtonClickTimer ()
1065 timer.Enabled = false;
1066 timer.Interval = 200;
1067 timer_type = TimerType.HoldButton;
1068 timer.Enabled = true;
1071 private void SetRepeatButtonTimer ()
1073 timer.Enabled = false;
1074 timer.Interval = 50;
1075 timer_type = TimerType.RepeatButton;
1076 timer.Enabled = true;
1079 private void SetHoldThumbAreaTimer ()
1081 timer.Enabled = false;
1082 timer.Interval = 200;
1083 timer_type = TimerType.HoldThumbArea;
1084 timer.Enabled = true;
1087 private void SetRepeatThumbAreaTimer ()
1089 timer.Enabled = false;
1090 timer.Interval = 50;
1091 timer_type = TimerType.RepeatThumbArea;
1092 timer.Enabled = true;
1095 private void UpdatePos (int newPos, bool update_thumbpos)
1099 if (newPos < minimum)
1102 if (newPos > maximum + 1 - large_change)
1103 pos = maximum + 1 - large_change;
1107 // pos can't be less than minimum
1111 if (update_thumbpos) {
1113 UpdateThumbPos (thumb_area.Y + (int)(((float)(pos - minimum)) * pixel_per_pos), false);
1115 UpdateThumbPos (thumb_area.X + (int)(((float)(pos - minimum)) * pixel_per_pos), false);
1119 position = pos; // Updates directly the value to avoid thumb pos update
1121 if (ValueChanged != null)
1122 ValueChanged (this, EventArgs.Empty);
1126 private void UpdateThumbPos (int pixel, bool update_value)
1132 if (pixel < thumb_area.Y)
1133 thumb_pos.Y = thumb_area.Y;
1135 if (pixel > thumb_area.Y + thumb_area.Height - thumb_size)
1136 thumb_pos.Y = thumb_area.Y + thumb_area.Height - thumb_size;
1138 thumb_pos.Y = pixel;
1141 thumb_pos.Width = ThemeEngine.Current.ScrollBarButtonSize;
1142 thumb_pos.Height = thumb_size;
1143 new_pos = (float) (thumb_pos.Y - thumb_area.Y);
1144 new_pos = new_pos / pixel_per_pos;
1149 if (pixel < thumb_area.X)
1150 thumb_pos.X = thumb_area.X;
1152 if (pixel > thumb_area.X + thumb_area.Width - thumb_size)
1153 thumb_pos.X = thumb_area.X + thumb_area.Width - thumb_size;
1155 thumb_pos.X = pixel;
1158 thumb_pos.Width = thumb_size;
1159 thumb_pos.Height = ThemeEngine.Current.ScrollBarButtonSize;
1160 new_pos = (float) (thumb_pos.X - thumb_area.X);
1161 new_pos = new_pos / pixel_per_pos;
1167 UpdatePos ((int) new_pos + minimum, false);
1170 private void SetValue (int value)
1172 if ( value < minimum || value > maximum )
1173 throw new ArgumentException(
1174 String.Format("'{0}' is not a valid value for 'Value'. 'Value' should be between 'Minimum' and 'Maximum'", value));
1176 if (position != value){
1179 OnValueChanged (EventArgs.Empty);
1180 UpdatePos (value, true);
1184 private void ClearDirty ()
1186 dirty = Rectangle.Empty;
1189 private void Dirty (Rectangle r)
1191 if (dirty == Rectangle.Empty) {
1195 dirty = Rectangle.Union (dirty, r);
1198 private void DirtyThumbArea ()
1200 if (thumb_moving == ThumbMoving.Forward) {
1202 Dirty (new Rectangle (0, thumb_pos.Y + thumb_pos.Height,
1203 ClientRectangle.Width,
1204 ClientRectangle.Height - (thumb_pos.Y + thumb_pos.Height) -
1205 scrollbutton_height));
1207 Dirty (new Rectangle (thumb_pos.X + thumb_pos.Width, 0,
1208 ClientRectangle.Width - (thumb_pos.X + thumb_pos.Width) -
1210 ClientRectangle.Height));
1212 } else if (thumb_moving == ThumbMoving.Backwards) {
1214 Dirty(new Rectangle (0, scrollbutton_height,
1215 ClientRectangle.Width,
1216 thumb_pos.Y - scrollbutton_height));
1218 Dirty (new Rectangle (scrollbutton_width, 0,
1219 thumb_pos.X - scrollbutton_width,
1220 ClientRectangle.Height));
1225 private void InvalidateDirty ()
1228 dirty = Rectangle.Empty;
1231 #endregion //Private Methods