/*   _                                
    ( )                               
   _| |   __   _ __   ___ ___     _ _ 
 /'_` | /'__`\( '__)/' _ ` _ `\ /'_` )
( (_| |(  ___/| |   | ( ) ( ) |( (_| |
`\__,_)`\____)(_)   (_) (_) (_)`\__,_) 

	DVScrollBar

	
	Usage:
	
	Place this control in your panel. You will ideally have another panel or 
		control which is bigger than the original panel. This is the Canvas.
	
	scrollbar:SetUp( _barsize_, _canvassize_ ) should be called whenever
		the size of your 'canvas' changes.
		
	scrollbar:GetOffset() can be called to get the offset of the canvas.
		You should call this in your PerformLayout function and set the Y 
		pos of your canvas to this value.
		
	Example:
	

	function PANEL:PerformLayout()
	
		local Wide = self:GetWide()
		local YPos = 0
		
		// Place the scrollbar
		self.VBar:SetPos( self:GetWide() - 16, 0 )
		self.VBar:SetSize( 16, self:GetTall() )
		
		// Make sure the scrollbar knows how big our canvas is
		self.VBar:SetUp( self:GetTall(), self.pnlCanvas:GetTall() )
		
		// Get data from the scrollbar
		YPos = self.VBar:GetOffset()
		
		// If the scrollbar is enabled make the canvas thinner so it will fit in.
		if ( self.VBar.Enabled ) then Wide = Wide - 16 end
			
		// Position the canvas according to the scrollbar's data
		self.pnlCanvas:SetPos( self.Padding, YPos + self.Padding )
		self.pnlCanvas:SetSize( Wide - self.Padding * 2, self.pnlCanvas:GetTall() )
	
	end

	
*/

local derma_smoothscroll = CreateClientConVar( "derma_smoothscroll", 
												"1", 
												true /*Should Save*/, 
												false /*Accessible by server*/ )

local PANEL = {}

/*---------------------------------------------------------
   Name: Init
---------------------------------------------------------*/
function PANEL:Init()

	self:SetEnabled( true )
	self.Offset = 0
	self.Scroll = 0
	self.CanvasSize = 1
	self.BarSize = 1	
	
	self.btnUp = vgui.Create( "DSysButton", self )
	self.btnUp:SetType( "up" )
	self.btnUp.DoClick = function ( self ) self:GetParent():AddScroll( -1 ) end
	
	self.btnDown = vgui.Create( "DSysButton", self )
	self.btnDown:SetType( "down" )
	self.btnDown.DoClick = function ( self ) self:GetParent():AddScroll( 1 ) end
	
	self.btnGrip = vgui.Create( "DScrollBarGrip", self )

end

/*---------------------------------------------------------
   Name: SetEnabled
---------------------------------------------------------*/
function PANEL:SetEnabled( b )
	
	self.Enabled = b	

	if ( !b ) then
	
		self.Offset = 0
		self:SetScroll( 0 )
		self.HasChanged = true
		
	end
	
	self:SetMouseInputEnabled( b )
	self:SetVisible( b )
	
end


/*---------------------------------------------------------
   Name: Value
---------------------------------------------------------*/
function PANEL:Value()

	return self.Pos
	
end

/*---------------------------------------------------------
   Name: Value
---------------------------------------------------------*/
function PANEL:BarScale()

	if ( self.BarSize == 0 ) then return 1 end

	return self.BarSize / self.CanvasSize
	
end

/*---------------------------------------------------------
   Name: SetPos
---------------------------------------------------------*/
function PANEL:SetUp( _barsize_, _canvassize_ )

	self.BarSize 	= _barsize_
	self.CanvasSize = _canvassize_

	self:SetEnabled( self:BarScale() < 0.98 )
	
	self:InvalidateLayout()
		
end

