diff --git a/druid/base/scroll.lua b/druid/base/scroll.lua index 01fbdd4..0d5c7e3 100755 --- a/druid/base/scroll.lua +++ b/druid/base/scroll.lua @@ -560,13 +560,13 @@ end function Scroll._set_scroll_position(self, position) local available_extra = self.available_pos_extra - position.x = helper.clamp(position.x, available_extra.x, available_extra.z) - position.y = helper.clamp(position.y, available_extra.w, available_extra.y) + local position_x = helper.clamp(position.x, available_extra.x, available_extra.z) + local position_y = helper.clamp(position.y, available_extra.w, available_extra.y) - if self.position.x ~= position.x or self.position.y ~= position.y then - self.position.x = position.x - self.position.y = position.y - gui.set_position(self.content_node, position) + if self.position.x ~= position_x or self.position.y ~= position_y then + self.position.x = position_x + self.position.y = position_y + gui.set_position(self.content_node, self.position) self.on_scroll:trigger(self:get_context(), self.position) end @@ -708,17 +708,13 @@ function Scroll._update_size(self) local content_border_extra = helper.get_border(self.content_node) local stretch_size = self.style.EXTRA_STRETCH_SIZE - if self.drag.can_x then - local sign = content_size.x > self.view_size.x and 1 or -1 - content_border_extra.x = content_border_extra.x - stretch_size * sign - content_border_extra.z = content_border_extra.z + stretch_size * sign - end + local sign_x = content_size.x > self.view_size.x and 1 or -1 + content_border_extra.x = content_border_extra.x - stretch_size * sign_x + content_border_extra.z = content_border_extra.z + stretch_size * sign_x - if self.drag.can_y then - local sign = content_size.y > self.view_size.y and 1 or -1 - content_border_extra.y = content_border_extra.y + stretch_size * sign - content_border_extra.w = content_border_extra.w - stretch_size * sign - end + local sign_y = content_size.y > self.view_size.y and 1 or -1 + content_border_extra.y = content_border_extra.y + stretch_size * sign_y + content_border_extra.w = content_border_extra.w - stretch_size * sign_y if not self.style.SMALL_CONTENT_SCROLL then self.drag.can_x = content_size.x > self.view_size.x diff --git a/druid/extended/data_list.lua b/druid/extended/data_list.lua index e8e95c6..8b50bab 100644 --- a/druid/extended/data_list.lua +++ b/druid/extended/data_list.lua @@ -25,6 +25,12 @@ --- Event triggered when scroll progress is changed; event(self, progress_value) -- @tfield DruidEvent on_scroll_progress_change @{DruidEvent} +---On DataList visual element created Event callback(self, index, node, instance) +-- @tfield DruidEvent on_element_add @{DruidEvent} + +---On DataList visual element created Event callback(self, index) +-- @tfield DruidEvent on_element_remove @{DruidEvent} + --- local const = require("druid.const") @@ -64,6 +70,8 @@ function DataList.init(self, scroll, grid, create_function) self.scroll.on_scroll:subscribe(self._check_elements, self) self.on_scroll_progress_change = Event() + self.on_element_add = Event() + self.on_element_remove = Event() self:set_data() end @@ -89,6 +97,14 @@ function DataList.set_data(self, data) end +--- Return current data from DataList component +-- @tparam DataList self @{DataList} +-- @treturn table The current data array +function DataList.get_data(self) + return self._data +end + + --- Add element to DataList. Currenly untested -- @tparam DataList self @{DataList} -- @tparam table data @@ -189,6 +205,34 @@ function DataList.get_index(self, data) end +--- Return all currenly created nodes in DataList +-- @tparam DataList self @{DataList} +-- @treturn Node[] List of created nodes +function DataList.get_created_nodes(self) + local nodes = {} + + for index, data in pairs(self._data_visual) do + nodes[index] = data.node + end + + return nodes +end + + +--- Return all currenly created components in DataList +-- @tparam DataList self @{DataList} +-- @treturn druid.base_component[] List of created nodes +function DataList.get_created_components(self) + local components = {} + + for index, data in pairs(self._data_visual) do + components[index] = data.component + end + + return components +end + + --- Instant scroll to element with passed index -- @tparam DataList self @{DataList} -- @tparam number index @@ -220,6 +264,7 @@ function DataList._add_at(self, index) } self:log_message("Add element at", { index = index }) + self.on_element_add:trigger(self:get_context(), index, node, instance) end @@ -233,12 +278,14 @@ function DataList._remove_at(self, index) local node = self._data_visual[index].node gui.delete_node(node) - if self._data_visual[index].component then - self.druid:remove(self._data_visual[index].component) + local instance = self._data_visual[index].component + if instance then + self.druid:remove(instance) end self._data_visual[index] = nil self:log_message("Remove element at", { index = index }) + self.on_element_remove:trigger(self:get_context(), index) end diff --git a/example/example.collection b/example/example.collection index 3e861b0..4bb97e3 100644 --- a/example/example.collection +++ b/example/example.collection @@ -1688,3 +1688,66 @@ embedded_instances { z: 1.0 } } +embedded_instances { + id: "data_list_with_component" + data: "components {\n" + " id: \"screen_factory\"\n" + " component: \"/monarch/screen_factory.script\"\n" + " position {\n" + " x: 0.0\n" + " y: 0.0\n" + " z: 0.0\n" + " }\n" + " rotation {\n" + " x: 0.0\n" + " y: 0.0\n" + " z: 0.0\n" + " w: 1.0\n" + " }\n" + " properties {\n" + " id: \"screen_id\"\n" + " value: \"data_list_with_component\"\n" + " type: PROPERTY_TYPE_HASH\n" + " }\n" + " properties {\n" + " id: \"popup\"\n" + " value: \"true\"\n" + " type: PROPERTY_TYPE_BOOLEAN\n" + " }\n" + "}\n" + "embedded_components {\n" + " id: \"collectionfactory\"\n" + " type: \"collectionfactory\"\n" + " data: \"prototype: \\\"/example/examples/data_list/with_component/with_component.collection\\\"\\n" + "load_dynamically: false\\n" + "\"\n" + " position {\n" + " x: 0.0\n" + " y: 0.0\n" + " z: 0.0\n" + " }\n" + " rotation {\n" + " x: 0.0\n" + " y: 0.0\n" + " z: 0.0\n" + " w: 1.0\n" + " }\n" + "}\n" + "" + position { + x: 0.0 + y: 0.0 + z: 0.0 + } + rotation { + x: 0.0 + y: 0.0 + z: 0.0 + w: 1.0 + } + scale3 { + x: 1.0 + y: 1.0 + z: 1.0 + } +} diff --git a/example/example.gui_script b/example/example.gui_script index 2af7cad..9a45ad1 100644 --- a/example/example.gui_script +++ b/example/example.gui_script @@ -156,6 +156,7 @@ local function init_lobby(self) self.lobby_grid:add(get_button_disabled(self, "Add/remove elements", "data_list_add_remove_nodes")) self.lobby_grid:add(get_button(self, "Navigate over elements", "data_list_navigate", "/data_list/navigate/navigate.gui_script")) self.lobby_grid:add(get_button(self, "Reinit data", "data_list_reinit_data", "/data_list/reinit_data/reinit_data.gui_script")) + self.lobby_grid:add(get_button(self, "With component", "data_list_with_component", "/data_list/with_component/with_component.gui_script")) self.lobby_grid:add(get_title(self, "Custom components")) self.lobby_grid:add(get_button(self, "Rich Input", "custom_rich_input", "/custom/rich_input/rich_input.gui_script")) diff --git a/example/examples/data_list/with_component/button_component/button_component.gui b/example/examples/data_list/with_component/button_component/button_component.gui new file mode 100644 index 0000000..f2c721f --- /dev/null +++ b/example/examples/data_list/with_component/button_component/button_component.gui @@ -0,0 +1,249 @@ +script: "" +fonts { + name: "game" + font: "/example/assets/fonts/game.font" +} +textures { + name: "kenney" + texture: "/example/assets/images/kenney.atlas" +} +background_color { + x: 0.0 + y: 0.0 + z: 0.0 + w: 0.0 +} +nodes { + position { + x: 0.0 + y: 0.0 + z: 0.0 + w: 1.0 + } + rotation { + x: 0.0 + y: 0.0 + z: 0.0 + w: 1.0 + } + scale { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + size { + x: 450.0 + y: 80.0 + z: 0.0 + w: 1.0 + } + color { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + type: TYPE_BOX + blend_mode: BLEND_MODE_ALPHA + texture: "kenney/button_blue" + id: "root" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_CENTER + adjust_mode: ADJUST_MODE_FIT + layer: "" + inherit_alpha: true + slice9 { + x: 20.0 + y: 20.0 + z: 20.0 + w: 0.0 + } + clipping_mode: CLIPPING_MODE_NONE + clipping_visible: true + clipping_inverted: false + alpha: 1.0 + template_node_child: false + size_mode: SIZE_MODE_MANUAL + custom_type: 0 +} +nodes { + position { + x: -50.0 + y: 8.0 + z: 0.0 + w: 1.0 + } + rotation { + x: 0.0 + y: 0.0 + z: 0.0 + w: 1.0 + } + scale { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + size { + x: 300.0 + y: 50.0 + z: 0.0 + w: 1.0 + } + color { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + type: TYPE_TEXT + blend_mode: BLEND_MODE_ALPHA + text: "Record: 1" + font: "game" + id: "text" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_CENTER + outline { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + shadow { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + adjust_mode: ADJUST_MODE_FIT + line_break: false + parent: "root" + layer: "" + inherit_alpha: true + alpha: 1.0 + outline_alpha: 0.0 + shadow_alpha: 0.0 + template_node_child: false + text_leading: 1.0 + text_tracking: 0.0 + custom_type: 0 +} +nodes { + position { + x: 175.0 + y: 6.0 + z: 0.0 + w: 1.0 + } + rotation { + x: 0.0 + y: 0.0 + z: 0.0 + w: 1.0 + } + scale { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + size { + x: 49.0 + y: 49.0 + z: 0.0 + w: 1.0 + } + color { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + type: TYPE_BOX + blend_mode: BLEND_MODE_ALPHA + texture: "kenney/back_green" + id: "icon" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_CENTER + adjust_mode: ADJUST_MODE_FIT + parent: "root" + layer: "" + inherit_alpha: true + slice9 { + x: 0.0 + y: 0.0 + z: 0.0 + w: 0.0 + } + clipping_mode: CLIPPING_MODE_NONE + clipping_visible: true + clipping_inverted: false + alpha: 1.0 + template_node_child: false + size_mode: SIZE_MODE_AUTO + custom_type: 0 +} +nodes { + position { + x: 0.0 + y: 2.0 + z: 0.0 + w: 1.0 + } + rotation { + x: 0.0 + y: 0.0 + z: 0.0 + w: 1.0 + } + scale { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + size { + x: 21.0 + y: 20.0 + z: 0.0 + w: 1.0 + } + color { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + type: TYPE_BOX + blend_mode: BLEND_MODE_ALPHA + texture: "kenney/checkmark" + id: "checkbox" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_CENTER + adjust_mode: ADJUST_MODE_FIT + parent: "icon" + layer: "" + inherit_alpha: true + slice9 { + x: 0.0 + y: 0.0 + z: 0.0 + w: 0.0 + } + clipping_mode: CLIPPING_MODE_NONE + clipping_visible: true + clipping_inverted: false + alpha: 1.0 + template_node_child: false + size_mode: SIZE_MODE_AUTO + custom_type: 0 +} +material: "/builtins/materials/gui.material" +adjust_reference: ADJUST_REFERENCE_PARENT +max_nodes: 512 diff --git a/example/examples/data_list/with_component/button_component/button_component.lua b/example/examples/data_list/with_component/button_component/button_component.lua new file mode 100644 index 0000000..39c6c23 --- /dev/null +++ b/example/examples/data_list/with_component/button_component/button_component.lua @@ -0,0 +1,76 @@ +--- For component interest functions +--- see https://github.com/Insality/druid/blob/develop/docs_md/02-creating_custom_components.md +--- Require this component in you gui file: +--- local ButtonComponent = require("example.examples.data_list.with_component.button_component.button_component") +--- And create this component via: +--- self.button_component = self.druid:new(ButtonComponent, template, nodes) + +local Event = require("druid.event") +local component = require("druid.component") + +---@class button_component: druid.base_component +---@field root node +---@field text druid.text +---@field druid druid_instance +local ButtonComponent = component.create("button_component") + +local SCHEME = { + ROOT = "root", + TEXT = "text", + ICON = "icon", + CHECKBOX = "checkbox" +} + + +---@param template string +---@param nodes table +function ButtonComponent:init(template, nodes) + self:set_template(template) + self:set_nodes(nodes) + self.druid = self:get_druid() + + self.root = self:get_node(SCHEME.ROOT) + self.text = self.druid:new_text(SCHEME.TEXT) + self.checkbox = self:get_node(SCHEME.CHECKBOX) + + self.button = self.druid:new_button(self.root, self._on_click) + + self.on_click = Event() +end + + +function ButtonComponent:set_data(data) + self._data = data + self.text:set_to("Element: " .. data.value) + self:set_checked(self._data.is_checked) +end + + +function ButtonComponent:get_data() + return self._data +end + + +function ButtonComponent:set_checked(state) + self._data.is_checked = state + gui.set_enabled(self.checkbox, state) +end + + +function ButtonComponent:set_click_zone(node) + self.button:set_click_zone(node) +end + + +function ButtonComponent:on_remove() + self.on_click:clear() +end + + +function ButtonComponent:_on_click() + self.on_click:trigger(self) +end + + + +return ButtonComponent diff --git a/example/examples/data_list/with_component/with_component.collection b/example/examples/data_list/with_component/with_component.collection new file mode 100644 index 0000000..18df249 --- /dev/null +++ b/example/examples/data_list/with_component/with_component.collection @@ -0,0 +1,37 @@ +name: "data_list_with_component" +scale_along_z: 0 +embedded_instances { + id: "go" + data: "components {\n" + " id: \"data_list_with_component\"\n" + " component: \"/example/examples/data_list/with_component/with_component.gui\"\n" + " position {\n" + " x: 0.0\n" + " y: 0.0\n" + " z: 0.0\n" + " }\n" + " rotation {\n" + " x: 0.0\n" + " y: 0.0\n" + " z: 0.0\n" + " w: 1.0\n" + " }\n" + "}\n" + "" + position { + x: 0.0 + y: 0.0 + z: 0.0 + } + rotation { + x: 0.0 + y: 0.0 + z: 0.0 + w: 1.0 + } + scale3 { + x: 1.0 + y: 1.0 + z: 1.0 + } +} diff --git a/example/examples/data_list/with_component/with_component.gui b/example/examples/data_list/with_component/with_component.gui new file mode 100644 index 0000000..54992cc --- /dev/null +++ b/example/examples/data_list/with_component/with_component.gui @@ -0,0 +1,528 @@ +script: "/example/examples/data_list/with_component/with_component.gui_script" +fonts { + name: "game" + font: "/example/assets/fonts/game.font" +} +textures { + name: "kenney" + texture: "/example/assets/images/kenney.atlas" +} +background_color { + x: 0.0 + y: 0.0 + z: 0.0 + w: 0.0 +} +nodes { + position { + x: 300.0 + y: 415.0 + z: 0.0 + w: 1.0 + } + rotation { + x: 0.0 + y: 0.0 + z: 0.0 + w: 1.0 + } + scale { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + size { + x: 600.0 + y: 830.0 + z: 0.0 + w: 1.0 + } + color { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + type: TYPE_BOX + blend_mode: BLEND_MODE_ALPHA + texture: "kenney/empty" + id: "root" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_CENTER + adjust_mode: ADJUST_MODE_FIT + layer: "" + inherit_alpha: true + slice9 { + x: 0.0 + y: 0.0 + z: 0.0 + w: 0.0 + } + clipping_mode: CLIPPING_MODE_NONE + clipping_visible: true + clipping_inverted: false + alpha: 1.0 + template_node_child: false + size_mode: SIZE_MODE_MANUAL + custom_type: 0 +} +nodes { + position { + x: 0.0 + y: 370.0 + z: 0.0 + w: 1.0 + } + rotation { + x: 0.0 + y: 0.0 + z: 0.0 + w: 1.0 + } + scale { + x: 0.75 + y: 0.75 + z: 1.0 + w: 1.0 + } + size { + x: 700.0 + y: 60.0 + z: 0.0 + w: 1.0 + } + color { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + type: TYPE_TEXT + blend_mode: BLEND_MODE_ALPHA + text: "Click to select component in DataList" + font: "game" + id: "text_hint_horizontal" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_CENTER + outline { + x: 0.0 + y: 0.0 + z: 0.0 + w: 1.0 + } + shadow { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + adjust_mode: ADJUST_MODE_FIT + line_break: false + parent: "root" + layer: "" + inherit_alpha: true + alpha: 1.0 + outline_alpha: 1.0 + shadow_alpha: 0.0 + template_node_child: false + text_leading: 1.0 + text_tracking: 0.0 + custom_type: 0 +} +nodes { + position { + x: 0.0 + y: 200.0 + z: 0.0 + w: 1.0 + } + rotation { + x: 0.0 + y: 0.0 + z: 0.0 + w: 1.0 + } + scale { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + size { + x: 450.0 + y: 400.0 + z: 0.0 + w: 1.0 + } + color { + x: 0.8 + y: 1.0 + z: 1.0 + w: 1.0 + } + type: TYPE_BOX + blend_mode: BLEND_MODE_ALPHA + texture: "" + id: "data_list_view" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_N + adjust_mode: ADJUST_MODE_FIT + parent: "root" + layer: "" + inherit_alpha: true + slice9 { + x: 0.0 + y: 0.0 + z: 0.0 + w: 0.0 + } + clipping_mode: CLIPPING_MODE_STENCIL + clipping_visible: true + clipping_inverted: false + alpha: 1.0 + template_node_child: false + size_mode: SIZE_MODE_MANUAL + custom_type: 0 +} +nodes { + position { + x: 0.0 + y: 0.0 + z: 0.0 + w: 1.0 + } + rotation { + x: 0.0 + y: 0.0 + z: 0.0 + w: 1.0 + } + scale { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + size { + x: 450.0 + y: 400.0 + z: 0.0 + w: 1.0 + } + color { + x: 1.0 + y: 0.6 + z: 0.4 + w: 1.0 + } + type: TYPE_BOX + blend_mode: BLEND_MODE_ALPHA + texture: "" + id: "data_list_content" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_N + adjust_mode: ADJUST_MODE_FIT + parent: "data_list_view" + layer: "" + inherit_alpha: true + slice9 { + x: 0.0 + y: 0.0 + z: 0.0 + w: 0.0 + } + clipping_mode: CLIPPING_MODE_NONE + clipping_visible: true + clipping_inverted: false + alpha: 1.0 + template_node_child: false + size_mode: SIZE_MODE_MANUAL + custom_type: 0 +} +nodes { + position { + x: 0.0 + y: 157.0 + z: 0.0 + w: 1.0 + } + rotation { + x: 0.0 + y: 0.0 + z: 0.0 + w: 1.0 + } + scale { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + size { + x: 200.0 + y: 100.0 + z: 0.0 + w: 1.0 + } + color { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + type: TYPE_TEMPLATE + id: "button_component" + parent: "root" + layer: "" + inherit_alpha: true + alpha: 1.0 + template: "/example/examples/data_list/with_component/button_component/button_component.gui" + template_node_child: false + custom_type: 0 +} +nodes { + position { + x: 0.0 + y: 0.0 + z: 0.0 + w: 1.0 + } + rotation { + x: 0.0 + y: 0.0 + z: 0.0 + w: 1.0 + } + scale { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + size { + x: 450.0 + y: 80.0 + z: 0.0 + w: 1.0 + } + color { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + type: TYPE_BOX + blend_mode: BLEND_MODE_ALPHA + texture: "kenney/button_blue" + id: "button_component/root" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_CENTER + adjust_mode: ADJUST_MODE_FIT + parent: "button_component" + layer: "" + inherit_alpha: true + slice9 { + x: 20.0 + y: 20.0 + z: 20.0 + w: 0.0 + } + clipping_mode: CLIPPING_MODE_NONE + clipping_visible: true + clipping_inverted: false + alpha: 1.0 + template_node_child: true + size_mode: SIZE_MODE_MANUAL + custom_type: 0 +} +nodes { + position { + x: -50.0 + y: 8.0 + z: 0.0 + w: 1.0 + } + rotation { + x: 0.0 + y: 0.0 + z: 0.0 + w: 1.0 + } + scale { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + size { + x: 300.0 + y: 50.0 + z: 0.0 + w: 1.0 + } + color { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + type: TYPE_TEXT + blend_mode: BLEND_MODE_ALPHA + text: "Record: 1" + font: "game" + id: "button_component/text" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_CENTER + outline { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + shadow { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + adjust_mode: ADJUST_MODE_FIT + line_break: false + parent: "button_component/root" + layer: "" + inherit_alpha: true + alpha: 1.0 + outline_alpha: 0.0 + shadow_alpha: 0.0 + template_node_child: true + text_leading: 1.0 + text_tracking: 0.0 + custom_type: 0 +} +nodes { + position { + x: 175.0 + y: 6.0 + z: 0.0 + w: 1.0 + } + rotation { + x: 0.0 + y: 0.0 + z: 0.0 + w: 1.0 + } + scale { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + size { + x: 49.0 + y: 49.0 + z: 0.0 + w: 1.0 + } + color { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + type: TYPE_BOX + blend_mode: BLEND_MODE_ALPHA + texture: "kenney/back_green" + id: "button_component/icon" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_CENTER + adjust_mode: ADJUST_MODE_FIT + parent: "button_component/root" + layer: "" + inherit_alpha: true + slice9 { + x: 0.0 + y: 0.0 + z: 0.0 + w: 0.0 + } + clipping_mode: CLIPPING_MODE_NONE + clipping_visible: true + clipping_inverted: false + alpha: 1.0 + template_node_child: true + size_mode: SIZE_MODE_AUTO + custom_type: 0 +} +nodes { + position { + x: 0.0 + y: 2.0 + z: 0.0 + w: 1.0 + } + rotation { + x: 0.0 + y: 0.0 + z: 0.0 + w: 1.0 + } + scale { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + size { + x: 21.0 + y: 20.0 + z: 0.0 + w: 1.0 + } + color { + x: 1.0 + y: 1.0 + z: 1.0 + w: 1.0 + } + type: TYPE_BOX + blend_mode: BLEND_MODE_ALPHA + texture: "kenney/checkmark" + id: "button_component/checkbox" + xanchor: XANCHOR_NONE + yanchor: YANCHOR_NONE + pivot: PIVOT_CENTER + adjust_mode: ADJUST_MODE_FIT + parent: "button_component/icon" + layer: "" + inherit_alpha: true + slice9 { + x: 0.0 + y: 0.0 + z: 0.0 + w: 0.0 + } + clipping_mode: CLIPPING_MODE_NONE + clipping_visible: true + clipping_inverted: false + alpha: 1.0 + template_node_child: true + size_mode: SIZE_MODE_AUTO + custom_type: 0 +} +layers { + name: "image" +} +layers { + name: "text" +} +material: "/builtins/materials/gui.material" +adjust_reference: ADJUST_REFERENCE_PARENT +max_nodes: 512 diff --git a/example/examples/data_list/with_component/with_component.gui_script b/example/examples/data_list/with_component/with_component.gui_script new file mode 100644 index 0000000..7a143cd --- /dev/null +++ b/example/examples/data_list/with_component/with_component.gui_script @@ -0,0 +1,89 @@ +local druid = require("druid.druid") + +local ButtonComponent = require("example.examples.data_list.with_component.button_component.button_component") + + +local function on_element_add(self, index, node, instance) + print("Add element from DataList at index", index, node) +end + + +local function on_element_remove(self, index) + print("Remove element from DataList at index", index) +end + + +local function on_button_click(self, button) + -- Since we change data of other records, we need to change raw data and change state of + -- created components + local data = self.data_list:get_data() + for _, entry in pairs(data) do + entry.is_checked = false + end + + -- This is way to access all current created DataList components + local components = self.data_list:get_created_components() + for _, component in pairs(components) do + component:set_checked(component == button) + end +end + + +local function create_element(self, data) + local nodes = gui.clone_tree(self.prefab) + -- Create custom component to pass it to DataList + local button = self.druid:new(ButtonComponent, "button_component", nodes) + -- Prefab is disabled, so need to enable it for new component + gui.set_enabled(button.root, true) + button:set_data(data) + button:set_click_zone(self.scroll.view_node) + button.on_click:subscribe(on_button_click, self) + + return button.root, button +end + + +function init(self) + self.druid = druid.new(self) + + self.prefab = gui.get_node("button_component/root") + gui.set_enabled(self.prefab, false) + + self.scroll = self.druid:new_scroll("data_list_view", "data_list_content") + self.scroll:set_horizontal_scroll(false) + self.grid = self.druid:new_static_grid("data_list_content", self.prefab, 1) + self.data_list = self.druid:new_data_list(self.scroll, self.grid, create_element) + + self.data = {} + for i = 1, 100 do + table.insert(self.data, { + is_checked = false, + value = i + }) + end + + self.data_list:set_data(self.data) + -- Custom callbacks for more management in DataList + self.data_list.on_element_add:subscribe(on_element_add) + self.data_list.on_element_remove:subscribe(on_element_remove) +end + + +function final(self) + self.druid:final() +end + + +function update(self, dt) + self.druid:update(dt) +end + + +function on_message(self, message_id, message, sender) + self.druid:on_message(message_id, message, sender) +end + + +function on_input(self, action_id, action) + return self.druid:on_input(action_id, action) +end