diff --git a/druid/event.lua b/druid/event.lua index 0e9f624..5893cdc 100644 --- a/druid/event.lua +++ b/druid/event.lua @@ -22,11 +22,15 @@ end --- Subscribe callback on event -- @tparam DruidEvent self -- @tparam function callback Callback itself -function DruidEvent.subscribe(self, callback) +-- @tparam table context Additional context as first param to callback call +function DruidEvent.subscribe(self, callback, context) assert(type(self) == "table", "You should subscribe to event with : syntax") assert(type(callback) == "function", "Callback should be function") - table.insert(self._callbacks, callback) + table.insert(self._callbacks, { + callback = callback, + context = context + }) return callback end @@ -35,10 +39,11 @@ end --- Unsubscribe callback on event -- @tparam DruidEvent self -- @tparam function callback Callback itself -function DruidEvent.unsubscribe(self, callback) - for i = 1, #self._callbacks do - if self._callbacks[i] == callback then - table.remove(self._callbacks, i) +-- @tparam table context Additional context as first param to callback call +function DruidEvent.unsubscribe(self, callback, context) + for index, callback_info in ipairs(self._callbacks) do + if callback_info.callback == callback and callback_info.context == context then + table.remove(self._callbacks, index) return end end @@ -64,8 +69,12 @@ end -- @tparam DruidEvent self -- @tparam any ... All event params function DruidEvent.trigger(self, ...) - for i = 1, #self._callbacks do - self._callbacks[i](...) + for index, callback_info in ipairs(self._callbacks) do + if callback_info.context then + callback_info.callback(callback_info.context, ...) + else + callback_info.callback(...) + end end end diff --git a/druid/extended/infinity_list.lua b/druid/extended/infinity_list.lua index 42f877f..0ab82ac 100644 --- a/druid/extended/infinity_list.lua +++ b/druid/extended/infinity_list.lua @@ -4,7 +4,7 @@ local const = require("druid.const") local helper = require("druid.helper") local component = require("druid.component") -local M = component.create("infinity_list", { const.ON_UPDATE }) +local M = component.create("infinity_list") function M:init(data_list, scroll, grid, create_function) @@ -25,20 +25,12 @@ function M:init(data_list, scroll, grid, create_function) self.components = {} self:_refresh() - self.scroll.on_scroll:subscribe(function() self._check_elements(self) end) + self.scroll.on_scroll:subscribe(self._check_elements, self) end function M:on_remove() - -- TODO: make this work - -- self.scroll.on_scroll:unsubscribe(self._check_elements) -end - - -function M:update(dt) - if self.scroll.animate then - self:_check_elements() - end + self.scroll.on_scroll:unsubscribe(self._check_elements, self) end @@ -48,6 +40,44 @@ function M:set_data(data_list) end +function M:add(data, index) + table.insert(self.data, index, data) + self:_refresh() +end + + +function M:remove(index, shift_policy) + table.remove(self.data, index) + self:_refresh() +end + + +function M:clear() + self.data = {} + self:_refresh() +end + + +function M:get_first_index() + return self.top_index +end + + +function M:get_last_index() + return self.last_index +end + + +function M:get_index(data) + for index, value in pairs(self.data) do + if value == data then + return index + end + end + return nil +end + + function M:scroll_to_index(index) self.top_index = helper.clamp(index, 1, #self.data) self:_refresh() @@ -90,66 +120,46 @@ end function M:_check_elements() - self.last_index = self.top_index - for index, node in pairs(self.nodes) do if self.scroll:is_node_in_view(node) then self.top_index = index - break + self.last_index = index end end - -- make items from (top_index upside - local is_top_outside = false - local cur_index = self.top_index - 1 - while not is_top_outside do - if not self.data[cur_index] then - break - end + self:_check_elements_from(self.top_index - 1, -1) + self:_check_elements_from(self.top_index, 1) - if not self.nodes[cur_index] then - self:_add_at(cur_index) - end - - if not self.scroll:is_node_in_view(self.nodes[cur_index]) then - is_top_outside = true - - -- remove nexts: - local remove_index = cur_index - 1 - while self.nodes[remove_index] do - self:_remove_at(remove_index) - remove_index = remove_index - 1 - end - end - - cur_index = cur_index - 1 + for index, node in pairs(self.nodes) do + self.top_index = math.min(self.top_index or index, index) + self.last_index = math.max(self.last_index or index, index) end +end - -- make items from [top_index downsize - local is_bot_outside = false - cur_index = self.top_index - while not is_bot_outside do - if not self.data[cur_index] then + +function M:_check_elements_from(index, step) + local is_outside = false + while not is_outside do + if not self.data[index] then break end - if not self.nodes[cur_index] then - self:_add_at(cur_index) + if not self.nodes[index] then + self:_add_at(index) end - if not self.scroll:is_node_in_view(self.nodes[cur_index]) then - is_bot_outside = true + + if not self.scroll:is_node_in_view(self.nodes[index]) then + is_outside = true -- remove nexts: - local remove_index = cur_index + 1 + local remove_index = index while self.nodes[remove_index] do self:_remove_at(remove_index) - remove_index = remove_index + 1 + remove_index = remove_index + step end - else - self.last_index = cur_index end - cur_index = cur_index + 1 + index = index + step end end