/*---------------------------------------------------------
   Name: OnMouseWheeled
---------------------------------------------------------*/
function PANEL:OnMouseWheeled( dlta )

	self:AddScroll( dlta * -2 )
	return true
	
end

/*---------------------------------------------------------
   Name: AddScroll
---------------------------------------------------------*/
function PANEL:AddScroll( dlta )

	dlta = dlta * self:BarScale() * 0.1
	self:SetScroll(  self:GetScroll() + dlta )
	
end

/*---------------------------------------------------------
   Name: SetScroll
---------------------------------------------------------*/
function PANEL:SetScroll( scrll )

	if ( !self.Enabled ) then self.Scroll = 0 return end
	self.Scroll = math.Clamp( scrll, 0, 1 )
	
	self:InvalidateLayout()
	self:GetParent():InvalidateLayout()
	
end

/*---------------------------------------------------------
   Name: SetScroll
---------------------------------------------------------*/
function PANEL:GetScroll()

	if ( !self.Enabled ) then self.Scroll = 0 end
	return self.Scroll
	
end

/*---------------------------------------------------------
   Name: GetOffset
---------------------------------------------------------*/
function PANEL:GetOffset()

	return self.Offset
	
end

/*---------------------------------------------------------
   Name: Think
---------------------------------------------------------*/
function PANEL:Think()

	local TargetOffset = self:GetScroll() * (self.CanvasSize - self.BarSize) * -1
	
	if ( TargetOffset != self.Offset ) then
	
		local Steps = derma_smoothscroll:GetInt()
	
		self.Offset = (TargetOffset + self.Offset * Steps) / ( Steps + 1 )
		self:GetParent():InvalidateLayout()
		
	end
	
end


/*---------------------------------------------------------
   Name: Paint
---------------------------------------------------------*/
function PANEL:Paint()
	
	derma.SkinHook( "Paint", "VScrollBar", self )
	return true
	
end

/*---------------------------------------------------------
   Name: OnMouseReleased
---------------------------------------------------------*/
function PANEL:OnMousePressed()

	local x, y = self:CursorPos()
	y = y / self:GetTall()
	
	local PageSize = self.BarSize / (self.CanvasSize - self.BarSize)
	
	if ( y > self:GetScroll() ) then
		self:SetScroll( self:GetScroll() + PageSize )
	else
		self:SetScroll( self:GetScroll() - PageSize )
	end	
	
end

/*---------------------------------------------------------
   Name: OnMouseReleased
---------------------------------------------------------*/
function PANEL:OnMouseReleased()

	self.Dragging = false
	self:MouseCapture( false )
	
end

/*---------------------------------------------------------
   Name: OnCursorMoved
---------------------------------------------------------*/
function PANEL:OnCursorMoved( x, y )

	if ( !self.Enabled ) then return end
	if ( !self.Dragging ) then return end
	
	local ToOffset = ( self.CanvasSize - self.BarSize )
	if ( ToOffset == 0 ) then return end
	
	local Delta = (gui.MouseY() - self.StartDraggingPos) / ToOffset
	Delta = Delta * self.DragDirection
	
	self:SetScroll( self:GetScroll() + Delta )
	
	self.StartDraggingPos = gui.MouseY()
	
end

/*---------------------------------------------------------
   Name: Grip
---------------------------------------------------------*/
function PANEL:Grip( direction )

	if ( !self.Enabled ) then return end
	if ( self.BarSize == 0 ) then return end

	self:MouseCapture( true )
	
	if ( direction ) then
		self.DragDirection = self.CanvasSize / self.BarSize
	else
		self.DragDirection = -1
	end

	self.Dragging = 1
	
	self.StartDraggingPos = gui.MouseY()
	
end


/*---------------------------------------------------------
	PerformLayout
---------------------------------------------------------*/
function PANEL:PerformLayout()

	derma.SkinHook( "Layout", "VScrollBar", self )

end


derma.DefineControl( "DVScrollBar", "A Scrollbar", PANEL, "Panel" )