diff --git a/druid/base/static_grid.lua b/druid/base/static_grid.lua index 33bd2c8..f965a14 100644 --- a/druid/base/static_grid.lua +++ b/druid/base/static_grid.lua @@ -159,13 +159,21 @@ end -- @tparam StaticGrid self -- @tparam node item Gui node -- @tparam[opt] number index The item position. By default add as last item -function StaticGrid.add(self, item, index) +-- @tparam[opt=SHIFT.RIGHT] number shift_policy How shift nodes, if required. See const.SHIFT +function StaticGrid.add(self, item, index, shift_policy) + shift_policy = shift_policy or const.SHIFT.RIGHT index = index or ((self.last_index or 0) + 1) if self.nodes[index] then - -- Move nodes to right - for i = self.last_index, index, -1 do - self.nodes[i + 1] = self.nodes[i] + if shift_policy == const.SHIFT.RIGHT then + for i = self.last_index, index, -1 do + self.nodes[i + 1] = self.nodes[i] + end + end + if shift_policy == const.SHIFT.LEFT then + for i = self.first_index, index do + self.nodes[i - 1] = self.nodes[i] + end end end @@ -189,19 +197,25 @@ end --- Remove the item from the grid. Note that gui node will be not deleted -- @tparam StaticGrid self -- @tparam number index The grid node index to remove --- @tparam bool is_shift_nodes If true, will shift nodes left after index +-- @tparam[opt=SHIFT.RIGHT] number shift_policy How shift nodes, if required. See const.SHIFT -- @treturn Node The deleted gui node from grid -function StaticGrid.remove(self, index, is_shift_nodes) +function StaticGrid.remove(self, index, shift_policy) + shift_policy = shift_policy or const.SHIFT.RIGHT assert(self.nodes[index], "No grid item at given index " .. index) local remove_node = self.nodes[index] self.nodes[index] = nil - if is_shift_nodes then + if shift_policy == const.SHIFT.RIGHT then for i = index, self.last_index do self.nodes[i] = self.nodes[i + 1] end end + if shift_policy == const.SHIFT.LEFT then + for i = index, self.first_index, -1 do + self.nodes[i] = self.nodes[i - 1] + end + end self:_update() diff --git a/druid/const.lua b/druid/const.lua index a16499e..f8016bd 100644 --- a/druid/const.lua +++ b/druid/const.lua @@ -89,6 +89,13 @@ M.OS = { } +M.SHIFT = { + NO_SHIFT = 0, + LEFT = -1, + RIGHT = 1, +} + + M.SIDE = { X = "x", Y = "y" diff --git a/druid/extended/dynamic_grid.lua b/druid/extended/dynamic_grid.lua index 2dc0fbc..d1f1d9c 100644 --- a/druid/extended/dynamic_grid.lua +++ b/druid/extended/dynamic_grid.lua @@ -136,18 +136,19 @@ end -- @tparam DynamicGrid self -- @tparam node node Gui node -- @tparam[opt] number index The node position. By default add as last node --- @tparam[opt=false] bool is_shift_left If true, shift all nodes to the left, otherwise shift nodes to the right -function DynamicGrid.add(self, node, index, is_shift_left) - local delta = is_shift_left and -1 or 1 +-- @tparam[opt=SHIFT.RIGHT] number shift_policy How shift nodes, if required. See const.SHIFT +function DynamicGrid.add(self, node, index, shift_policy) + shift_policy = shift_policy or const.SHIFT.RIGHT + local delta = shift_policy -- -1 or 1 or 0 -- By default add node at end index = index or ((self.last_index or 0) + 1) -- If node exist at index place, shifting them - local is_shift = self.nodes[index] + local is_shift = self.nodes[index] and shift_policy ~= const.SHIFT.NO_SHIFT if is_shift then -- We need to iterate from index to start or end grid, depends of shift side - local start_index = is_shift_left and self.first_index or self.last_index + local start_index = shift_policy == const.SHIFT.LEFT and self.first_index or self.last_index for i = start_index, index, -delta do self.nodes[i + delta] = self.nodes[i] end @@ -158,14 +159,13 @@ function DynamicGrid.add(self, node, index, is_shift_left) -- After shifting we should recalc node poses if is_shift then -- We need to iterate from placed node to start or end grid, depends of shift side - local target_index = is_shift_left and self.first_index or self.last_index + local target_index = shift_policy == const.SHIFT.LEFT and self.first_index or self.last_index for i = index + delta, target_index + delta, delta do local move_node = self.nodes[i] move_node.pos = self:get_pos(i, move_node.node, i - delta) end end - -- Sync grid data self:_update() @@ -178,9 +178,11 @@ end -- @tparam DynamicGrid self -- @tparam number index The grid node index to remove -- @tparam[opt=false] bool is_shift_left If true, shift all nodes to the left, otherwise shift nodes to the right +-- @tparam[opt=SHIFT.RIGHT] number shift_policy How shift nodes, if required. See const.SHIFT -- @treturn Node The deleted gui node from grid -function DynamicGrid.remove(self, index, is_shift_left) - local delta = is_shift_left and -1 or 1 +function DynamicGrid.remove(self, index, shift_policy) + shift_policy = shift_policy or const.SHIFT.RIGHT + local delta = shift_policy -- -1 or 1 or 0 assert(self.nodes[index], "No grid item at given index " .. index) @@ -189,11 +191,13 @@ function DynamicGrid.remove(self, index, is_shift_left) self.nodes[index] = nil -- After delete node, we should shift nodes and recalc their poses, depends from is_shift_left - local target_index = is_shift_left and self.first_index or self.last_index - for i = index, target_index, delta do - self.nodes[i] = self.nodes[i + delta] - if self.nodes[i] then - self.nodes[i].pos = self:get_pos(i, self.nodes[i].node, i - delta) + if shift_policy ~= const.SHIFT.NO_SHIFT then + local target_index = shift_policy == const.SHIFT.LEFT and self.first_index or self.last_index + for i = index, target_index, delta do + self.nodes[i] = self.nodes[i + delta] + if self.nodes[i] then + self.nodes[i].pos = self:get_pos(i, self.nodes[i].node, i - delta) + end end end @@ -407,7 +411,6 @@ function DynamicGrid:get_offset() local offset = vmath.vector3( (borders.z + borders.x)/2 + size.x * self.pivot.x, (borders.y + borders.w)/2 + size.y * self.pivot.y, - 0, 0) return offset diff --git a/druid/extended/infinity_list.lua b/druid/extended/infinity_list.lua index 190000a..5f2e7c0 100644 --- a/druid/extended/infinity_list.lua +++ b/druid/extended/infinity_list.lua @@ -1,6 +1,7 @@ --- Manage data for huge dataset in scroll --- It requires basic druid scroll and druid grid components local const = require("druid.const") +local helper = require("druid.helper") local component = require("druid.component") local M = component.create("infinity_list", { const.ON_UPDATE }) @@ -12,6 +13,7 @@ function M:init(data_list, scroll, grid, create_function) self.druid = self:get_druid() self.scroll = scroll self.grid = grid + self.scroll:bind_grid(grid) self.data = data_list self.top_index = 1 @@ -46,20 +48,27 @@ function M:set_data(data_list) end +function M:scroll_to_index(index) + self.top_index = helper.clamp(index, 1, #self.data) + self:_refresh() + self.scroll.on_scroll:trigger(self:get_context(), self) +end + + function M:_add_at(index) if self.nodes[index] then self:_remove_at(index) end local node, instance = self.create_function(self.data[index], index) - self.grid:add(node, index) + self.grid:add(node, index, const.SHIFT.NO_SHIFT) self.nodes[index] = node self.components[index] = instance end function M:_remove_at(index) - self.grid:remove(index) + self.grid:remove(index, const.SHIFT.NO_SHIFT) local node = self.nodes[index] gui.delete_node(node)