diff --git a/druid/annotations.lua b/druid/annotations.lua index 6ad81de..27e9271 100644 --- a/druid/annotations.lua +++ b/druid/annotations.lua @@ -43,13 +43,20 @@ function druid.set_text_function(callback) end ---@class druid.back_handler : druid.base_component ---@field on_back druid.event The @{DruidEvent} Event on back handler action. ----@field params any Custom args to pass in the callback +---@field params any|nil Custom args to pass in the callback local druid__back_handler = {} ---@class druid.base_component local druid__base_component = {} +--- Set current component style table. +--- Invoke `on_style_change` on component, if exist. Component should handle their style changing and store all style params +---@param self druid.base_component @{BaseComponent} +---@param druid_style table|nil Druid style module +---@return druid.base_component @{BaseComponent} +function druid__base_component.component:set_style(self, druid_style) end + --- Return all children components, recursive ---@param self druid.base_component @{BaseComponent} ---@return table Array of childrens if the Druid component instance @@ -131,13 +138,6 @@ function druid__base_component.set_input_priority(self, value, is_temporary) end ---@return druid.base_component @{BaseComponent} function druid__base_component.set_nodes(self, nodes) end ---- Set current component style table. ---- Invoke `on_style_change` on component, if exist. Component should handle their style changing and store all style params ----@param self druid.base_component @{BaseComponent} ----@param druid_style table|nil Druid style module ----@return druid.base_component @{BaseComponent} -function druid__base_component.set_style(self, druid_style) end - --- Set component template name. --- Use on all your custom components with GUI layouts used as templates. It will check parent template name to build full template name in self:get_node() ---@param self druid.base_component @{BaseComponent} @@ -169,7 +169,7 @@ function druid__blocker.set_enabled(self, state) end ---@class druid.button : druid.base_component ---@field anim_node node Button animation node. ----@field click_zone node Additional button click area, defined by another GUI Node +---@field click_zone node|nil Additional button click area, defined by another GUI node ---@field hover druid.hover The @{Hover}: Button Hover component ---@field node node Button trigger node ---@field node_id hash The GUI node id from button node @@ -226,7 +226,7 @@ function druid__button.set_enabled(self, state) end --- Set key name to trigger this button by keyboard. ---@param self druid.button @{Button} ----@param key hash The action_id of the input key +---@param key hash|string The action_id of the input key ---@return druid.button Current button instance function druid__button.set_key_trigger(self, key) end @@ -384,9 +384,10 @@ function druid__data_list.set_data(self, data) end ---@field can_y boolean Is drag component process horizontal. ---@field is_drag boolean Is component now dragging ---@field is_touch boolean Is component now touching +---@field node node Drag node ---@field on_drag druid.event on drag progress callback(self, dx, dy, total_x, total_y) ---@field on_drag_end druid.event Event on drag end callback(self, total_x, total_y) ----@field on_drag_start druid.event Event on drag start callback(self) +---@field on_drag_start druid.event Event on drag start callback(self, touch) ---@field on_touch_end druid.event Event on touch end callback(self) ---@field on_touch_start druid.event Event on touch start callback(self) ---@field style druid.drag.style Component style params. @@ -561,17 +562,22 @@ local druid__hotkey = {} --- Add hotkey for component callback ---@param self druid.hotkey @{Hotkey} ---@param keys string[]|hash[]|string|hash that have to be pressed before key pressed to activate ----@param callback_argument any|nil The argument to pass into the callback function ----@return druid.hotkey Current instance +---@param callback_argument value The argument to pass into the callback function function druid__hotkey.add_hotkey(self, keys, callback_argument) end ---- The @{Hotkey} constructor +--- Component init function ---@param self druid.hotkey @{Hotkey} ---@param keys string[]|string The keys to be pressed for trigger callback. Should contains one key and any modificator keys ---@param callback function The callback function ----@param callback_argument any|nil The argument to pass into the callback function +---@param callback_argument value The argument to pass into the callback function function druid__hotkey.init(self, keys, callback, callback_argument) end +--- If true, the callback will be triggered on action.repeated +---@param self druid.hotkey @{Hotkey} +---@param is_enabled_repeated bool The flag value +---@return druid.hotkey +function druid__hotkey.set_repeat(self, is_enabled_repeated) end + ---@class druid.hotkey.style ---@field MODIFICATORS string[] The list of action_id as hotkey modificators @@ -630,12 +636,12 @@ function druid__hover.set_mouse_hover(self, state) end ---@class druid.input : druid.base_component ----@field allowerd_characters string Pattern matching for user input +---@field allowerd_characters string|nil Pattern matching for user input ---@field button druid.button Button component ---@field is_empty boolean Is current input is empty now ---@field is_selected boolean Is current input selected now ---@field keyboard_type number Gui keyboard type for input field ----@field max_length number Max length for input text +---@field max_length number|nil Max length for input text ---@field on_input_empty druid.event On input field text change to empty string callback(self, input_text) ---@field on_input_full druid.event On input field text change to max length string callback(self, input_text) ---@field on_input_select druid.event On input field select callback(self, button_node) @@ -1002,6 +1008,7 @@ local druid__rich_text__style = {} ---@class druid.scroll : druid.base_component +---@field _is_inert bool Flag, if scroll now moving by inertion ---@field available_pos vector4 Available position for content node: (min_x, max_y, max_x, min_y) ---@field available_size vector3 Size of available positions: (width, height, 0) ---@field content_node node Scroll content node @@ -1012,7 +1019,7 @@ local druid__rich_text__style = {} ---@field on_scroll druid.event On scroll move callback(self, position) ---@field on_scroll_to druid.event On scroll_to function callback(self, target, is_instant) ---@field position vector3 Current scroll posisition ----@field selected number Current index of points of interests +---@field selected number|nil Current index of points of interests ---@field style druid.scroll.style Component style params. ---@field target_position vector3 Current scroll target position ---@field view_node node Scroll view node @@ -1394,7 +1401,7 @@ function druid__text.set_size(self, size) end --- Set text adjust, refresh the current text visuals, if needed ---@param self druid.text @{Text} ----@param adjust_type number|nil See const.TEXT_ADJUST. If pass nil - use current adjust type +---@param adjust_type string|nil See const.TEXT_ADJUST. If pass nil - use current adjust type ---@param minimal_scale number|nil If pass nil - not use minimal scale ---@return druid.text Current text instance function druid__text.set_text_adjust(self, adjust_type, minimal_scale) end diff --git a/druid/base/back_handler.lua b/druid/base/back_handler.lua index 4c2f2af..899e12e 100644 --- a/druid/base/back_handler.lua +++ b/druid/base/back_handler.lua @@ -32,7 +32,7 @@ -- @usage -- -- Replace params on runtime: -- back_handler.params = { ... } --- @tfield[opt] any params +-- @tfield any|nil params --- diff --git a/druid/base/button.lua b/druid/base/button.lua index 14550a4..5bd10c4 100755 --- a/druid/base/button.lua +++ b/druid/base/button.lua @@ -27,7 +27,7 @@ -- print("Also the button component is passed in callback params") -- end -- --- local custom_args = "any variable to pass inside callback" +-- local custom_args = "Any variable to pass inside callback" -- local button = self.druid:new_button("button_name", on_button_click, custom_args) -- -- @module Button @@ -131,8 +131,8 @@ --- The @{Hover}: Button Hover component -- @tfield Hover hover @{Hover} ---- Additional button click area, defined by another GUI Node --- @tfield[opt] node click_zone +--- Additional button click area, defined by another GUI node +-- @tfield node|nil click_zone --- @@ -257,6 +257,7 @@ end --- Component style params. -- You can override this component styles params in Druid styles table -- or create your own style +-- @table style -- @tfield[opt=0.4] number LONGTAP_TIME Minimum time to trigger on_hold_callback -- @tfield[opt=0.8] number AUTOHOLD_TRIGGER Maximum hold time to trigger button release while holding -- @tfield[opt=0.4] number DOUBLETAP_TIME Time between double taps @@ -265,7 +266,6 @@ end -- @tfield function on_hover function(self, node, hover_state) -- @tfield function on_mouse_hover function(self, node, hover_state) -- @tfield function on_set_enabled function(self, node, enabled_state) --- @table style function Button.on_style_change(self, style) self.style = {} self.style.LONGTAP_TIME = style.LONGTAP_TIME or 0.4 @@ -492,7 +492,7 @@ end --- Set key name to trigger this button by keyboard. -- @tparam Button self @{Button} --- @tparam hash key The action_id of the input key +-- @tparam hash|string key The action_id of the input key -- @treturn Button Current button instance -- @usage -- button:set_key_trigger("key_space") diff --git a/druid/base/drag.lua b/druid/base/drag.lua index c7f3457..db811e4 100644 --- a/druid/base/drag.lua +++ b/druid/base/drag.lua @@ -10,13 +10,16 @@ -- @within BaseComponent -- @alias druid.drag +--- Drag node +-- @tfield node node + --- Event on touch start callback(self) -- @tfield DruidEvent on_touch_start @{DruidEvent} --- Event on touch end callback(self) -- @tfield DruidEvent on_touch_end @{DruidEvent} ---- Event on drag start callback(self) +--- Event on drag start callback(self, touch) -- @tfield DruidEvent on_drag_start @{DruidEvent} --- on drag progress callback(self, dx, dy, total_x, total_y) @@ -67,23 +70,24 @@ local function start_touch(self, touch) self.y = touch.y self._scene_scale = helper.get_scene_scale(self.node) - self.on_touch_start:trigger(self:get_context()) + self.on_touch_start:trigger(self:get_context(), touch) end -local function end_touch(self) +local function end_touch(self, touch) if self.is_drag then self.on_drag_end:trigger( self:get_context(), self.x - self.touch_start_pos.x, - self.y - self.touch_start_pos.y + self.y - self.touch_start_pos.y, + touch ) end self.is_drag = false if self.is_touch then self.is_touch = false - self.on_touch_end:trigger(self:get_context()) + self.on_touch_end:trigger(self:get_context(), touch) end self:reset_input_priority() self.touch_id = 0 @@ -102,7 +106,7 @@ local function process_touch(self, touch) local distance = helper.distance(touch.x, touch.y, self.touch_start_pos.x, self.touch_start_pos.y) if not self.is_drag and distance >= self.style.DRAG_DEADZONE then self.is_drag = true - self.on_drag_start:trigger(self:get_context()) + self.on_drag_start:trigger(self:get_context(), touch) self:set_input_priority(const.PRIORITY_INPUT_MAX, true) end end @@ -266,7 +270,7 @@ function Drag.on_input(self, action_id, action) on_touch_release(self, action_id, action) else -- PC - end_touch(self) + end_touch(self, touch) end end @@ -285,7 +289,7 @@ function Drag.on_input(self, action_id, action) self.y = touch_modified.y end - if self.is_drag then + if self.is_drag and (self.dx ~= 0 or self.dy ~= 0) then local x_koef, y_koef = self._x_koef, self._y_koef if self.style.NO_USE_SCREEN_KOEF then x_koef, y_koef = 1, 1 @@ -295,7 +299,7 @@ function Drag.on_input(self, action_id, action) self.dx * x_koef / self._scene_scale.x, self.dy * y_koef / self._scene_scale.y, (self.x - self.touch_start_pos.x) * x_koef / self._scene_scale.x, - (self.y - self.touch_start_pos.y) * y_koef / self._scene_scale.y) + (self.y - self.touch_start_pos.y) * y_koef / self._scene_scale.y, touch_modified) end return self.is_drag diff --git a/druid/base/scroll.lua b/druid/base/scroll.lua index 5e4391d..7328429 100755 --- a/druid/base/scroll.lua +++ b/druid/base/scroll.lua @@ -53,6 +53,9 @@ --- Scroll content node -- @tfield node content_node +--- Flag, if scroll now moving by inertion +-- @tfield bool _is_inert + --- Current inert speed -- @tfield vector3 inertion @@ -72,7 +75,7 @@ -- @tfield Drag drag @{Drag} --- Current index of points of interests --- @tfield[opt] number selected +-- @tfield number|nil selected --- Flag, if scroll now animating by gui.animate -- @tfield boolean is_animate diff --git a/druid/base/text.lua b/druid/base/text.lua index e46f2e5..a34ffe7 100755 --- a/druid/base/text.lua +++ b/druid/base/text.lua @@ -408,7 +408,7 @@ end --- Set text adjust, refresh the current text visuals, if needed -- @tparam Text self @{Text} --- @tparam number|nil adjust_type See const.TEXT_ADJUST. If pass nil - use current adjust type +-- @tparam string|nil adjust_type See const.TEXT_ADJUST. If pass nil - use current adjust type -- @tparam number|nil minimal_scale If pass nil - not use minimal scale -- @treturn Text Current text instance function Text.set_text_adjust(self, adjust_type, minimal_scale) diff --git a/druid/component.lua b/druid/component.lua index ca6f89e..c2130d5 100644 --- a/druid/component.lua +++ b/druid/component.lua @@ -74,6 +74,7 @@ end -- -- Invoke `on_style_change` on component, if exist. Component should handle -- their style changing and store all style params +-- @function component:set_style -- @tparam BaseComponent self @{BaseComponent} -- @tparam table|nil druid_style Druid style module -- @treturn BaseComponent @{BaseComponent} diff --git a/druid/druid.lua b/druid/druid.lua index 811ad50..ad5e766 100644 --- a/druid/druid.lua +++ b/druid/druid.lua @@ -85,6 +85,8 @@ function M.register(name, module) druid_instance["new_" .. name] = function(self, ...) return druid_instance.new(self, module, ...) end + + return druid_instance["new_" .. name] end diff --git a/druid/extended/hotkey.lua b/druid/extended/hotkey.lua index f6e4608..1e867a8 100644 --- a/druid/extended/hotkey.lua +++ b/druid/extended/hotkey.lua @@ -23,6 +23,8 @@ local helper = require("druid.helper") local component = require("druid.component") +local Event = require("druid.event") +local const = require("druid.const") local Hotkey = component.create("hotkey") @@ -37,7 +39,9 @@ function Hotkey.init(self, keys, callback, callback_argument) self._hotkeys = {} self._modificators = {} - self._callback = callback + + self.on_hotkey_pressed = Event() + self.on_hotkey_released = Event(callback) if keys then self:add_hotkey(keys, callback_argument) @@ -104,8 +108,15 @@ function Hotkey.add_hotkey(self, keys, callback_argument) end +function Hotkey.on_focus_gained(self) + for k, v in pairs(self._modificators) do + self._modificators[k] = false + end +end + + function Hotkey.on_input(self, action_id, action) - if not action_id then + if not action_id or #self._hotkeys == 0 then return false end @@ -136,16 +147,16 @@ function Hotkey.on_input(self, action_id, action) if action.pressed and is_modificator_ok then hotkey.is_processing = true + self.on_hotkey_pressed:trigger(self:get_context(), hotkey.callback_argument) + end + if not action.pressed and self._is_process_repeated and action.repeated and is_modificator_ok and hotkey.is_processing then + self.on_hotkey_released:trigger(self:get_context(), hotkey.callback_argument) + return true end if action.released and is_modificator_ok and hotkey.is_processing then hotkey.is_processing = false - if hotkey.callback_argument then - self._callback(self:get_context(), hotkey.callback_argument) - return true - else - self._callback(self:get_context()) - return true - end + self.on_hotkey_released:trigger(self:get_context(), hotkey.callback_argument) + return true end end end @@ -154,4 +165,14 @@ function Hotkey.on_input(self, action_id, action) end +--- If true, the callback will be triggered on action.repeated +-- @tparam Hotkey self @{Hotkey} +-- @tparam bool is_enabled_repeated The flag value +-- @treturn Hotkey +function Hotkey.set_repeat(self, is_enabled_repeated) + self._is_process_repeated = is_enabled_repeated + return self +end + + return Hotkey diff --git a/druid/extended/input.lua b/druid/extended/input.lua index 319ee31..89c5fa0 100755 --- a/druid/extended/input.lua +++ b/druid/extended/input.lua @@ -40,10 +40,10 @@ -- @tfield boolean is_empty --- Max length for input text --- @tfield[opt] number max_length +-- @tfield number|nil max_length --- Pattern matching for user input --- @tfield[opt] string allowerd_characters +-- @tfield string|nil allowerd_characters --- Gui keyboard type for input field -- @tfield number keyboard_type diff --git a/druid/system/druid_instance.lua b/druid/system/druid_instance.lua index c9cd01e..c16a2a4 100755 --- a/druid/system/druid_instance.lua +++ b/druid/system/druid_instance.lua @@ -96,7 +96,6 @@ local back_handler = require("druid.base.back_handler") local DruidInstance = class("druid.druid_instance") -local PATH_OBJ = "." local MSG_ADD_FOCUS = hash("acquire_input_focus") local MSG_REMOVE_FOCUS = hash("release_input_focus") local IS_NO_AUTO_INPUT = sys.get_config_int("druid.no_auto_input", 0) == 1 @@ -107,11 +106,7 @@ local function set_input_state(self, is_input_inited) end self.input_inited = is_input_inited - if is_input_inited then - msg.post(PATH_OBJ, MSG_ADD_FOCUS) - else - msg.post(PATH_OBJ, MSG_REMOVE_FOCUS) - end + msg.post(".", is_input_inited and MSG_ADD_FOCUS or MSG_REMOVE_FOCUS) end @@ -207,10 +202,10 @@ local function process_input(self, action_id, action, components) local meta = component._meta if meta.input_enabled and can_use_input_component(self, component) then if not is_input_consumed then - is_input_consumed = component:on_input(action_id, action) + is_input_consumed = component:on_input(action_id, action) or false else if component.on_input_interrupt then - component:on_input_interrupt() + component:on_input_interrupt(action_id, action) end end end