diff --git a/example/kenneyblue.gui_script b/example/kenneyblue.gui_script index 9c769b1..8444f51 100644 --- a/example/kenneyblue.gui_script +++ b/example/kenneyblue.gui_script @@ -111,6 +111,8 @@ function init(self) kenneyblue.input("input", gui.KEYBOARD_TYPE_DEFAULT, nil, nil, { empty_text = "EMPTY, MAX 8 CHARS" }) kenneyblue.static_list("staticlist", "staticscrollbar", self.list_ids) kenneyblue.dynamic_list("dynamiclist", "dynamicscrollbar", self.list_data) + kenneyblue.scrollbar("staticscrollbar") + kenneyblue.scrollbar("dynamicscrollbar") end function on_input(self, action_id, action) @@ -146,7 +148,7 @@ function on_input(self, action_id, action) kenneyblue.button("remove", action_id, action, function(button) table.remove(self.list_data) end) - + kenneyblue.static_list("staticlist", "staticscrollbar", self.list_ids, action_id, action, function(list) print("selected list item", list.selected_item) end) diff --git a/gooey/internal/list.lua b/gooey/internal/list.lua index f9b264d..bf266f6 100644 --- a/gooey/internal/list.lua +++ b/gooey/internal/list.lua @@ -53,7 +53,7 @@ function LIST.scroll_to(list, x, y) list.consumed = true list.scrolling = true list.scroll_pos.y = list.min_y + (list.max_y - list.min_y) * y - list.scroll.y = 1 - y + list.scroll.y = y if list.static then update_static_listitems(list.items, vmath.vector3(list.scroll_pos)) elseif list.dynamic then @@ -69,7 +69,7 @@ local function get_instance(list_id, stencil_id, refresh_fn, lists) local list = core.instance(stencil_id, lists, LIST) list.id = list_id list.scroll = list.scroll or vmath.vector3(1) - list.stencil = list.stencil or gui.get_node(stencil_id) + list.stencil = list.stencil or gui.get_node(stencil_id) list.stencil_size = list.stencil_size or gui.get_size(list.stencil) list.refresh_fn = refresh_fn list.enabled = core.is_enabled(list.stencil) @@ -94,7 +94,7 @@ local function handle_input(list, action_id, action, click_fn) list.pressed = false end list.consumed = false - + -- handle mouse-wheel scrolling if over_stencil and (scroll_up or scroll_down) then list.consumed = true @@ -125,7 +125,7 @@ local function handle_input(list, action_id, action, click_fn) if list.scrolling then list.scroll_pos.y = math.min(list.scroll_pos.y, list.max_y) list.scroll_pos.y = math.max(list.scroll_pos.y, list.min_y) - list.scroll.y = 1 - (list.scroll_pos.y / list.max_y) + list.scroll.y = (list.scroll_pos.y / list.max_y) end -- find which item (if any) that the touch event is over @@ -136,7 +136,7 @@ local function handle_input(list, action_id, action, click_fn) list.consumed = true over_item = item.index break - end + end end -- handle list item over state @@ -185,11 +185,11 @@ function M.static(list_id, stencil_id, item_ids, action_id, action, fn, refresh_ gui.set_parent(node, list.stencil) end update_static_listitems(list.items, vmath.vector3(0)) - + local last_item = list.items[#list.items].root local total_height = last_item and (math.abs(gui.get_position(last_item).y) + gui.get_size(last_item).y / 2) or 0 local list_height = gui.get_size(list.stencil).y - + list.scroll_pos = vmath.vector3(0) list.min_y = 0 list.max_y = total_height - list_height @@ -204,10 +204,10 @@ function M.static(list_id, stencil_id, item_ids, action_id, action, fn, refresh_ if refresh_fn then refresh_fn(list) end return list end - + if list.enabled then handle_input(list, action_id, action, fn) - + -- re-position the list items if we're scrolling if list.scrolling then update_static_listitems(list.items, vmath.vector3(list.scroll_pos)) @@ -235,7 +235,7 @@ function M.dynamic(list_id, stencil_id, item_id, data, action_id, action, fn, re list.scroll_pos = vmath.vector3(0) list.first_item_pos = vmath.vector3(item_pos) list.data_size = nil - + local item_count = math.ceil(list.stencil_size.y / item_size.y) + 1 for i=1,item_count do local nodes = gui.clone_tree(item_node) @@ -256,7 +256,7 @@ function M.dynamic(list_id, stencil_id, item_id, data, action_id, action, fn, re -- deselect and realign items local data_size_changed = list.data_size ~= #data if not list.data_size or data_size_changed then - list.data_size = #data + list.data_size = #data list.min_y = 0 list.max_y = (#data * list.item_size.y) - list.stencil_size.y list.selected_item = nil @@ -284,7 +284,7 @@ function M.dynamic(list_id, stencil_id, item_id, data, action_id, action, fn, re end end end - + -- bail early if the list is empty if list.data_size == 0 then if refresh_fn then refresh_fn(list) end @@ -299,7 +299,7 @@ function M.dynamic(list_id, stencil_id, item_id, data, action_id, action, fn, re update_dynamic_listitem_positions(list) end end - + update_dynamic_listitem_data(list, data) if refresh_fn then refresh_fn(list) end @@ -313,4 +313,4 @@ setmetatable(M, { end }) -return M \ No newline at end of file +return M diff --git a/gooey/internal/scrollbar.lua b/gooey/internal/scrollbar.lua index 65de820..887965d 100644 --- a/gooey/internal/scrollbar.lua +++ b/gooey/internal/scrollbar.lua @@ -18,10 +18,17 @@ function SCROLLBAR.scroll_to(scrollbar, x, y) x = core.clamp(x, 0, 1) y = core.clamp(y, 0, 1) - handle_pos.x = x * scrollbar.bounds_size.x - handle_pos.y = y * scrollbar.bounds_size.y + if scrollbar.vertical then + local adjusted_height = (scrollbar.bounds_size.y - scrollbar.handle_size.y) + local offset_y = scrollbar.vertical and (scrollbar.handle_size.y / 2) or 0 + handle_pos.y = offset_y + adjusted_height - y * adjusted_height + else + local adjusted_width = (scrollbar.bounds_size.x - scrollbar.handle_size.x) + local offset_x = scrollbar.vertical and 0 or (scrollbar.handle_size.x / 2) + handle_pos.x = offset_x + adjusted_width - x * adjusted_width + end gui.set_position(scrollbar.node, handle_pos) - scrollbar.scroll.y = 1 - y + scrollbar.scroll.y = y end function SCROLLBAR.set_visible(button, visible) gui.set_enabled(scrollbar.node, visible) @@ -36,15 +43,18 @@ function M.vertical(handle_id, bounds_id, action_id, action, fn, refresh_fn) assert(handle) assert(bounds) local scrollbar = core.instance(handle_id, scrollbars, SCROLLBAR) - scrollbar.scroll = scrollbar.scroll or vmath.vector3() + scrollbar.scroll = scrollbar.scroll or vmath.vector3(0, 0, 0) + scrollbar.vertical = true + local handle_size = gui.get_size(handle) local bounds_size = gui.get_size(bounds) - + scrollbar.enabled = core.is_enabled(handle) scrollbar.node = handle scrollbar.bounds = bounds scrollbar.bounds_size = bounds_size - + scrollbar.handle_size = handle_size + if action then scrollbar.refresh_fn = refresh_fn @@ -53,11 +63,13 @@ function M.vertical(handle_id, bounds_id, action_id, action, fn, refresh_fn) core.clickable(scrollbar, action_id, action) if scrollbar.pressed_now or scrollbar.pressed then local bounds_pos = core.get_root_position(bounds) - local ratio = (action_pos.y - bounds_pos.y) / bounds_size.y + local size = bounds_size.y - handle_size.y + local ratio = (size - (action_pos.y - bounds_pos.y - (scrollbar.handle_size.y / 2))) / size SCROLLBAR.scroll_to(scrollbar, 0, ratio) - action.scroll_y = scrollbar.scroll.y fn(scrollbar) end + else + SCROLLBAR.scroll_to(scrollbar, 0, scrollbar.scroll.y) end scrollbar.refresh() @@ -70,4 +82,4 @@ setmetatable(M, { end }) -return M \ No newline at end of file +return M diff --git a/gooey/themes/kenneyblue/kenneyblue.lua b/gooey/themes/kenneyblue/kenneyblue.lua index d443d86..ac3f881 100644 --- a/gooey/themes/kenneyblue/kenneyblue.lua +++ b/gooey/themes/kenneyblue/kenneyblue.lua @@ -176,5 +176,8 @@ function M.dynamic_list(list_id, scrollbar_id, data, action_id, action, fn) return list end +function M.scrollbar(scrollbar_id, action_id, action, fn) + return gooey.vertical_scrollbar(scrollbar_id .. "/handle", scrollbar_id .. "/bounds") +end return M