--NEXT: Figure out scroll direction in smooth_nav() 
 
 
 
 
 
Vdo_scrollbox_threads = {}  
Vdo_scrollbox_thread_count = 0 
 
 
 
VDO_SCROLLBOX_BAR_SPACING = 5 
 
VDO_SCROLLBOX_DURATION					= 0.05		--TODO: OUTLINE THESE NUMBERS... 
 
VDO_SCROLLBOX_DURATION_PIXEL_RATE	= 20 
 
 
 
-- Inherited from Vdo_base_object 
 
Vdo_scrollbox = Vdo_base_object:new_base() 
 
 
 
function vdo_scrollbox_init() 
 
	debug_print("vint", "Vdo_scrollbox:init()\n")	  
end 
 
 
 
function vdo_scrollbox_cleanup() 
 
end 
 
 
 
 
 
function Vdo_scrollbox:init() 
 
	--Create references to all the objects.... 
 
	self.scroll_box_h				= vint_object_find("scroll_box", self.handle, self.doc_handle)  
	self.clip_h						= vint_object_find("clip", self.handle, self.doc_handle)  
	self.scroll_item_h			= vint_object_find("scroll_item", self.handle, self.doc_handle)  
	self.text_h						= vint_object_find("scroll_text", self.handle, self.doc_handle)  
	self.scrollbar					= Vdo_scrollbar:new("scrollbar", self.handle, self.doc_handle)  
	self.scroll_anim_h			= vint_object_find("scroll_anim", self.handle, self.doc_handle)  
	self.main_scroll_twn_h		= vint_object_find("main_scroll_twn", self.handle, self.doc_handle)  
	 
 
	--Callback string... 
 
	local callback_string = self:package_tween_callback("scroll_finished")  
	vint_set_property(self.main_scroll_twn_h, "end_event", callback_string) 
 
	vint_set_property(self.main_scroll_twn_h, "target_handle", self.scroll_item_h) 
 
	 
 
	--scrolling defaults 
 
	self.scroll_thread = 0 
 
	self:set_size(400, 200) 
 
	self.content_height = 0 
 
	self.content_width = 0 
 
	self.scroll_direction = 0 
 
	 
 
end 
 
 
 
function vdo_scrollbox_thread(awesome) 
 
 
 
end 
 
 
 
--Events need to be registered on the main screen and sent through this function... 
 
