Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'mcs/class/Managed.Windows.Forms/System.Windows.Forms/ScrollBar.cs')
-rw-r--r--mcs/class/Managed.Windows.Forms/System.Windows.Forms/ScrollBar.cs1235
1 files changed, 1235 insertions, 0 deletions
diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ScrollBar.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ScrollBar.cs
new file mode 100644
index 00000000000..8dab1dfe0da
--- /dev/null
+++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ScrollBar.cs
@@ -0,0 +1,1235 @@
+//
+// System.Windows.Forms.ScrollBar.cs
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// Copyright (C) 2004-2005, Novell, Inc.
+//
+// Authors:
+// Jordi Mas i Hernandez jordi@ximian.com
+//
+//
+
+// COMPLETE
+
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.Drawing.Drawing2D;
+using System.ComponentModel;
+using System.Runtime.InteropServices;
+
+namespace System.Windows.Forms
+{
+ [DefaultEvent ("Scroll")]
+ [DefaultProperty ("Value")]
+ public abstract class ScrollBar : Control
+ {
+ #region Local Variables
+ private int position;
+ private int minimum;
+ private int maximum;
+ private int large_change;
+ private int small_change;
+ internal int scrollbutton_height;
+ internal int scrollbutton_width;
+ private ScrollBars type;
+ private Rectangle first_arrow_area = new Rectangle (); // up or left
+ private Rectangle second_arrow_area = new Rectangle (); // down or right
+ private Rectangle thumb_pos = new Rectangle ();
+ private Rectangle thumb_area = new Rectangle ();
+ internal ButtonState firstbutton_state = ButtonState.Normal;
+ internal ButtonState secondbutton_state = ButtonState.Normal;
+ private bool firstbutton_pressed = false;
+ private bool secondbutton_pressed = false;
+ private bool thumb_pressed = false;
+ private float pixel_per_pos = 0;
+ private Timer timer = new Timer ();
+ private TimerType timer_type;
+ private int thumb_pixel_click_move;
+ private int thumb_pixel_click_move_prev;
+ private int thumb_size = 40;
+ private const int thumb_min_size = 8;
+ private const int thumb_notshown_size = 40;
+ internal bool vert;
+ private int lastclick_pos; // Position of the last button-down event
+ private int lastclick_pos_thumb; // Position of the last button-down event relative to the thumb
+ private bool outside_thumbarea_right = false;
+ private bool outside_thumbarea_left = false;
+
+ private Rectangle dirty;
+
+ internal ThumbMoving thumb_moving = ThumbMoving.None;
+ #endregion // Local Variables
+
+ private enum TimerType
+ {
+ HoldButton,
+ RepeatButton,
+ HoldThumbArea,
+ RepeatThumbArea
+ }
+
+ internal enum ThumbMoving
+ {
+ None,
+ Forward,
+ Backwards,
+ }
+
+ #region events
+
+ [Browsable (false)]
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ public new event EventHandler BackColorChanged;
+
+ [Browsable (false)]
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ public new event EventHandler BackgroundImageChanged;
+
+ [Browsable (false)]
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ public new event EventHandler Click;
+
+ [Browsable (false)]
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ public new event EventHandler DoubleClick;
+
+ [Browsable (false)]
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ public new event EventHandler FontChanged;
+
+ [Browsable (false)]
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ public new event EventHandler ForeColorChanged;
+
+ [Browsable (false)]
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ public new event EventHandler ImeModeChanged;
+
+ [Browsable (false)]
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ public new event MouseEventHandler MouseDown;
+
+ [Browsable (false)]
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ public new event MouseEventHandler MouseMove;
+
+ [Browsable (false)]
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ public new event MouseEventHandler MouseUp;
+
+ [Browsable (false)]
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ public new event PaintEventHandler Paint;
+
+ public event ScrollEventHandler Scroll;
+
+ [Browsable (false)]
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ public new event EventHandler TextChanged;
+
+ public event EventHandler ValueChanged;
+ #endregion Events
+
+ public ScrollBar ()
+ {
+ position = 0;
+ minimum = 0;
+ maximum = 100;
+ large_change = 10;
+ small_change = 1;
+
+ timer.Tick += new EventHandler (OnTimer);
+ base.KeyDown += new KeyEventHandler (OnKeyDownSB);
+ base.MouseDown += new MouseEventHandler (OnMouseDownSB);
+ base.MouseUp += new MouseEventHandler (OnMouseUpSB);
+ base.MouseMove += new MouseEventHandler (OnMouseMoveSB);
+ base.Resize += new EventHandler (OnResizeSB);
+ base.TabStop = false;
+
+ SetStyle (ControlStyles.UserPaint | ControlStyles.StandardClick, false);
+ }
+
+ #region Internal & Private Properties
+ internal Rectangle FirstArrowArea {
+ get {
+ return this.first_arrow_area;
+ }
+
+ set {
+ this.first_arrow_area = value;
+ }
+ }
+
+ internal Rectangle SecondArrowArea {
+ get {
+ return this.second_arrow_area;
+ }
+
+ set {
+ this.second_arrow_area = value;
+ }
+ }
+
+ internal Rectangle ThumbPos {
+ get {
+ return thumb_pos;
+ }
+
+ set {
+ thumb_pos = value;
+ }
+ }
+ #endregion // Internal & Private Properties
+
+ #region Public Properties
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Browsable (false)]
+ public override Color BackColor
+ {
+ get { return base.BackColor; }
+ set {
+ if (base.BackColor == value)
+ return;
+
+ if (BackColorChanged != null)
+ BackColorChanged (this, EventArgs.Empty);
+
+ base.BackColor = value;
+ Refresh ();
+ }
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Browsable (false)]
+ public override Image BackgroundImage
+ {
+ get { return base.BackgroundImage; }
+ set {
+ if (base.BackgroundImage == value)
+ return;
+
+ if (BackgroundImageChanged != null)
+ BackgroundImageChanged (this, EventArgs.Empty);
+
+ base.BackgroundImage = value;
+ }
+ }
+
+ protected override CreateParams CreateParams
+ {
+ get { return base.CreateParams; }
+ }
+
+ protected override ImeMode DefaultImeMode
+ {
+ get { return ImeMode.Disable; }
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Browsable (false)]
+ public override Font Font
+ {
+ get { return base.Font; }
+ set {
+ if (base.Font.Equals (value))
+ return;
+
+ if (FontChanged != null)
+ FontChanged (this, EventArgs.Empty);
+
+ base.Font = value;
+ }
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Browsable (false)]
+ public override Color ForeColor
+ {
+ get { return base.ForeColor; }
+ set {
+ if (base.ForeColor == value)
+ return;
+
+ if (ForeColorChanged != null)
+ ForeColorChanged (this, EventArgs.Empty);
+
+ base.ForeColor = value;
+ Refresh ();
+ }
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Browsable (false)]
+ public new ImeMode ImeMode
+ {
+ get { return base.ImeMode; }
+ set {
+ if (base.ImeMode == value)
+ return;
+
+ if (ImeModeChanged != null)
+ ImeModeChanged (this, EventArgs.Empty);
+
+ base.ImeMode = value;
+ }
+ }
+
+ [DefaultValue (10)]
+ [RefreshProperties(RefreshProperties.Repaint)]
+ [MWFDescription("Scroll amount when clicking in the scroll area"), MWFCategory("Behaviour")]
+ public int LargeChange {
+ get {
+ if (large_change > maximum)
+ return (maximum + 1);
+ else
+ return large_change;
+ }
+ set {
+ if (value < 0)
+ throw new Exception( string.Format("Value '{0}' must be greater than or equal to 0.", value));
+
+ if (large_change != value) {
+ large_change = value;
+
+ // thumb area depends on large change value,
+ // so we need to recalculate it.
+ CalcThumbArea ();
+ UpdatePos (Value, true);
+ Refresh ();
+ }
+ }
+ }
+
+ [DefaultValue (100)]
+ [RefreshProperties(RefreshProperties.Repaint)]
+ [MWFDescription("Highest value for scrollbar"), MWFCategory("Behaviour")]
+ public int Maximum {
+ get { return maximum; }
+ set {
+ if (maximum == value)
+ return;
+
+ maximum = value;
+
+ if (maximum < minimum)
+ minimum = maximum;
+
+ // thumb area depends on maximum value,
+ // so we need to recalculate it.
+ CalcThumbArea ();
+ UpdatePos (Value, true);
+ Refresh ();
+ }
+ }
+
+ [DefaultValue (0)]
+ [RefreshProperties(RefreshProperties.Repaint)]
+ [MWFDescription("Smallest value for scrollbar"), MWFCategory("Behaviour")]
+ public int Minimum {
+ get { return minimum; }
+ set {
+ if (minimum == value)
+ return;
+
+ minimum = value;
+
+ if (minimum > maximum)
+ maximum = minimum;
+
+ // thumb area depends on minimum value,
+ // so we need to recalculate it.
+ CalcThumbArea ();
+ UpdatePos (Value, true);
+ Refresh ();
+ }
+ }
+
+ [DefaultValue (1)]
+ [MWFDescription("Scroll amount when clicking scroll arrows"), MWFCategory("Behaviour")]
+ public int SmallChange {
+ get { return small_change; }
+ set {
+ if ( value < 0 )
+ throw new Exception( string.Format("Value '{0}' must be greater than or equal to 0.", value));
+
+ if (small_change != value) {
+ small_change = value;
+ UpdatePos (Value, true);
+ Refresh ();
+ }
+ }
+ }
+
+ [DefaultValue (false)]
+ public new bool TabStop {
+ get { return base.TabStop; }
+ set { base.TabStop = value; }
+ }
+
+ [EditorBrowsable (EditorBrowsableState.Never)]
+ [Bindable (false)]
+ [Browsable (false)]
+ [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
+ public override string Text {
+ get { return base.Text; }
+ set { base.Text = value; }
+ }
+
+ [Bindable(true)]
+ [DefaultValue (0)]
+ [MWFDescription("Current value for scrollbar"), MWFCategory("Behaviour")]
+ public int Value {
+ get { return position; }
+ set {
+ if ( value < minimum || value > maximum )
+ throw new ArgumentException(
+ string.Format("'{0}' is not a valid value for 'Value'. 'Value' should be between 'Minimum' and 'Maximum'", value));
+
+ if (position != value){
+ position = value;
+
+ OnValueChanged (EventArgs.Empty);
+
+ ClearDirty ();
+
+ if (IsHandleCreated) {
+ UpdateThumbPos (thumb_area.Y + (int)(((float)(position - minimum)) * pixel_per_pos), false);
+ }
+
+ InvalidateDirty ();
+ }
+ }
+ }
+
+ #endregion //Public Properties
+
+ #region Public Methods
+
+ protected override void OnEnabledChanged (EventArgs e)
+ {
+ base.OnEnabledChanged (e);
+
+ if (Enabled)
+ firstbutton_state = secondbutton_state = ButtonState.Normal;
+ else
+ firstbutton_state = secondbutton_state = ButtonState.Inactive;
+
+ Refresh ();
+ }
+
+ protected override void OnHandleCreated (System.EventArgs e)
+ {
+ base.OnHandleCreated (e);
+
+ CalcButtonSizes ();
+ CalcThumbArea ();
+ UpdateThumbPos (thumb_area.Y + (int)(((float)(position - minimum)) * pixel_per_pos), false);
+ }
+
+ protected virtual void OnScroll (ScrollEventArgs event_args)
+ {
+ if (Scroll == null)
+ return;
+
+ if (event_args.NewValue < Minimum) {
+ event_args.NewValue = Minimum;
+ }
+
+ if (event_args.NewValue > Maximum) {
+ event_args.NewValue = Maximum;
+ }
+
+ Scroll (this, event_args);
+ }
+
+ protected virtual void OnValueChanged (EventArgs e)
+ {
+ if (ValueChanged != null)
+ ValueChanged (this, e);
+ }
+
+ public override string ToString()
+ {
+ return string.Format("{0}, Minimum: {1}, Maximum: {2}, Value: {3}",
+ GetType( ).FullName.ToString( ), minimum, maximum, position);
+ }
+
+ protected void UpdateScrollInfo ()
+ {
+ Refresh ();
+ }
+
+ protected override void WndProc (ref Message m)
+ {
+ switch ((Msg) m.Msg)
+ {
+ case Msg.WM_PAINT:
+ {
+ PaintEventArgs paint_event;
+
+ paint_event = XplatUI.PaintEventStart (Handle, true);
+ OnPaintSB (paint_event);
+ XplatUI.PaintEventEnd (Handle, true);
+ return;
+ }
+
+ case Msg.WM_ERASEBKGND:
+ m.Result = (IntPtr) 1; /// Disable background painting to avoid flickering
+ return;
+
+ default:
+ break;
+ }
+
+ base.WndProc (ref m);
+ }
+
+ #endregion //Public Methods
+
+ #region Private Methods
+
+ private void CalcButtonSizes ()
+ {
+ if (vert) {
+ if (Height < ThemeEngine.Current.ScrollBarButtonSize * 2)
+ scrollbutton_height = Height /2;
+ else
+ scrollbutton_height = ThemeEngine.Current.ScrollBarButtonSize;
+
+ } else {
+ if (Width < ThemeEngine.Current.ScrollBarButtonSize * 2)
+ scrollbutton_width = Width /2;
+ else
+ scrollbutton_width = ThemeEngine.Current.ScrollBarButtonSize;
+ }
+ }
+
+ private void CalcThumbArea ()
+ {
+ // Thumb area
+ if (vert) {
+
+ thumb_area.Height = Height - scrollbutton_height - scrollbutton_height;
+ thumb_area.X = 0;
+ thumb_area.Y = scrollbutton_height;
+ thumb_area.Width = Width;
+
+ if (Height < thumb_notshown_size)
+ thumb_size = 0;
+ else {
+ double per = ((double) this.LargeChange / (double)((1 + maximum - minimum)));
+ thumb_size = 1 + (int) (thumb_area.Height * per);
+
+ if (thumb_size < thumb_min_size)
+ thumb_size = thumb_min_size;
+ }
+
+ pixel_per_pos = ((float)(thumb_area.Height - thumb_size) / (float) ((maximum - minimum - this.LargeChange) + 1));
+
+ } else {
+
+ thumb_area.Y = 0;
+ thumb_area.X = scrollbutton_width;
+ thumb_area.Height = Height;
+ thumb_area.Width = Width - scrollbutton_width - scrollbutton_width;
+
+ if (Width < thumb_notshown_size)
+ thumb_size = 0;
+ else {
+ double per = ((double) this.LargeChange / (double)((1 + maximum - minimum)));
+ thumb_size = 1 + (int) (thumb_area.Width * per);
+
+ if (thumb_size < thumb_min_size)
+ thumb_size = thumb_min_size;
+ }
+
+ pixel_per_pos = ((float)(thumb_area.Width - thumb_size) / (float) ((maximum - minimum - this.LargeChange) + 1));
+ }
+ }
+
+ private void LargeIncrement ()
+ {
+ ScrollEventArgs event_args;
+ int pos = position + large_change;
+
+ event_args = new ScrollEventArgs (ScrollEventType.LargeIncrement, pos);
+ OnScroll (event_args);
+ pos = event_args.NewValue;
+
+ event_args = new ScrollEventArgs (ScrollEventType.EndScroll, pos);
+ OnScroll (event_args);
+ pos = event_args.NewValue;
+
+ UpdatePos (pos, true);
+ }
+
+ private void LargeDecrement ()
+ {
+ ScrollEventArgs event_args;
+ int pos = position - large_change;
+
+ event_args = new ScrollEventArgs (ScrollEventType.LargeDecrement, pos);
+ OnScroll (event_args);
+ pos = event_args.NewValue;
+
+ event_args = new ScrollEventArgs (ScrollEventType.EndScroll, pos);
+ OnScroll (event_args);
+ pos = event_args.NewValue;
+
+
+ UpdatePos (pos, true);
+ }
+
+ private void OnResizeSB (Object o, EventArgs e)
+ {
+ if (Width <= 0 || Height <= 0)
+ return;
+
+ CalcButtonSizes ();
+ CalcThumbArea ();
+ UpdatePos (position, true);
+ }
+
+ private void OnPaintSB (PaintEventArgs pevent)
+ {
+ if (Paint != null) {
+ Paint (this, pevent);
+ }
+ ThemeEngine.Current.DrawScrollBar (pevent.Graphics, pevent.ClipRectangle, this);
+ }
+
+ private void OnTimer (Object source, EventArgs e)
+ {
+ ClearDirty ();
+
+ switch (timer_type) {
+
+ case TimerType.HoldButton:
+ SetRepeatButtonTimer ();
+ break;
+
+ case TimerType.RepeatButton:
+ {
+ if ((firstbutton_state & ButtonState.Pushed) == ButtonState.Pushed &&
+ position != Minimum)
+ SmallDecrement();
+
+ if ((secondbutton_state & ButtonState.Pushed) == ButtonState.Pushed &&
+ position != Maximum)
+ SmallIncrement();
+
+ break;
+ }
+
+ case TimerType.HoldThumbArea:
+ SetRepeatThumbAreaTimer ();
+ break;
+
+ case TimerType.RepeatThumbArea:
+ {
+ Point pnt, pnt_screen;
+ Rectangle thumb_area_screen = thumb_area;
+
+ pnt_screen = PointToScreen (new Point (thumb_area.X, thumb_area.Y));
+ thumb_area_screen.X = pnt_screen.X;
+ thumb_area_screen.Y = pnt_screen.Y;
+
+ if (thumb_area_screen.Contains (MousePosition) == false) {
+ timer.Enabled = false;
+ thumb_moving = ThumbMoving.None;
+ DirtyThumbArea ();
+ InvalidateDirty ();
+ }
+
+ pnt = PointToClient (MousePosition);
+
+ if (vert)
+ lastclick_pos = pnt.Y;
+ else
+ lastclick_pos = pnt.X;
+
+ if (thumb_moving == ThumbMoving.Forward) {
+ if ((vert && (thumb_pos.Y + thumb_size > lastclick_pos)) ||
+ (!vert && (thumb_pos.X + thumb_size > lastclick_pos)) ||
+ (thumb_area.Contains (pnt) == false)){
+ timer.Enabled = false;
+ thumb_moving = ThumbMoving.None;
+ Refresh ();
+ return;
+ } else {
+ LargeIncrement ();
+ }
+ }
+ else
+ if ((vert && (thumb_pos.Y < lastclick_pos)) ||
+ (!vert && (thumb_pos.X < lastclick_pos))){
+ timer.Enabled = false;
+ thumb_moving = ThumbMoving.None;
+ Refresh ();
+ } else {
+ LargeDecrement ();
+ }
+
+ break;
+ }
+ default:
+ break;
+ }
+
+ InvalidateDirty ();
+ }
+
+ private void OnMouseMoveSB (object sender, MouseEventArgs e)
+ {
+ if (MouseMove != null) {
+ MouseMove (this, e);
+ }
+
+ if (Enabled == false || thumb_size == 0)
+ return;
+
+ if (firstbutton_pressed) {
+ if (!first_arrow_area.Contains (e.X, e.Y) && ((firstbutton_state & ButtonState.Pushed) == ButtonState.Pushed)) {
+ firstbutton_state = ButtonState.Normal;
+ Invalidate (first_arrow_area);
+ return;
+ } else if (first_arrow_area.Contains (e.X, e.Y) && ((firstbutton_state & ButtonState.Normal) == ButtonState.Normal)) {
+ firstbutton_state = ButtonState.Pushed;
+ Invalidate (first_arrow_area);
+ return;
+ }
+ } else if (secondbutton_pressed) {
+ if (!second_arrow_area.Contains (e.X, e.Y) && ((secondbutton_state & ButtonState.Pushed) == ButtonState.Pushed)) {
+ secondbutton_state = ButtonState.Normal;
+ Invalidate (second_arrow_area);
+ return;
+ } else if (second_arrow_area.Contains (e.X, e.Y) && ((secondbutton_state & ButtonState.Normal) == ButtonState.Normal)) {
+ secondbutton_state = ButtonState.Pushed;
+ Invalidate (second_arrow_area);
+ return;
+ }
+ } else if (thumb_pressed == true) {
+ int pixel_pos;
+
+ if (vert) {
+
+ int mouse_click = e.Y;
+ int outside_curpos = thumb_area.Y + thumb_area.Height - thumb_size + lastclick_pos_thumb;
+
+
+ if (mouse_click > thumb_area.Y + thumb_area.Height) {
+ outside_thumbarea_right = true;
+ mouse_click = thumb_area.Y + thumb_area.Height;
+ }
+
+ if (mouse_click < thumb_area.Y) {
+ outside_thumbarea_left = true;
+ mouse_click = thumb_area.Y;
+ }
+
+ if (outside_thumbarea_right && mouse_click < outside_curpos) {
+ outside_thumbarea_right = false;
+ thumb_pixel_click_move_prev =
+ thumb_pixel_click_move = outside_curpos;
+ }
+
+ if (outside_thumbarea_left && mouse_click > thumb_area.Y + lastclick_pos_thumb) {
+ outside_thumbarea_left = false;
+ thumb_pixel_click_move_prev =
+ thumb_pixel_click_move = thumb_area.Y + lastclick_pos_thumb;
+ }
+
+ if (outside_thumbarea_right == false && outside_thumbarea_left == false) {
+ pixel_pos = thumb_pos.Y + (thumb_pixel_click_move - thumb_pixel_click_move_prev);
+ thumb_pixel_click_move_prev = thumb_pixel_click_move;
+ thumb_pixel_click_move = mouse_click;
+
+ UpdateThumbPos (pixel_pos, true);
+ OnScroll (new ScrollEventArgs (ScrollEventType.ThumbTrack, position));
+ }
+
+ }
+ else {
+ int mouse_click = e.X;
+ int outside_curpos = thumb_area.X + thumb_area.Width - thumb_size + lastclick_pos_thumb;
+
+ if (mouse_click > thumb_area.X + thumb_area.Width) {
+ outside_thumbarea_right = true;
+ mouse_click = thumb_area.X + thumb_area.Width;
+ }
+
+ if (mouse_click < thumb_area.X) {
+ outside_thumbarea_left = true;
+ mouse_click = thumb_area.X;
+ }
+
+ if (outside_thumbarea_right && mouse_click < outside_curpos) {
+ outside_thumbarea_right = false;
+ thumb_pixel_click_move_prev =
+ thumb_pixel_click_move = outside_curpos;
+ }
+
+ if (outside_thumbarea_left && mouse_click > thumb_area.X + lastclick_pos_thumb) {
+ outside_thumbarea_left = false;
+ thumb_pixel_click_move_prev =
+ thumb_pixel_click_move = thumb_area.X + lastclick_pos_thumb;
+ }
+
+ if (outside_thumbarea_right == false && outside_thumbarea_left == false) {
+ pixel_pos = thumb_pos.X + (thumb_pixel_click_move - thumb_pixel_click_move_prev);
+ thumb_pixel_click_move_prev = thumb_pixel_click_move;
+ thumb_pixel_click_move = mouse_click;
+ UpdateThumbPos (pixel_pos, true);
+ OnScroll (new ScrollEventArgs (ScrollEventType.ThumbTrack, position));
+ }
+
+ }
+
+ Refresh ();
+ }
+
+ }
+
+ private void OnMouseDownSB (object sender, MouseEventArgs e)
+ {
+ ClearDirty ();
+
+ if (e.Button == MouseButtons.Right) {
+ if (MouseDown != null) {
+ MouseDown (this, e);
+ }
+ }
+
+ if (Enabled == false)
+ return;
+
+ if (firstbutton_state != ButtonState.Inactive && first_arrow_area.Contains (e.X, e.Y)) {
+ this.Capture = true;
+ firstbutton_state = ButtonState.Pushed;
+ firstbutton_pressed = true;
+ Invalidate (first_arrow_area);
+ if (!timer.Enabled) {
+ SetHoldButtonClickTimer ();
+ timer.Enabled = true;
+ }
+ }
+
+ if (secondbutton_state != ButtonState.Inactive && second_arrow_area.Contains (e.X, e.Y)) {
+ this.Capture = true;
+ secondbutton_state = ButtonState.Pushed;
+ secondbutton_pressed = true;
+ Invalidate (second_arrow_area);
+ if (!timer.Enabled) {
+ SetHoldButtonClickTimer ();
+ timer.Enabled = true;
+ }
+ }
+
+ if (thumb_size > 0 && thumb_pos.Contains (e.X, e.Y)) {
+ thumb_pressed = true;
+ this.Capture = true;
+ if (vert) {
+ lastclick_pos_thumb = e.Y - thumb_pos.Y;
+ lastclick_pos = e.Y;
+ thumb_pixel_click_move_prev = thumb_pixel_click_move = e.Y;
+ }
+ else {
+ lastclick_pos_thumb = e.X - thumb_pos.X;
+ lastclick_pos = e.X;
+ thumb_pixel_click_move_prev = thumb_pixel_click_move = e.X;
+ }
+ } else {
+ if (thumb_size > 0 && thumb_area.Contains (e.X, e.Y)) {
+
+ if (vert) {
+ lastclick_pos_thumb = e.Y - thumb_pos.Y;
+ lastclick_pos = e.Y;
+
+ if (e.Y > thumb_pos.Y + thumb_pos.Height) {
+ LargeIncrement ();
+ thumb_moving = ThumbMoving.Forward;
+ Dirty (new Rectangle (0, thumb_pos.Y + thumb_pos.Height,
+ ClientRectangle.Width,
+ ClientRectangle.Height - (thumb_pos.Y + thumb_pos.Height) -
+ scrollbutton_height));
+ } else {
+ LargeDecrement ();
+ thumb_moving = ThumbMoving.Backwards;
+ Dirty (new Rectangle (0, scrollbutton_height,
+ ClientRectangle.Width,
+ thumb_pos.Y - scrollbutton_height));
+ }
+ } else {
+
+ lastclick_pos_thumb = e.X - thumb_pos.X;
+ lastclick_pos = e.X;
+
+ if (e.X > thumb_pos.X + thumb_pos.Width) {
+ thumb_moving = ThumbMoving.Forward;
+ LargeIncrement ();
+ Dirty (new Rectangle (thumb_pos.X + thumb_pos.Width, 0,
+ ClientRectangle.Width - (thumb_pos.X + thumb_pos.Width) -
+ scrollbutton_width,
+ ClientRectangle.Height));
+ } else {
+ thumb_moving = ThumbMoving.Backwards;
+ LargeDecrement ();
+ Dirty (new Rectangle (scrollbutton_width, 0,
+ thumb_pos.X - scrollbutton_width,
+ ClientRectangle.Height));
+ }
+ }
+
+ SetHoldThumbAreaTimer ();
+ timer.Enabled = true;
+ InvalidateDirty ();
+ }
+ }
+ }
+
+ private void OnMouseUpSB (object sender, MouseEventArgs e)
+ {
+ ClearDirty ();
+
+ if (e.Button == MouseButtons.Right) {
+ if (MouseUp != null) {
+ MouseUp (this, e);
+ }
+ }
+
+ if (Enabled == false)
+ return;
+
+ timer.Enabled = false;
+ if (thumb_moving != ThumbMoving.None) {
+ DirtyThumbArea ();
+ thumb_moving = ThumbMoving.None;
+ }
+ this.Capture = false;
+
+ if (firstbutton_pressed) {
+ firstbutton_state = ButtonState.Normal;
+ if (first_arrow_area.Contains (e.X, e.Y)) {
+ SmallDecrement ();
+ }
+ firstbutton_pressed = false;
+ Dirty (first_arrow_area);
+ } else if (secondbutton_pressed) {
+ secondbutton_state = ButtonState.Normal;
+ if (second_arrow_area.Contains (e.X, e.Y)) {
+ SmallIncrement ();
+ }
+ Dirty (second_arrow_area);
+ secondbutton_pressed = false;
+ } else if (thumb_pressed == true) {
+ OnScroll (new ScrollEventArgs (ScrollEventType.ThumbPosition, position));
+ OnScroll (new ScrollEventArgs (ScrollEventType.EndScroll, position));
+ thumb_pressed = false;
+ Refresh ();
+ return;
+ }
+
+ InvalidateDirty ();
+ }
+
+ private void OnKeyDownSB (Object o, KeyEventArgs key)
+ {
+ if (Enabled == false)
+ return;
+
+ ClearDirty ();
+
+ switch (key.KeyCode){
+ case Keys.Up:
+ {
+ SmallDecrement ();
+ break;
+ }
+ case Keys.Down:
+ {
+ SmallIncrement ();
+ break;
+ }
+ case Keys.PageUp:
+ {
+ LargeDecrement ();
+ break;
+ }
+ case Keys.PageDown:
+ {
+ LargeIncrement ();
+ break;
+ }
+ case Keys.Home:
+ {
+ SetHomePosition ();
+ break;
+ }
+ case Keys.End:
+ {
+ SetEndPosition ();
+ break;
+ }
+ default:
+ break;
+ }
+
+ InvalidateDirty ();
+ }
+
+ private void SetEndPosition ()
+ {
+ ScrollEventArgs event_args;
+ int pos = Maximum;
+
+ event_args = new ScrollEventArgs (ScrollEventType.Last, pos);
+ OnScroll (event_args);
+ pos = event_args.NewValue;
+
+ event_args = new ScrollEventArgs (ScrollEventType.EndScroll, pos);
+ OnScroll (event_args);
+ pos = event_args.NewValue;
+
+ SetValue (pos);
+ }
+
+ private void SetHomePosition ()
+ {
+ ScrollEventArgs event_args;
+ int pos = Minimum;
+
+ event_args = new ScrollEventArgs (ScrollEventType.First, pos);
+ OnScroll (event_args);
+ pos = event_args.NewValue;
+
+ event_args = new ScrollEventArgs (ScrollEventType.EndScroll, pos);
+ OnScroll (event_args);
+ pos = event_args.NewValue;
+
+ SetValue (pos);
+ }
+
+ private void SmallIncrement ()
+ {
+ ScrollEventArgs event_args;
+ int pos = position + small_change;
+
+ event_args = new ScrollEventArgs (ScrollEventType.SmallIncrement, pos);
+ OnScroll (event_args);
+ pos = event_args.NewValue;
+
+ event_args = new ScrollEventArgs (ScrollEventType.EndScroll, pos);
+ OnScroll (event_args);
+ pos = event_args.NewValue;
+
+ UpdatePos (pos, true);
+ }
+
+ private void SmallDecrement ()
+ {
+ ScrollEventArgs event_args;
+ int pos = position - small_change;
+
+ event_args = new ScrollEventArgs (ScrollEventType.SmallDecrement, pos);
+ OnScroll (event_args);
+ pos = event_args.NewValue;
+
+ event_args = new ScrollEventArgs (ScrollEventType.EndScroll, pos);
+ OnScroll (event_args);
+ pos = event_args.NewValue;
+
+ UpdatePos (pos, true);
+ }
+
+ private void SetHoldButtonClickTimer ()
+ {
+ timer.Enabled = false;
+ timer.Interval = 200;
+ timer_type = TimerType.HoldButton;
+ timer.Enabled = true;
+ }
+
+ private void SetRepeatButtonTimer ()
+ {
+ timer.Enabled = false;
+ timer.Interval = 50;
+ timer_type = TimerType.RepeatButton;
+ timer.Enabled = true;
+ }
+
+ private void SetHoldThumbAreaTimer ()
+ {
+ timer.Enabled = false;
+ timer.Interval = 200;
+ timer_type = TimerType.HoldThumbArea;
+ timer.Enabled = true;
+ }
+
+ private void SetRepeatThumbAreaTimer ()
+ {
+ timer.Enabled = false;
+ timer.Interval = 50;
+ timer_type = TimerType.RepeatThumbArea;
+ timer.Enabled = true;
+ }
+
+ private void UpdatePos (int newPos, bool update_thumbpos)
+ {
+ int pos;
+
+ if (newPos < minimum)
+ pos = minimum;
+ else
+ if (newPos > maximum + 1 - large_change)
+ pos = maximum + 1 - large_change;
+ else
+ pos = newPos;
+
+ // pos can't be less than minimum
+ if (pos < minimum)
+ pos = minimum;
+
+ if (update_thumbpos) {
+ if (vert)
+ UpdateThumbPos (thumb_area.Y + (int)(((float)(pos - minimum)) * pixel_per_pos), false);
+ else
+ UpdateThumbPos (thumb_area.X + (int)(((float)(pos - minimum)) * pixel_per_pos), false);
+ SetValue (pos);
+ }
+ else {
+ position = pos; // Updates directly the value to avoid thumb pos update
+
+ if (ValueChanged != null)
+ ValueChanged (this, EventArgs.Empty);
+ }
+ }
+
+ private void UpdateThumbPos (int pixel, bool update_value)
+ {
+ float new_pos = 0;
+
+ if (vert) {
+ Dirty (thumb_pos);
+ if (pixel < thumb_area.Y)
+ thumb_pos.Y = thumb_area.Y;
+ else
+ if (pixel > thumb_area.Y + thumb_area.Height - thumb_size)
+ thumb_pos.Y = thumb_area.Y + thumb_area.Height - thumb_size;
+ else
+ thumb_pos.Y = pixel;
+
+ thumb_pos.X = 0;
+ thumb_pos.Width = ThemeEngine.Current.ScrollBarButtonSize;
+ thumb_pos.Height = thumb_size;
+ new_pos = (float) (thumb_pos.Y - thumb_area.Y);
+ new_pos = new_pos / pixel_per_pos;
+
+ Dirty (thumb_pos);
+ } else {
+ Dirty (thumb_pos);
+ if (pixel < thumb_area.X)
+ thumb_pos.X = thumb_area.X;
+ else
+ if (pixel > thumb_area.X + thumb_area.Width - thumb_size)
+ thumb_pos.X = thumb_area.X + thumb_area.Width - thumb_size;
+ else
+ thumb_pos.X = pixel;
+
+ thumb_pos.Y = 0;
+ thumb_pos.Width = thumb_size;
+ thumb_pos.Height = ThemeEngine.Current.ScrollBarButtonSize;
+ new_pos = (float) (thumb_pos.X - thumb_area.X);
+ new_pos = new_pos / pixel_per_pos;
+
+ Dirty (thumb_pos);
+ }
+
+ if (update_value)
+ UpdatePos ((int) new_pos + minimum, false);
+ }
+
+ private void SetValue (int value)
+ {
+ if ( value < minimum || value > maximum )
+ throw new ArgumentException(
+ String.Format("'{0}' is not a valid value for 'Value'. 'Value' should be between 'Minimum' and 'Maximum'", value));
+
+ if (position != value){
+ position = value;
+
+ OnValueChanged (EventArgs.Empty);
+ UpdatePos (value, true);
+ }
+ }
+
+ private void ClearDirty ()
+ {
+ dirty = Rectangle.Empty;
+ }
+
+ private void Dirty (Rectangle r)
+ {
+ if (dirty == Rectangle.Empty) {
+ dirty = r;
+ return;
+ }
+ dirty = Rectangle.Union (dirty, r);
+ }
+
+ private void DirtyThumbArea ()
+ {
+ if (thumb_moving == ThumbMoving.Forward) {
+ if (vert) {
+ Dirty (new Rectangle (0, thumb_pos.Y + thumb_pos.Height,
+ ClientRectangle.Width,
+ ClientRectangle.Height - (thumb_pos.Y + thumb_pos.Height) -
+ scrollbutton_height));
+ } else {
+ Dirty (new Rectangle (thumb_pos.X + thumb_pos.Width, 0,
+ ClientRectangle.Width - (thumb_pos.X + thumb_pos.Width) -
+ scrollbutton_width,
+ ClientRectangle.Height));
+ }
+ } else if (thumb_moving == ThumbMoving.Backwards) {
+ if (vert) {
+ Dirty(new Rectangle (0, scrollbutton_height,
+ ClientRectangle.Width,
+ thumb_pos.Y - scrollbutton_height));
+ } else {
+ Dirty (new Rectangle (scrollbutton_width, 0,
+ thumb_pos.X - scrollbutton_width,
+ ClientRectangle.Height));
+ }
+ }
+ }
+
+ private void InvalidateDirty ()
+ {
+ Invalidate (dirty);
+ dirty = Rectangle.Empty;
+ }
+
+ #endregion //Private Methods
+ }
+}
+
+