diff --git a/druid/extended/infinity_list.lua b/druid/extended/infinity_list.lua index c9974f0..e7e8e87 100644 --- a/druid/extended/infinity_list.lua +++ b/druid/extended/infinity_list.lua @@ -15,17 +15,22 @@ function M:init(data_list, scroll, grid, create_function) self.grid = grid self.scroll:bind_grid(grid) - self.data = data_list + --- Current visual elements indexes self.top_index = 1 self.last_index = 1 + self._data = {} + self._data_first_index = false + self._data_last_index = false + self._data_length = 0 + self.create_function = create_function - self.nodes = {} - self.components = {} + self._data_visual = {} - self:_refresh() self.scroll.on_scroll:subscribe(self._check_elements, self) + + self:set_data(data_list) end @@ -35,41 +40,72 @@ end function M:set_data(data_list) - self.data = data_list + self._data = data_list + self:_update_data_info() self:_refresh() end -function M:add(data, index) - table.insert(self.data, index, data) - self:_refresh() +function M:add(data, index, shift_policy) + index = index or self._data_last_index + 1 + shift_policy = shift_policy or const.SHIFT.RIGHT + + if self._data[index] then + if shift_policy == const.SHIFT.RIGHT then + for i = self._data_last_index, index, -1 do + self._data[i + 1] = self._data[i] + end + end + if shift_policy == const.SHIFT.LEFT then + for i = self._data_first_index, index do + self._data[i - 1] = self._data[i] + end + end + end + self._data[index] = data + self:_update_data_info() + self:_check_elements() end function M:remove(index, shift_policy) - table.remove(self.data, index) + table.remove(self._data, index) self:_refresh() end +function M:remove_by_data(data, shift_policy) + local index = helper.contains(self._data, data) + if index then + table.remove(self._data, index) + self:_refresh() + end +end + + function M:clear() - self.data = {} + self._data = {} self:_refresh() end function M:get_first_index() - return self.top_index + return self._data_first_index end function M:get_last_index() - return self.last_index + return self._data_last_index +end + + +function M:get_length() + return self._data_length end function M:get_index(data) - for index, value in pairs(self.data) do + for index, value in pairs(self._data) do if value == data then return index end @@ -79,40 +115,41 @@ end function M:scroll_to_index(index) - self.top_index = helper.clamp(index, 1, #self.data) + 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 + if self._data_visual[index] then self:_remove_at(index) end - local node, instance = self.create_function(self.data[index], index) + local node, instance = self.create_function(self._data[index], index) self.grid:add(node, index, const.SHIFT.NO_SHIFT) - self.nodes[index] = node - self.components[index] = instance + self._data_visual[index] = { + node = node, + component = instance + } end function M:_remove_at(index) self.grid:remove(index, const.SHIFT.NO_SHIFT) - local node = self.nodes[index] + local node = self._data_visual[index].node gui.delete_node(node) - self.nodes[index] = nil - if self.components[index] then - self.druid:remove(self.components[index]) - self.components[index] = nil + if self._data_visual[index].component then + self.druid:remove(self._data_visual[index].component) end + self._data_visual[index] = nil end function M:_refresh() - for index, _ in pairs(self.nodes) do + for index, _ in pairs(self._data_visual) do self:_remove_at(index) end self:_check_elements() @@ -120,8 +157,8 @@ end function M:_check_elements() - for index, node in pairs(self.nodes) do - if self.scroll:is_node_in_view(node) then + for index, data in pairs(self._data_visual) do + if self.scroll:is_node_in_view(data.node) then self.top_index = index self.last_index = index end @@ -130,7 +167,7 @@ function M:_check_elements() self:_check_elements_from(self.top_index - 1, -1) self:_check_elements_from(self.top_index, 1) - for index, node in pairs(self.nodes) do + for index, data in pairs(self._data_visual) do self.top_index = math.min(self.top_index or index, index) self.last_index = math.max(self.last_index or index, index) end @@ -140,20 +177,20 @@ end function M:_check_elements_from(index, step) local is_outside = false while not is_outside do - if not self.data[index] then + if not self._data[index] then break end - if not self.nodes[index] then + if not self._data_visual[index] then self:_add_at(index) end - if not self.scroll:is_node_in_view(self.nodes[index]) then + if not self.scroll:is_node_in_view(self._data_visual[index].node) then is_outside = true -- remove nexts: local remove_index = index + step - while self.nodes[remove_index] do + while self._data_visual[remove_index] do self:_remove_at(remove_index) remove_index = remove_index + step end @@ -164,4 +201,22 @@ function M:_check_elements_from(index, step) end +function M:_update_data_info() + self._data_first_index = false + self._data_last_index = false + self._data_length = 0 + + for index, data in pairs(self._data) do + self._data_first_index = math.min(self._data_first_index or index, index) + self._data_last_index = math.max(self._data_last_index or index, index) + self._data_length = self._data_length + 1 + end + + if self._data_length == 0 then + self._data_first_index = 1 + self._data_last_index = 1 + end +end + + return M diff --git a/example/page/infinity_page.lua b/example/page/infinity_page.lua index 80201a0..7988f88 100644 --- a/example/page/infinity_page.lua +++ b/example/page/infinity_page.lua @@ -4,23 +4,43 @@ local function create_infinity_instance(self, record, index) local instance = gui.clone_tree(self.infinity_prefab) gui.set_enabled(instance["infinity_prefab"], true) - gui.set_text(instance["infinity_text"], "Record " .. index) + gui.set_text(instance["infinity_text"], "Record " .. record) local button = self.druid:new_button(instance["infinity_prefab"], function() - print("Infinity click on", index) + print("Infinity click on", record) + self.infinity_list:add(self.infinity_list:get_length() + 1) + end) + button.on_long_click:subscribe(function() + self.infinity_list:remove_by_data(record) end) return instance["infinity_prefab"], button end +local function create_infinity_instance_hor(self, record, index) + local instance = gui.clone_tree(self.infinity_prefab) + gui.set_enabled(instance["infinity_prefab"], true) + gui.set_text(instance["infinity_text"], "Record " .. record) + + local button = self.druid:new_button(instance["infinity_prefab"], function() + print("Infinity click on", record) + self.infinity_list_hor:remove_by_data(record) + end) + + return instance["infinity_prefab"], button +end + + + local function create_infinity_instance_small(self, record, index) local instance = gui.clone_tree(self.infinity_prefab_small) gui.set_enabled(instance["infinity_prefab_small"], true) - gui.set_text(instance["infinity_text_3"], index) + gui.set_text(instance["infinity_text_3"], record) local button = self.druid:new_button(instance["infinity_prefab_small"], function() - print("Infinity click on", index) + print("Infinity click on", record) + self.infinity_list_small:remove_by_data(record) end) button:set_click_zone(self.infinity_scroll_3.view_node) @@ -31,11 +51,12 @@ end local function create_infinity_instance_dynamic(self, record, index) local instance = gui.clone_tree(self.infinity_prefab_dynamic) gui.set_enabled(instance["infinity_prefab_dynamic"], true) - gui.set_text(instance["infinity_text_dynamic"], "Record " .. index) + gui.set_text(instance["infinity_text_dynamic"], "Record " .. record) gui.set_size(instance["infinity_prefab_dynamic"], vmath.vector3(200, 60 + index * 3, 0)) local button = self.druid:new_button(instance["infinity_prefab_dynamic"], function() - print("Dynamic click on", index) + print("Dynamic click on", record) + self.infinity_list_dynamic:remove_by_data(record) end) button:set_click_zone(self.infinity_scroll_dynamic.view_node) @@ -46,11 +67,12 @@ end local function create_infinity_instance_dynamic_hor(self, record, index) local instance = gui.clone_tree(self.infinity_prefab_dynamic) gui.set_enabled(instance["infinity_prefab_dynamic"], true) - gui.set_text(instance["infinity_text_dynamic"], "Record " .. index) + gui.set_text(instance["infinity_text_dynamic"], "Record " .. record) gui.set_size(instance["infinity_prefab_dynamic"], vmath.vector3(150 + 2 * index, 60, 0)) local button = self.druid:new_button(instance["infinity_prefab_dynamic"], function() - print("Dynamic click on", index) + print("Dynamic click on", record) + self.infinity_list_dynamic_hor:remove_by_data(record) end) button:set_click_zone(self.infinity_scroll_dynamic_hor.view_node) @@ -73,7 +95,7 @@ local function setup_infinity_list(self) self.infinity_list_hor = self.druid:new_infinity_list(data, self.infinity_scroll_hor, self.infinity_grid_hor, function(record, index) -- function should return gui_node, [druid_component] - local root, button = create_infinity_instance(self, record, index) + local root, button = create_infinity_instance_hor(self, record, index) button:set_click_zone(self.infinity_scroll_hor.view_node) return root, button end)