function Vdo_scrollbox:nav_smooth(value) 
 
	-- First check if the stick is pointed in any direction 
 
	debug_print("vint", "nav_smooth(value): " .. value .. "\n")  
	 
 
	-- No scrolling if we dont needs to. 
 
	if self.clip_height > self.content_height then 
 
		-- Kill the thread if it exists, and reset the scrollbar 
 
		if self.scroll_thread ~= 0 then 
 
			thread_kill(self.scroll_thread) 
 
			self.scroll_thread = 0 
 
		end 
 
		return 
 
	end 
 
	 
 
	if abs(value) < 0.5 then 
 
		-- Stop scrolling if it's not 
 
		if self.scroll_direction ~= 0 then 
 
			 
 
			-- Kill the thread for scrolling 
 
			if self.scroll_thread ~= 0 then 
 
				thread_kill(self.scroll_thread) 
 
				self.scroll_thread = 0 
 
			end 
 
 
 
			-- Pause the animation 
 
			vint_set_property(self.scroll_anim_h, "is_paused", true) 
 
			self.scroll_direction = 0 
 
			self:scrollbar_set() 
 
		end 
 
	else 
 
		-- Just continue tweening if we're still going in the same direction 
 
		if (self.scroll_direction > 0 and value > 0) or 
 
			(self.scroll_direction < 0 and value < 0) then 
 
			return 
 
		elseif self.scroll_direction ~= 0 then 
 
			-- Stop the animation if we're changing direction 
 
			vint_set_property(self.scroll_anim_h, "is_paused", true) 
 
		end 
 
		 
 
		-- Kill the thread if it exists, and reset the scrollbar 
 
		if self.scroll_thread ~= 0 then 
 
			thread_kill(self.scroll_thread) 
 
			self.scroll_thread = 0 
 
			self:scrollbar_set() 
 
		end 
 
		 
 
		-- If the value is negative, we're naving down 
 
		local nav_down = (value < 0) 
 
		local movement = 0 
 
		local pixel_per_duration = 0 
 
 
 
		local x, y = vint_get_property(self.scroll_item_h, "anchor") 
 
		local bottom_y = y + self.clip_height		 
 
 
 
		-- Find the bottom of the text 
 
		local bottom_y = y + self.content_height		 
 
		 
 
		-- Prepare for movement 
 
		if nav_down == false then 
 
			-- Move to the top 
 
			if y < 0 then  
 
				movement = -(y) 
 
			end 
 
		else  
 
			-- Move to the bottom 
 
			movement = -(bottom_y - self.clip_height) 
 
		end 
 
		 
 
		debug_print("vint", "y: " .. y .. "\n")  
		debug_print("vint", "movement: " .. movement .. "\n")  
		debug_print("vint", "self.scroll_item_h: " .. self.scroll_item_h .. "\n")  
		debug_print("vint", "bottom_y: " .. bottom_y .. "\n")  
		debug_print("vint", "self.clip_height: " .. self.clip_height .. "\n")  
		debug_print("vint", "self.content_height: " .. self.content_height .. "\n\n")  
		 
 
		-- If we're going to be moving, then start the tween 
 
		if movement ~= 0 then 
 
			local twn_h = self.main_scroll_twn_h 
 
			 
 
			-- Calculate the duration of the tween, this is the amount of time it should take to scroll from the current position to bottom 
 
			-- This speed should be consistent no matter how much movement is left 
 
			local duration = VDO_SCROLLBOX_DURATION * (abs(movement) / VDO_SCROLLBOX_DURATION_PIXEL_RATE) 
 
			 
 
			-- Create the tween, its told to scroll until it gets all the way to the top or the bottom, but will be killed when the  
 
			-- stick is released 
 
			vint_set_property(twn_h, "duration", duration) 
 
			vint_set_property(twn_h, "start_value", x, y) 
 
			vint_set_property(twn_h, "end_value", x, y + movement) 
 
			lua_play_anim(self.scroll_anim_h, 0)	 
 
 
 
			-- Start the thread for scrolling 
 
			self.scroll_thread = thread_new("vdo_scrollbox_scroll_thread", self)  
			 
 
			-- Store our scroll direction 
 
			if nav_down == true then  
 
				self.scroll_direction = -1 
 
			else  
 
				self.scroll_direction = 1 
 
			end				 
 
		end 
 
	end 
 
end 
 
 
 
function Vdo_scrollbox:scroll_finished() 
 
	-- Reset the start values for the tween when the scroll is no longer occuring 
 
	local twn_h = self.main_scroll_twn_h 
 
	local new_x, new_y = vint_get_property(twn_h, "end_value") 
 
	vint_set_property(twn_h, "start_value", new_x, new_y) 
 
 
 
	-- Kill the thread that runs while the button is held 
 
	if self.scroll_thread ~= 0 then 
 
		thread_kill(self.scroll_thread) 
 
		self.scroll_thread = 0 
 
		self:scrollbar_set() 
 
	end 
 
	 
 
	self.scroll_direction = 0 
 
end 
 
 
 
 
 
function Vdo_scrollbox:on_destroy() 
 
	if self.scroll_thread ~= nil then 
 
		thread_kill(self.scroll_thread) 
 
	end 
 
end 
 
 
 
------------------------------------------------------------------------------- 
 
-- Sets text tag of default element... 
 
-- @param	width		Width of scroll box without scrollbar 
 
