//
// System.Windows.Forms.TrackBar.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-2006 Novell, Inc.
//
// Authors:
//	Jordi Mas i Hernandez, jordi@ximian.com
//	Rolf Bjarne Kvinge, RKvinge@novell.com
// 
// TODO:
//		- The AutoSize functionality seems quite broken for vertical controls in .Net 1.1. Not
//		sure if we are implementing it the right way.
//

// NOT COMPLETE

using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.Timers;
using System.Runtime.InteropServices;

namespace System.Windows.Forms
{	
#if NET_2_0
	[DefaultBindingProperty ("Value")]
	[ComVisible (true)]
	[ClassInterface (ClassInterfaceType.AutoDispatch)]
#endif
	[Designer("System.Windows.Forms.Design.TrackBarDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
	[DefaultEvent ("Scroll")]
	[DefaultProperty("Value")]
	public class TrackBar : Control, ISupportInitialize
	{
		private int minimum;
		private int maximum;
		internal int tickFrequency;
		private bool autosize;
		private int position;
		private int smallChange;
		private int largeChange;
		private Orientation orientation;
		private TickStyle tickStyle;		
		private Rectangle thumb_pos = new Rectangle ();	 /* Current position and size of the thumb */
		private Rectangle thumb_area = new Rectangle (); /* Area where the thumb can scroll */
		internal bool thumb_pressed = false;		 
		private System.Timers.Timer holdclick_timer = new System.Timers.Timer ();
		internal int thumb_mouseclick;		
		private bool mouse_clickmove;
		private bool is_moving_right; // which way the thumb should move when mouse is down (right=up, left=down) 
		internal int mouse_down_x_offset; // how far from left side of thumb was the mouse clicked.
		internal bool mouse_moved; // has the mouse moved since it was clicked?
		private const int size_of_autosize = 45;
#if NET_2_0
		private bool right_to_left_layout;
#endif
		bool thumb_entered;
	
		#region events
#if NET_2_0
		[EditorBrowsable (EditorBrowsableState.Always)]
		[Browsable (true)]
		public new event EventHandler AutoSizeChanged {
			add {base.AutoSizeChanged += value;}
			remove {base.AutoSizeChanged -= value;}
		}
#endif

		[Browsable (false)]
		[EditorBrowsable (EditorBrowsableState.Never)]
		public new event EventHandler BackgroundImageChanged {
			add { base.BackgroundImageChanged += value; }
			remove { base.BackgroundImageChanged -= value; }
		}
		
#if NET_2_0
		[EditorBrowsable (EditorBrowsableState.Never)]
		[Browsable (false)]
		public new event EventHandler BackgroundImageLayoutChanged
		{
			add { base.BackgroundImageLayoutChanged += value; }
			remove { base.BackgroundImageLayoutChanged -= value; }
		}
#endif

		[Browsable (false)]
		[EditorBrowsable (EditorBrowsableState.Never)]
		public new event EventHandler Click {
			add { base.Click += value; }
			remove { base.Click -= value; }
		}
		
		[Browsable (false)]
		[EditorBrowsable (EditorBrowsableState.Never)]
		public new event EventHandler DoubleClick {
			add { base.DoubleClick += value; }
			remove { base.DoubleClick -= value; }
		}
		
		[Browsable (false)]
		[EditorBrowsable (EditorBrowsableState.Never)]
		public new event EventHandler FontChanged {
			add { base.FontChanged += value; }
			remove { base.FontChanged -= value; }
		}
		
		[Browsable (false)]
		[EditorBrowsable (EditorBrowsableState.Never)]
		public new event EventHandler ForeColorChanged {
			add { base.ForeColorChanged += value; }
			remove { base.ForeColorChanged -= value; }
		}
		
		[Browsable (false)]
		[EditorBrowsable (EditorBrowsableState.Never)]
		public new event EventHandler ImeModeChanged {
			add { base.ImeModeChanged += value; }
			remove { base.ImeModeChanged -= value; }
		}
		
#if NET_2_0
		[Browsable (false)]
		[EditorBrowsable (EditorBrowsableState.Never)]
		public new event MouseEventHandler MouseClick {
			add {base.MouseClick += value;}
			remove {base.MouseClick -= value;}
		}
		
		[Browsable (false)]
		[EditorBrowsable (EditorBrowsableState.Never)]
		public new event MouseEventHandler MouseDoubleClick
		{
			add { base.MouseDoubleClick += value; }
			remove { base.MouseDoubleClick -= value; }
		}
		
		[Browsable (false)]
		[EditorBrowsable (EditorBrowsableState.Never)]
		public new event EventHandler PaddingChanged
		{
			add { base.PaddingChanged += value; }
			remove { base.PaddingChanged -= value; }
		}
		
#endif
		
		[Browsable (false)]
		[EditorBrowsable (EditorBrowsableState.Never)]
		public new event PaintEventHandler Paint {
			add { base.Paint += value; }
			remove { base.Paint -= value; }
		}

#if NET_2_0
		public new event EventHandler RightToLeftLayoutChanged {
			add {Events.AddHandler (RightToLeftLayoutChangedEvent, value);}
			remove {Events.RemoveHandler (RightToLeftLayoutChangedEvent, value);}
		}
#endif

		[Browsable (false)]
		[EditorBrowsable (EditorBrowsableState.Never)]
		public new event EventHandler TextChanged {
			add { base.TextChanged += value; }
			remove { base.TextChanged -= value; }
		}

#if NET_2_0
		static object RightToLeftLayoutChangedEvent = new object ();
#endif
		static object ScrollEvent = new object ();
		static object ValueChangedEvent = new object ();

		public event EventHandler Scroll {
			add { Events.AddHandler (ScrollEvent, value); }
			remove { Events.RemoveHandler (ScrollEvent, value); }
		}

		public event EventHandler ValueChanged {
			add { Events.AddHandler (ValueChangedEvent, value); }
			remove { Events.RemoveHandler (ValueChangedEvent, value); }
		}
		
		#endregion // Events

		public TrackBar ()
		{
			orientation = Orientation.Horizontal;
			minimum = 0;
			maximum = 10;
			tickFrequency = 1;
			autosize = true;
			position = 0;
			tickStyle = TickStyle.BottomRight;
			smallChange = 1;
			largeChange = 5;			
			mouse_clickmove = false;			
			MouseDown += new MouseEventHandler (OnMouseDownTB); 
			MouseUp += new MouseEventHandler (OnMouseUpTB); 
			MouseMove += new MouseEventHandler (OnMouseMoveTB);
			MouseLeave += new EventHandler (OnMouseLeave);
			KeyDown += new KeyEventHandler (OnKeyDownTB);
			LostFocus += new EventHandler (OnLostFocusTB);
			GotFocus += new EventHandler (OnGotFocusTB);
			holdclick_timer.Elapsed += new ElapsedEventHandler (OnFirstClickTimer);

			SetStyle (ControlStyles.UserPaint | ControlStyles.Opaque
#if NET_2_0
				| ControlStyles.UseTextForAccessibility
#endif
				, false);
		}

		#region Private & Internal Properties
		internal Rectangle ThumbPos {
			get {
				return thumb_pos;
			}

			set {
				thumb_pos = value;
			}
		}

		internal Rectangle ThumbArea {
			get {
				return thumb_area;
			}

			set {
				thumb_area = value;
			}
		}

		internal bool ThumbEntered {
			get { return thumb_entered; }
			set {
				if (thumb_entered == value)
					return;
				thumb_entered = value;
				if (ThemeEngine.Current.TrackBarHasHotThumbStyle)
					Invalidate (GetRealThumbRectangle ());
			}
		}
		#endregion	// Private & Internal Properties

		#region Public Properties

#if NET_2_0
		[Browsable (true)]
		[EditorBrowsable (EditorBrowsableState.Always)]
		[DesignerSerializationVisibility (DesignerSerializationVisibility.Visible)]
#endif
		[DefaultValue (true)]
#if NET_2_0
		public override bool AutoSize {
#else
		public new bool AutoSize {
#endif
			get { return autosize; }
			set { autosize = value;}
		}

		[EditorBrowsable (EditorBrowsableState.Never)]
		[Browsable (false)]
		public override Image BackgroundImage {
			get { return base.BackgroundImage; }
			set { base.BackgroundImage = value; }
		}

#if NET_2_0
		[EditorBrowsable (EditorBrowsableState.Never)]
		[Browsable (false)]
		public override ImageLayout BackgroundImageLayout {
			get {
				return base.BackgroundImageLayout;
			}
			set {
				base.BackgroundImageLayout = value;
			}
		}
#endif

		protected override CreateParams CreateParams {
			get {
				return base.CreateParams;
			}
		}

		protected override ImeMode DefaultImeMode {
			get {return ImeMode.Disable; }
		}

		protected override Size DefaultSize {
			get { return ThemeEngine.Current.TrackBarDefaultSize; }
		}	
		
#if NET_2_0
		[EditorBrowsable (EditorBrowsableState.Never)]
		protected override bool DoubleBuffered {
			get {
				return base.DoubleBuffered;
			}
			set {
				base.DoubleBuffered = value;
			}
		}
#endif

		[Browsable(false)]
		[EditorBrowsable (EditorBrowsableState.Never)]
		public override Font Font {
			get { return base.Font;	}
			set { base.Font = value; }
		}

		[EditorBrowsable (EditorBrowsableState.Never)]	
		[Browsable (false)]
		public override Color ForeColor {
			get { return base.ForeColor; }
			set { base.ForeColor = value; }
		}		

		[EditorBrowsable (EditorBrowsableState.Never)]	
		[Browsable (false)]
		public new ImeMode ImeMode {
			get { return base.ImeMode; }
			set { base.ImeMode = value; }
		}
		
		[DefaultValue (5)]
		public int LargeChange 
		{
			get { return largeChange; }
			set {
#if NET_2_0
				if (value < 0)
					throw new ArgumentOutOfRangeException (string.Format ("Value '{0}' must be greater than or equal to 0.", value));
#else
				if ( value < 0 )
					throw new ArgumentException( string.Format("Value '{0}' must be greater than or equal to 0.", value));
#endif
				
				largeChange = value;				
			}
		}

		[DefaultValue (10)]
		[RefreshProperties (RefreshProperties.All)]		
		public int Maximum {
			get { return maximum; }
			set {
				if (maximum != value)  {
					maximum = value;

					if (maximum < minimum)
						minimum = maximum;

					Refresh ();
				}
			}
		}

		[DefaultValue (0)]
		[RefreshProperties (RefreshProperties.All)]		
		public int Minimum {
			get { return minimum; }
			set {

				if (Minimum != value) {
					minimum = value;

					if (minimum > maximum)
						maximum = minimum;

					Refresh ();
				}
			}
		}

		[DefaultValue (Orientation.Horizontal)]
		[Localizable (true)]
		public Orientation Orientation {
			get { return orientation; }
			set {
				if (!Enum.IsDefined (typeof (Orientation), value))
					throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for Orientation", value));

				/* Orientation can be changed once the control has been created */
				if (orientation != value) {
					orientation = value;
					
					if (this.IsHandleCreated) {
						Size = new Size (Height, Width);
						Refresh (); 
					}
				}
			}
		}

#if NET_2_0
		[Browsable (false)]
		[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
		[EditorBrowsable (EditorBrowsableState.Never)]
		public new Padding Padding {
			get {
				return base.Padding;
			}
			set {
				base.Padding = value;
			}
		}
		
		[Localizable (true)]
		[DefaultValue (false)]
		public virtual bool RightToLeftLayout {
			get {
				return right_to_left_layout;
			}
			set {
				if (value != right_to_left_layout) {
					right_to_left_layout = value;
					OnRightToLeftLayoutChanged (EventArgs.Empty);
				}
			}
		}
#endif

		[DefaultValue (1)]
		public int SmallChange {
			get { return smallChange;}
			set {
#if NET_2_0
				if (value < 0)
					throw new ArgumentOutOfRangeException (string.Format ("Value '{0}' must be greater than or equal to 0.", value));
#else
				if ( value < 0 )
					throw new ArgumentException( string.Format("Value '{0}' must be greater than or equal to 0.", value));
#endif
				if (smallChange != value) {
					smallChange = value;					
				}
			}
		}

		[EditorBrowsable (EditorBrowsableState.Never)]
		[Bindable (false)]
		[Browsable (false)]
		public override string Text {
			get {	return base.Text; }			
			set { base.Text = value; }
		}

		[DefaultValue (1)]
		public int TickFrequency {
			get { return tickFrequency; }
			set {
				if ( value > 0 ) {
					tickFrequency = value;
					Refresh ();
				}
			}
		}

		[DefaultValue (TickStyle.BottomRight)]
		public TickStyle TickStyle {
			get { return tickStyle; }
			set { 				
				if (!Enum.IsDefined (typeof (TickStyle), value))
					throw new InvalidEnumArgumentException (string.Format("Enum argument value '{0}' is not valid for TickStyle", value));
				
				if (tickStyle != value) {
					tickStyle = value;
					Refresh ();
				}
			}
		}
		
		[DefaultValue (0)]
		[Bindable (true)]
		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;					

					// XXX any reason we don't call OnValueChanged here?
					EventHandler eh = (EventHandler)(Events [ValueChangedEvent]);
					if (eh != null)
						eh (this, EventArgs.Empty);

					Invalidate (thumb_area);
				}				
			}
		}

		#endregion //Public Properties

		#region Public Methods

		public void BeginInit ()		
		{

		}

		protected override void CreateHandle ()
		{
			base.CreateHandle ();
		}

		protected override void SetBoundsCore (int x, int y,int width, int height, BoundsSpecified specified)
		{
			if (AutoSize) {
				if (orientation == Orientation.Vertical) {
					width = size_of_autosize;
				} else {
					height = size_of_autosize;
				}
			}
			base.SetBoundsCore (x, y, width, height, specified);
		}

		public void EndInit ()		
		{

		}

		protected override bool IsInputKey (Keys keyData)
		{
			if ((keyData & Keys.Alt) == 0) {
				switch (keyData & Keys.KeyCode) {
				case Keys.Down:
				case Keys.Right:
				case Keys.Up:
				case Keys.Left:
				case Keys.PageUp:
				case Keys.PageDown:
				case Keys.Home:
				case Keys.End:
					return true;
				}
			}
			return base.IsInputKey (keyData);
		}

		protected override void OnBackColorChanged (EventArgs e)
		{
			base.OnBackColorChanged (e);
		}

		protected override void OnHandleCreated (EventArgs e)
		{	
			base.OnHandleCreated (e);
					
			if (AutoSize)
				if (Orientation == Orientation.Horizontal)
					Size = new Size (Width, 40);
				else
					Size = new Size (50, Height);
			
			UpdatePos (Value, true);			
		}
	
		[EditorBrowsable (EditorBrowsableState.Advanced)]
		protected override void OnMouseWheel (MouseEventArgs e)
		{
			base.OnMouseWheel (e);
			
			if (!Enabled) return;
    			
			if (e.Delta > 0)
				SmallDecrement ();
			else
				SmallIncrement ();    					
		}

#if NET_2_0
		[EditorBrowsable (EditorBrowsableState.Advanced)]
		protected virtual void OnRightToLeftLayoutChanged (EventArgs e)
		{
			EventHandler eh = (EventHandler)Events [RightToLeftLayoutChangedEvent];
			if (eh != null)
				eh (this, e);
		}
#endif

		protected virtual void OnScroll (EventArgs e) 
		{
			EventHandler eh = (EventHandler)(Events [ScrollEvent]);
			if (eh != null)
				eh (this, e);
		}

#if NET_2_0
		protected override void OnSystemColorsChanged (EventArgs e)
		{
			base.OnSystemColorsChanged (e);
			Invalidate ();
		}
#endif
		protected virtual void OnValueChanged (EventArgs e) 
		{
			EventHandler eh = (EventHandler)(Events [ValueChangedEvent]);
			if (eh != null)
				eh (this, e);
		}

		public void SetRange (int minValue, int maxValue)
		{
			Minimum = minValue;
			Maximum = maxValue;			
		}

		public override string ToString()
		{
			return string.Format("System.Windows.Forms.TrackBar, Minimum: {0}, Maximum: {1}, Value: {2}",
						Minimum, Maximum, Value);
		}
							

		protected override void WndProc (ref Message m)
    		{
			base.WndProc (ref m);

			// Basically we want ControlStyles.ResizeRedraw but
			// tests say we can't set that flag
			if ((Msg)m.Msg == Msg.WM_WINDOWPOSCHANGED && Visible)
				Invalidate ();
    		}
    		
		#endregion Public Methods

		#region Private Methods
		
		private void UpdatePos (int newPos, bool update_trumbpos)
		{
			if (newPos < minimum){
				Value = minimum;
			}
			else {
				if (newPos > maximum) {
					Value = maximum;
				}
				else {
					Value = newPos;
				}
			}
		}
		
		private void LargeIncrement ()
    		{    			
			UpdatePos (position + LargeChange, true);
			Invalidate (thumb_area);
			OnScroll (new EventArgs ());
    		}

    		private void LargeDecrement ()
    		{
			UpdatePos (position - LargeChange, true);
			Invalidate (thumb_area);
			OnScroll (new EventArgs ());
    		}

		private void SmallIncrement ()
    		{    			
			UpdatePos (position + SmallChange, true);
			Invalidate (thumb_area);
			OnScroll (new EventArgs ());
    		}

    		private void SmallDecrement ()
    		{
			UpdatePos (position - SmallChange, true);
			Invalidate (thumb_area);
			OnScroll (new EventArgs ());	
    		}
    		
		private void OnMouseUpTB (object sender, MouseEventArgs e)
		{	
			if (!Enabled) return;			

			if (thumb_pressed == true || mouse_clickmove == true) {	
				thumb_pressed = false;
				holdclick_timer.Enabled = false;
				this.Capture = false;
				Invalidate (thumb_area);
			}
		}

		private void OnMouseDownTB (object sender, MouseEventArgs e)
    		{
    			if (!Enabled) return;			    			

			mouse_moved = false;

			bool fire_timer = false;
    			
    			Point point = new Point (e.X, e.Y);

			if (orientation == Orientation.Horizontal) {
				
				if (thumb_pos.Contains (point)) {
					this.Capture = true;
					thumb_pressed = true;
					thumb_mouseclick = e.X;
					mouse_down_x_offset = e.X - thumb_pos.X;
					Invalidate (thumb_area);
				}
				else {
					if (thumb_area.Contains (point)) {
						is_moving_right = e.X > thumb_pos.X + thumb_pos.Width; 
						if (is_moving_right)
							LargeIncrement ();
						else
							LargeDecrement ();

						Invalidate (thumb_area);
						fire_timer = true;
						mouse_clickmove = true;
					}
				}
			}
			else {
				Rectangle vertical_thumb_pos = thumb_pos;
				vertical_thumb_pos.Width = thumb_pos.Height;
				vertical_thumb_pos.Height = thumb_pos.Width;
				if (vertical_thumb_pos.Contains (point)) {
					this.Capture = true;
					thumb_pressed = true;
					thumb_mouseclick = e.Y;
					mouse_down_x_offset = e.Y - thumb_pos.Y;
					Invalidate (thumb_area);
				}
				else {
					if (thumb_area.Contains (point)) {
						is_moving_right = e.Y > thumb_pos.Y + thumb_pos.Width;
						if (is_moving_right)
							LargeDecrement ();
						else
							LargeIncrement ();

						Invalidate (thumb_area);
						fire_timer = true;
						mouse_clickmove = true;
					}
				}
			}

			if (fire_timer) { 				
				holdclick_timer.Interval = 300;
				holdclick_timer.Enabled = true;				
			}			
    		}

    		private void OnMouseMoveTB (object sender, MouseEventArgs e)
    		{    			
    			if (!Enabled) return;
    		
    			mouse_moved = true;

    			/* Moving the thumb */
    			if (thumb_pressed) {
    				int old_value = Value;
				Value = ThemeEngine.Current.TrackBarValueFromMousePosition (e.X, e.Y, this);			
    				
    				if (Value != old_value)
    					OnScroll (EventArgs.Empty);
			}
			ThumbEntered = GetRealThumbRectangle ().Contains (e.Location);
    		}

		Rectangle GetRealThumbRectangle ()
		{
			Rectangle result = thumb_pos;
			if (Orientation == Orientation.Vertical) {
				result.Width = thumb_pos.Height;
				result.Height = thumb_pos.Width;
			}
			return result;
		}

		internal override void OnPaintInternal (PaintEventArgs pevent)
		{		
			ThemeEngine.Current.DrawTrackBar (pevent.Graphics, pevent.ClipRectangle, this);
		}

		private void OnLostFocusTB (object sender, EventArgs e)
		{
			Invalidate();
		}

		private void OnGotFocusTB (object sender, EventArgs e)
		{
			Invalidate();
		}
		private void OnKeyDownTB (object sender, KeyEventArgs e) 
		{
			bool horiz = Orientation == Orientation.Horizontal;
			switch (e.KeyCode) {
			
			case Keys.Down:
			case Keys.Right:
				if(horiz)
					SmallIncrement();
				else
					SmallDecrement ();
				break;

			case Keys.Up:
			case Keys.Left:
				if (horiz)
					SmallDecrement();
				else
					SmallIncrement();
				break;

			case Keys.PageUp:
				if (horiz)
					LargeDecrement();
				else
					LargeIncrement();
				break;

			case Keys.PageDown:
				if (horiz)
					LargeIncrement();
				else
					LargeDecrement();
				break;

			case Keys.Home:
				if (horiz)
					Value = Minimum;
				else
					Value = Maximum;
				break;

			case Keys.End:
				if (horiz)
					Value = Maximum;
				else
					Value = Minimum;
				break;

			default:
				break;
			}
		}

		private void OnFirstClickTimer (Object source, ElapsedEventArgs e)
		{						
			Point pnt;
			pnt = PointToClient (MousePosition);			
			/*
				On Win32 the thumb only moves in one direction after a click, 
				if the thumb passes the clicked point it will never go in the 
				other way unless the mouse is released and clicked again. This
				is also true if the mouse moves while beeing hold down.
			*/
		
			if (thumb_area.Contains (pnt)) 	{
				bool invalidate = false;
				if (orientation == Orientation.Horizontal) {
					if (pnt.X > thumb_pos.X + thumb_pos.Width && is_moving_right) {
						LargeIncrement ();
						invalidate = true;
					} else if (pnt.X < thumb_pos.X && !is_moving_right) {
						LargeDecrement ();			
						invalidate = true;
					}					
				} else {
					if (pnt.Y > thumb_pos.Y + thumb_pos.Width && is_moving_right) {
						LargeDecrement ();		
						invalidate = true;
					} else if (pnt.Y < thumb_pos.Y && !is_moving_right) {
						LargeIncrement ();		
						invalidate = true;
					}
 				}
 				if (invalidate)
 					// A Refresh is necessary because the mouse is down and if we just invalidate
 					// we'll only get paint events once in a while.
 					Refresh();
			}			
		}					

		void OnMouseLeave (object sender, EventArgs e)
		{
			ThumbEntered = false;
		}
    		#endregion // Private Methods
	}
}

