diff --git a/druid/annotations.lua b/druid/annotations.lua index 9ffadd01..638d896a 100644 --- a/druid/annotations.lua +++ b/druid/annotations.lua @@ -1580,10 +1580,11 @@ local druid_instance = {} function druid_instance.final(self) end --- Create new component. +---@generic T ---@param self druid_instance ----@param component druid.base_component Component module +---@param component T Component module ---@param ... any Other component params to pass it to component:init function ----@return druid.base_component Component instance +---@return T Component instance function druid_instance.new(self, component, ...) end --- Create @{BackHandler} component diff --git a/druid/base/scroll.lua b/druid/base/scroll.lua index 068386d4..58ba1b56 100755 --- a/druid/base/scroll.lua +++ b/druid/base/scroll.lua @@ -365,6 +365,17 @@ function Scroll.set_view_size(self, size) end +--- Refresh scroll view size +-- @tparam Scroll self @{Scroll} +function Scroll.update_view_size(self) + self.view_size = helper.get_scaled_size(self.view_node) + self.view_border = helper.get_border(self.view_node) + self:_update_size() + + return self +end + + --- Enable or disable scroll inert. -- If disabled, scroll through points (if exist) -- If no points, just simple drag without inertion diff --git a/druid/extended/data_list.lua b/druid/extended/data_list.lua index c4a5f35f..fa9adcaa 100644 --- a/druid/extended/data_list.lua +++ b/druid/extended/data_list.lua @@ -61,6 +61,8 @@ function DataList.init(self, scroll, grid, create_function) self.scroll_progress = 0 self._create_function = create_function + self._is_use_cache = false + self._cache = {} self._data = {} self._data_visual = {} @@ -80,6 +82,14 @@ function DataList.on_remove(self) end +--- Set refresh function for DataList component +-- @tparam DataList self @{DataList} +function DataList.set_use_cache(self, is_use_cache) + self._is_use_cache = is_use_cache + return self +end + + --- Set new data set for DataList component -- @tparam DataList self @{DataList} -- @tparam table data The new data array @@ -199,7 +209,7 @@ function DataList.scroll_to_index(self, index) end ---- Add element at passed index +--- Add element at passed index using cache or create new -- @tparam DataList self @{DataList} -- @tparam number index -- @local @@ -208,19 +218,32 @@ function DataList._add_at(self, index) self:_remove_at(index) end - local node, instance = self._create_function(self:get_context(), self._data[index], index, self) + local data = self._data[index] + local node, instance + + -- Use cache if available and is_use_cache is set + if #self._cache > 0 and self._is_use_cache then + local cached = table.remove(self._cache) + node = cached.node + instance = cached.component + gui.set_enabled(node, true) + else + -- Create a new element if no cache or refresh function is not set + node, instance = self._create_function(self:get_context(), data, index, self) + end + self._data_visual[index] = { - data = self._data[index], + data = data, node = node, component = instance, } self.grid:add(node, index, const.SHIFT.NO_SHIFT) - self.on_element_add:trigger(self:get_context(), index, node, instance) + self.on_element_add:trigger(self:get_context(), index, node, instance, data) end ---- Remove element from passed index +--- Remove element from passed index and add it to cache if applicable -- @tparam DataList self @{DataList} -- @tparam number index -- @local @@ -230,18 +253,27 @@ function DataList._remove_at(self, index) local visual_data = self._data_visual[index] local node = visual_data.node local instance = visual_data.component - - gui.delete_node(node) - if instance then - -- We should remove instance from druid that spawned component - instance._meta.druid:remove(instance) + local data = visual_data.data + + self.on_element_remove:trigger(self:get_context(), index, node, instance, data) + + if self._is_use_cache then + -- Disable the node and add it to the cache instead of deleting it + gui.set_enabled(node, false) + table.insert(self._cache, visual_data) -- Cache the removed element + else + -- If no refresh function, delete the node and component as usual + gui.delete_node(node) + if instance then + instance._meta.druid:remove(instance) + end end - self._data_visual[index] = nil - self.on_element_remove:trigger(self:get_context(), index) + self._data_visual[index] = nil end + --- Refresh all elements in DataList -- @tparam DataList self @{DataList} -- @local diff --git a/example/examples/general/overview/overview.gui_script b/example/examples/general/overview/overview.gui_script index f0ded90b..8f4589ae 100644 --- a/example/examples/general/overview/overview.gui_script +++ b/example/examples/general/overview/overview.gui_script @@ -52,7 +52,7 @@ end local function setup_slider(self) local slider = self.druid:new_slider("slider_pin", vmath.vector3(95, 0, 0), function(_, value) gui.set_text(gui.get_node("text_progress_slider"), math.ceil(value * 100) .. "%") - end) + end) --[[@as druid.slider]] slider:set(0.2) end diff --git a/example/examples/general/scroll/scroll.gui_script b/example/examples/general/scroll/scroll.gui_script index 3ad39b9f..f9a5468a 100644 --- a/example/examples/general/scroll/scroll.gui_script +++ b/example/examples/general/scroll/scroll.gui_script @@ -54,9 +54,10 @@ function init(self) self.druid:new_scroll("children_scroll_3", "children_scroll_content_3") -- Content with less size than view - self.druid:new_scroll("scroll_smaller_view", "scroll_smaller_content") - :set_extra_stretch_size(0) - :set_inert(false) + local small_scroll = self.druid:new_scroll("scroll_smaller_view", "scroll_smaller_content") --[[@as druid.scroll]] + small_scroll.style.SMALL_CONTENT_SCROLL = true + small_scroll:set_extra_stretch_size(0) -- it also update scroll size due the change of SMALL_CONTENT_SCROLL + small_scroll:set_inert(false) -- Scroll with points of interests self.druid:new_scroll("scroll_with_points", "scroll_with_points_content")