-- @param	height	Width of scroll box with scrollbar 
 
function Vdo_scrollbox:set_size(width, height) 
 
	--set size of clip region... 
 
	vint_set_property(self.clip_h, "clip_size", width, height) 
 
	self.clip_width = width 
 
	self.clip_height = height 
 
	 
 
	vint_set_property(self.text_h, "wrap_width", width) 
 
	 
 
	--position scrollbar 
 
	vint_set_property(self.scrollbar.handle, "anchor", width + VDO_SCROLLBOX_BAR_SPACING, 0) 
 
end 
 
 
 
------------------------------------------------------------------------------- 
 
-- Sets text tag of default element... 
 
-- @param	text_tag		text tag to set the element to. 
 
-- 
 
function Vdo_scrollbox:set_text(text_tag) 
 
	--reset position 
 
	vint_set_property(self.scroll_item_h, "anchor", 0, 0) 
 
	 
 
	vint_set_property(self.text_h, "text_tag", text_tag) 
 
	 
 
	self.content_width, self.content_height = element_get_actual_size(self.text_h) 
 
	self.content_height = self.content_height + 4---+ 8 -- padd the box because the text height is deceiving. 
 
	--Determine if we need a scrollbar or not... if our content height is greater than 
 
	if self.clip_height < self.content_height then 
 
		-- Show scrollbar and set its properties... 
 
		self.scrollbar:set_property("visible", true)  
		self.scrollbar:set_size(SCROLLBAR_WIDTH, self.clip_height)		 
 
		self:scrollbar_set() 
 
	else 
 
		-- No scrollbar needed. 
 
		self.scrollbar:set_property("visible", false)	  
	end 
 
end 
 
 
 
------------------------------------------------------------------------------- 
 
-- Resets the scroll bar to current state of our box... 
 
-- 
 
function Vdo_scrollbox:scrollbar_set() 
 
	local x, y = vint_get_property(self.scroll_item_h, "anchor") 
 
	local bottom_y = y + self.content_height 
 
 
 
	-- Create the 'indices' to reference with the scroll bar.. we do this in pixel amoutns 
 
 
 
	-- Our current index is how far the task_bottom is from the entire height of the text 
 
	local index = floor(self.content_height - bottom_y) + 1-- not sure about this +1 
 
	 
 
	-- The max index is the height of the item, minus the visible area of the text 
 
	local max_index = floor(self.content_height - self.clip_height) + 1 
 
	 
 
	if index > max_index then 
 
		index = max_index 
 
	end 
 
	 
 
	self.scrollbar:set_value(max_index, index, true) 
 
end 
 
 
 
function Vdo_scrollbox:reset() 
 
	--Reset  
 
end 
 
 
 
function vdo_scrollbox_scroll_thread(vdo_object) 
 
	while true do 
 
		-- Set the scrollbar position based on where the text currently is (should be tweening) 
 
		vdo_object:scrollbar_set() 
 
		debug_print("vint", "self.scroll_direction".. vdo_object.scroll_direction .. "\n")  
		thread_yield() 
 
	end 
 
end 
 
 
 
function Vdo_scrollbox:set_color(color) 
 
	self.scrollbar:set_highlight_color(color) 
 
end 
 
 
 
