local PANEL = {}



AccessorFunc( PANEL, "m_DNDName", 			"DnD" )

AccessorFunc( PANEL, "m_bLiveDrag", 		"UseLiveDrag" )



--[[---------------------------------------------------------

   Name: Init

-----------------------------------------------------------]]

function PANEL:Init()



	self:SetPaintBackgroundEnabled( false )

	self:SetPaintBorderEnabled( false )

	self:SetMouseInputEnabled( true )

	self:SetDrawBackground( false )

	

	self:SetDropPos( "5" )

	

end



--

-- Determines where we can drop stuff - relative to the other children

-- Param is a string of numpad numbers, ie "852" is top middle bottom

--

function PANEL:SetDropPos( strPos )



	self.bDropLeft		= string.find( strPos, "4" )

	self.bDropCenter	= string.find( strPos, "5" )

	self.bDropRight		= string.find( strPos, "6" )

	self.bDropTop		= string.find( strPos, "8" )

	self.bDropBottom	= string.find( strPos, "2" )



end



function PANEL:MakeDroppable( name, bAllowCopy )



	self:SetDnD( name )

	

	if ( bAllowCopy ) then 

		self:Receiver( name, self.DropAction_Copy, { copy = "Copy", move = "Move" } )  

	else

		self:Receiver( name, self.DropAction_Normal )

	end		



end



function PANEL:DropAction_Copy( Drops, bDoDrop, Command, x, y )



	if ( Command && Command == "copy" ) then

	

		for k, v in pairs( Drops ) do

		

			if ( v.Copy ) then

				Drops[k] = v:Copy()

			end

			

		end

	

	end

	

	self:DropAction_Normal( Drops, bDoDrop, Command, x, y )



end



function PANEL:DropAction_Simple( Drops, bDoDrop, Command, x, y )



	self:SetDropTarget( 0, 0, self:GetWide(), 2 )

	

	if ( bDoDrop ) then 

	

		for k, v in pairs( Drops ) do

		

			v = v:OnDrop( self )

			v:SetParent( self ) 

			

		end

		

		self:OnModified()

		

	end



end







function PANEL:DropAction_Normal( Drops, bDoDrop, Command, x, y )



	local closest = self:GetClosestChild( x, y )

	if ( !IsValid( closest ) ) then

		return self:DropAction_Simple( Drops, bDoDrop, Command, x, y )		

	end

	

	local h = closest:GetTall()

	local w = closest:GetWide()

	

	local disty = y - ( closest.y + h * 0.5 )

	local distx = x - ( closest.x + w * 0.5 )

	

	local drop = 0

	if ( self.bDropCenter ) then drop = 5 end

	

	if ( disty < 0 && self.bDropTop && ( drop == 0 || math.abs( disty ) > h * 0.1 ) ) then drop = 8 end

	if ( disty >= 0 && self.bDropBottom && ( drop == 0 || math.abs( disty ) > h * 0.1 ) ) then drop = 2 end

	if ( distx < 0 && self.bDropLeft && ( drop == 0 || math.abs( distx ) > w * 0.1 ) ) then drop = 4 end

	if ( distx >= 0 && self.bDropRight && ( drop == 0 || math.abs( distx ) > w * 0.1 ) ) then drop = 6 end

	

	self:UpdateDropTarget( drop, closest )

	

	if ( table.HasValue( Drops, closest ) ) then return end

	

	if ( !bDoDrop && !self:GetUseLiveDrag() ) then return end

	

	-- This keeps the drop order the same, 

	-- whether we add it before an object or after

	if ( drop == 6 || drop == 2 ) then

		Drops = table.Reverse( Drops )

	end

	

	for k, v in pairs( Drops ) do

		

		-- Don't drop one of our parents onto us

		-- because we'll be sucked into a vortex

		if ( v:IsOurChild( self ) ) then continue end

		

		v = v:OnDrop( self )

	

		if ( drop == 5 ) then

			closest:DroppedOn( v )

		end

		

		if ( drop == 8 || drop == 4 ) then

			v:SetParent( self )

			v:MoveToBefore( closest )

		end

		

		if ( drop == 2 || drop == 6 ) then

			v:SetParent( self )

			v:MoveToAfter( closest )

		end

	

	end

	

	self:OnModified()



end



function PANEL:UpdateDropTarget( drop, pnl )



	if ( drop == 5 ) then

		return self:SetDropTarget( pnl.x, pnl.y, pnl:GetWide(), pnl:GetTall() )

	end

	

	if ( drop == 8 ) then

		return self:SetDropTarget( pnl.x, pnl.y-2, pnl:GetWide(), 4 )

	end

	

	if ( drop == 2 ) then

		return self:SetDropTarget( pnl.x, pnl.y+pnl:GetTall()-2, pnl:GetWide(), 4 )

	end

	

	if ( drop == 4 ) then

		return self:SetDropTarget( pnl.x-2, pnl.y-2, 4, pnl:GetTall() )

	end

	

	if ( drop == 6 ) then

		return self:SetDropTarget( pnl.x + pnl:GetWide() - 2, pnl.y, 4, pnl:GetTall() )

	end

	

	// Unhandled!	

	// self:ClearDropTarget()



end





derma.DefineControl( "DDragBase", "", PANEL, "DPanel" )

