--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
]]