--[[ 
 
 
 
--MOVE TO VINTLIB 
 
local Internal_threaded_objects = { }  
 
 
function vint_lua_create_threaded_object(func_name, object) 
 
	local id = thread_new(vint_lua_threaded_object_thread) 
 
	Internal_threaded_objects[id] = { object = object, function_name = func_name }  
	object.internal_thread_handle = id 
 
	return id 
 
end 
 
 
 
function vint_lua_threaded_object_thread() 
 
	thread_yield() 
 
	local object = Internal_threaded_objects[thread_get_handle()] 
 
	 
 
	object.func_name(object.object) 
 
	 
 
	vint_lua_exit_threaded_object() 
 
end 
 
 
 
function test_function(object) 
 
	-- object = thing you want to process 
 
end 
 
 
 
function vint_lua_create_threaded_object(func_name, object) 
 
	local id = thread_new(func_name) 
 
	Internal_threaded_objects[id] = object 
 
	object.internal_thread_handle = id 
 
	return id 
 
end 
 
 
 
function vint_lua_get_threaded_object() 
 
	thread_yield() 
 
	return Internal_threaded_objects[thread_get_handle()] 
 
end 
 
 
 
function vint_lua_get_threaded_object_handle(object) 
 
	if Internal_threaded_objects[object.internal_thread_handle] ~= nil then 
 
		return object.internal_thread_handle 
 
	else  
 
		return nil 
 
	end 
 
end 
 
 
 
function vint_lua_exit_threaded_object() 
 
	local id = thread_get_handle() 
 
	local object = Internal_threaded_objects[id] 
 
	object.internal_thread_handle = nil 
 
	Internal_threaded_objects[id] = nil 
 
end 
 
 
 
function vint_lua_kill_threaded_object(object) 
 
	local thread_handle = object.internal_thread_handle 
 
	thread_kill(thread_handle) 
 
	Internal_threaded_objects[thread_handle] = nil 
 
end 
 
 
 
--Example creating thread object... 
 
function Vdo_scrollbar:create_thread() 
 
	vint_lua_create_threaded_object("test_thread", self)  
end 
 
 
 
--Example killing thread object... 
 
function Vdo_scrollbar:kill_thread() 
 
	vint_lua_kill_threaded_object(self) 
 
end 
 
 
 
 
 
--Example thread... 
 
function test_thread() 
 
	local cur_obj = vint_lua_get_threaded_object() 
 
	 
 
	--Do thread logic in here... 
 
	 
 
	--MUST BE CALLED, or you will have a memory leak(A really bad memory leak.) 
 
	vint_lua_exit_threaded_object() 
 
end 
 
 
 
 
 
 
 
 
 
------------------ 
 
------------------- 
 
------------------ 
 
--Call this to create a new threaded object... 
 
function vint_lua_threaded_object_create(func_name, object) 
 
	local id = thread_new(vint_lua_threaded_object_thread) 
 
	Internal_threaded_objects[id] = { object = object, function_name = func_name }  
	object.vint_lua_internal_thread_handle = id 
 
	return id 
 
end 
 
 
 
-- Use this to get the handle to the  
 
function vint_lua_get_threaded_object_handle(object) 
 
	if Internal_threaded_objects[object.vint_lua_internal_thread_handle] ~= nil then 
 
		return object.vint_lua_internal_thread_handle 
 
	else  
 
		return nil 
 
	end 
 
end 
 
 
 
function vint_lua_kill_threaded_object(object) 
 
	local thread_handle = object.internal_thread_handle 
 
	thread_kill(thread_handle) 
 
	Internal_threaded_objects[thread_handle] = nil 
 
end 
 
 
 
--Internal to vint_lua_threaded_object...() 
 
function vint_lua_threaded_object_thread() 
 
	thread_yield() 
 
	local id = thread_get_handle() 
 
	local object = Internal_threaded_objects[id] 
 
 
 
	object.func_name(object.object) 
 
 
 
	object.internal_thread_handle = nil 
 
	Internal_threaded_objects[id] = nil 
 
end 
 
 
 
--Example creating thread object... 
 
function Vdo_scrollbar:create_thread() 
 
	vint_lua_create_threaded_object("test_thread", self)  
end 
 
 
 
--Example killing thread object... 
 
function Vdo_scrollbar:kill_thread() 
 
	vint_lua_kill_threaded_object(self) 
 
end 
 
 
 
 
 
--Example thread... 
 
--object is your reference.. 
 
function test_thread(object) 
 
	--object... 
 
end 
 
]]