mirror of
https://github.com/Insality/druid
synced 2025-09-27 18:12:21 +02:00
Merge branch 'layout' into develop
This commit is contained in:
@@ -17,10 +17,10 @@
|
||||
--- Event on drag start callback(self)
|
||||
-- @tfield DruidEvent on_drag_start @{DruidEvent}
|
||||
|
||||
--- on drag progress callback(self, dx, dy)
|
||||
--- on drag progress callback(self, dx, dy, total_x, total_y)
|
||||
-- @tfield DruidEvent on_drag Event @{DruidEvent}
|
||||
|
||||
--- Event on drag end callback(self)
|
||||
--- Event on drag end callback(self, total_x, total_y)
|
||||
-- @tfield DruidEvent on_drag_end @{DruidEvent}
|
||||
|
||||
--- Is component now touching
|
||||
@@ -70,7 +70,7 @@ end
|
||||
|
||||
local function end_touch(self)
|
||||
if self.is_drag then
|
||||
self.on_drag_end:trigger(self:get_context())
|
||||
self.on_drag_end:trigger(self:get_context(), self.x - self.touch_start_pos.x, self.y - self.touch_start_pos.y)
|
||||
end
|
||||
|
||||
self.is_drag = false
|
||||
@@ -96,7 +96,7 @@ local function process_touch(self, touch)
|
||||
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:set_input_priority(const.PRIORITY_INPUT_MAX)
|
||||
self:set_input_priority(const.PRIORITY_INPUT_MAX, true)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -176,6 +176,7 @@ function Drag.init(self, node, on_drag_callback)
|
||||
self.is_touch = false
|
||||
self.is_drag = false
|
||||
self.touch_start_pos = vmath.vector3(0)
|
||||
self._is_disabled = false
|
||||
|
||||
self.can_x = true
|
||||
self.can_y = true
|
||||
@@ -186,6 +187,8 @@ function Drag.init(self, node, on_drag_callback)
|
||||
self.on_drag_start = Event()
|
||||
self.on_drag = Event(on_drag_callback)
|
||||
self.on_drag_end = Event()
|
||||
|
||||
self:on_window_resized()
|
||||
end
|
||||
|
||||
|
||||
@@ -199,6 +202,13 @@ function Drag.on_late_init(self)
|
||||
end
|
||||
|
||||
|
||||
function Drag.on_window_resized(self)
|
||||
local x_koef, y_koef = helper.get_screen_aspect_koef()
|
||||
self._x_koef = x_koef
|
||||
self._y_koef = y_koef
|
||||
end
|
||||
|
||||
|
||||
function Drag.on_input_interrupt(self)
|
||||
if self.is_drag or self.is_touch then
|
||||
end_touch(self)
|
||||
@@ -211,7 +221,7 @@ function Drag.on_input(self, action_id, action)
|
||||
return false
|
||||
end
|
||||
|
||||
if not helper.is_enabled(self.node) then
|
||||
if not helper.is_enabled(self.node) or self._is_disabled then
|
||||
return false
|
||||
end
|
||||
|
||||
@@ -268,7 +278,7 @@ function Drag.on_input(self, action_id, action)
|
||||
end
|
||||
|
||||
if self.is_drag then
|
||||
self.on_drag:trigger(self:get_context(), self.dx, self.dy)
|
||||
self.on_drag:trigger(self:get_context(), self.dx, self.dy, self.x - self.touch_start_pos.x, self.y - self.touch_start_pos.y)
|
||||
end
|
||||
|
||||
return self.is_drag
|
||||
@@ -284,4 +294,21 @@ function Drag.set_click_zone(self, node)
|
||||
end
|
||||
|
||||
|
||||
--- Set Drag input enabled or disabled
|
||||
-- @tparam Drag self @{Drag}
|
||||
-- @tparam bool is enabled
|
||||
function Drag.set_enabled(self, is_enabled)
|
||||
self._is_disabled = not is_enabled
|
||||
end
|
||||
|
||||
|
||||
--- Check if Drag component is enabled
|
||||
-- @tparam Drag self @{Drag}
|
||||
-- @treturn bool
|
||||
function Drag.is_enabled(self)
|
||||
return self._is_disabled
|
||||
end
|
||||
|
||||
|
||||
|
||||
return Drag
|
||||
|
@@ -33,9 +33,12 @@
|
||||
--- The last index of node in grid
|
||||
-- @tfield number last_index
|
||||
|
||||
--- Item anchor
|
||||
--- Item anchor [0..1]
|
||||
-- @tfield vector3 anchor
|
||||
|
||||
--- Item pivot [-0.5..0.5]
|
||||
-- @tfield vector3 pivot
|
||||
|
||||
--- Item size
|
||||
-- @tfield vector3 node_size
|
||||
|
||||
|
@@ -240,10 +240,16 @@ end
|
||||
-- @treturn number Height
|
||||
function Text.get_text_size(self, text)
|
||||
text = text or self.last_value
|
||||
local font = gui.get_font(self.node)
|
||||
local font_name = gui.get_font(self.node)
|
||||
local font = gui.get_font_resource(font_name)
|
||||
local scale = gui.get_scale(self.node)
|
||||
local linebreak = gui.get_line_break(self.node)
|
||||
local metrics = gui.get_text_metrics(font, text, 0, linebreak, 0, 0)
|
||||
local metrics = resource.get_text_metrics(font, text, {
|
||||
line_break = linebreak,
|
||||
leading = 1,
|
||||
tracking = 0,
|
||||
width = self.start_size.x
|
||||
})
|
||||
local width = metrics.width
|
||||
for i = #text, 1, -1 do
|
||||
local c = string.sub(text, i, i)
|
||||
|
@@ -25,6 +25,7 @@ BaseComponent.ON_FOCUS_LOST = const.ON_FOCUS_LOST
|
||||
BaseComponent.ON_FOCUS_GAINED = const.ON_FOCUS_GAINED
|
||||
BaseComponent.ON_LAYOUT_CHANGE = const.ON_LAYOUT_CHANGE
|
||||
BaseComponent.ON_MESSAGE_INPUT = const.ON_MESSAGE_INPUT
|
||||
BaseComponent.ON_WINDOW_RESIZED = const.ON_WINDOW_RESIZED
|
||||
BaseComponent.ON_LANGUAGE_CHANGE = const.ON_LANGUAGE_CHANGE
|
||||
|
||||
|
||||
@@ -37,6 +38,7 @@ BaseComponent.ALL_INTERESTS = {
|
||||
BaseComponent.ON_FOCUS_GAINED,
|
||||
BaseComponent.ON_LAYOUT_CHANGE,
|
||||
BaseComponent.ON_MESSAGE_INPUT,
|
||||
BaseComponent.ON_WINDOW_RESIZED,
|
||||
BaseComponent.ON_LANGUAGE_CHANGE,
|
||||
}
|
||||
|
||||
@@ -46,6 +48,7 @@ BaseComponent.SPECIFIC_UI_MESSAGES = {
|
||||
[hash("layout_changed")] = BaseComponent.ON_LAYOUT_CHANGE, -- The message_id from Defold
|
||||
[hash(BaseComponent.ON_FOCUS_LOST)] = BaseComponent.ON_FOCUS_LOST,
|
||||
[hash(BaseComponent.ON_FOCUS_GAINED)] = BaseComponent.ON_FOCUS_GAINED,
|
||||
[hash(BaseComponent.ON_WINDOW_RESIZED)] = BaseComponent.ON_WINDOW_RESIZED,
|
||||
[hash(BaseComponent.ON_MESSAGE_INPUT)] = BaseComponent.ON_MESSAGE_INPUT,
|
||||
[hash(BaseComponent.ON_LANGUAGE_CHANGE)] = BaseComponent.ON_LANGUAGE_CHANGE,
|
||||
}
|
||||
@@ -170,7 +173,7 @@ function BaseComponent.get_node(self, node_or_name)
|
||||
end
|
||||
|
||||
if not node then
|
||||
assert(node, "No component with name: " .. template_name .. node_or_name)
|
||||
assert(node, "No component with name: " .. (template_name or "") .. (node_or_name or ""))
|
||||
end
|
||||
|
||||
return node
|
||||
@@ -215,17 +218,22 @@ end
|
||||
--- Set component input priority
|
||||
-- @tparam BaseComponent self @{BaseComponent}
|
||||
-- @tparam number value The new input priority value
|
||||
-- @tparam boolean is_temporary If true, the reset input priority will return to previous value
|
||||
-- @treturn number The component input priority
|
||||
function BaseComponent.set_input_priority(self, value)
|
||||
function BaseComponent.set_input_priority(self, value, is_temporary)
|
||||
assert(value)
|
||||
|
||||
if self._component.input_priority ~= value then
|
||||
self._component.input_priority = value
|
||||
self._component._is_input_priority_changed = true
|
||||
|
||||
if not is_temporary then
|
||||
self._component.default_input_priority = value
|
||||
end
|
||||
|
||||
local children = self:get_childrens()
|
||||
for i = 1, #children do
|
||||
children[i]:set_input_priority(value)
|
||||
children[i]:set_input_priority(value, is_temporary)
|
||||
end
|
||||
end
|
||||
|
||||
|
@@ -40,6 +40,7 @@ M.ON_FOCUS_LOST = "on_focus_lost"
|
||||
M.ON_FOCUS_GAINED = "on_focus_gained"
|
||||
M.ON_LAYOUT_CHANGE = "on_layout_change"
|
||||
M.ON_MESSAGE_INPUT = "on_message_input"
|
||||
M.ON_WINDOW_RESIZED = "on_window_resized"
|
||||
M.ON_LANGUAGE_CHANGE = "on_language_change"
|
||||
|
||||
|
||||
@@ -83,6 +84,16 @@ M.REVERSE_PIVOTS = {
|
||||
}
|
||||
|
||||
|
||||
M.LAYOUT_MODE = {
|
||||
STRETCH_X = "stretch_x",
|
||||
STRETCH_Y = "stretch_y",
|
||||
ZOOM_MIN = "zoom_min",
|
||||
ZOOM_MAX = "zoom_max",
|
||||
FIT = gui.ADJUST_FIT,
|
||||
STRETCH = gui.ADJUST_STRETCH,
|
||||
}
|
||||
|
||||
|
||||
M.VECTOR_ZERO = vmath.vector3(0)
|
||||
M.VECTOR_ONE = vmath.vector3(1)
|
||||
M.SYS_INFO = sys.get_sys_info()
|
||||
|
@@ -117,6 +117,12 @@ function M.on_window_callback(event)
|
||||
msg.post(instances[i].url, base_component.ON_FOCUS_GAINED)
|
||||
end
|
||||
end
|
||||
|
||||
if event == window.WINDOW_EVENT_RESIZED then
|
||||
for i = 1, #instances do
|
||||
msg.post(instances[i].url, base_component.ON_WINDOW_RESIZED)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
148
druid/extended/hotkey.lua
Normal file
148
druid/extended/hotkey.lua
Normal file
@@ -0,0 +1,148 @@
|
||||
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
|
||||
|
||||
--- Druid hotkey component
|
||||
-- @module Hotkey
|
||||
-- @within BaseComponent
|
||||
-- @alias druid.hotkey
|
||||
|
||||
--- On change state callback(self, state)
|
||||
-- @tfield DruidEvent on_change_state @{DruidEvent}
|
||||
|
||||
--- Visual node
|
||||
-- @tfield node node
|
||||
|
||||
--- Button trigger node
|
||||
-- @tfield[opt=node] node click_node
|
||||
|
||||
--- Button component from click_node
|
||||
-- @tfield Button button @{Button}
|
||||
|
||||
---
|
||||
|
||||
local helper = require("druid.helper")
|
||||
local component = require("druid.component")
|
||||
|
||||
local Hotkey = component.create("hotkey")
|
||||
|
||||
|
||||
--- Component init function
|
||||
-- @tparam Hotkey self @{Hotkey}
|
||||
-- @tparam string[]|string keys The keys to be pressed for trigger callback. Should contains one key and any modificator keys
|
||||
-- @tparam function callback The callback function
|
||||
function Hotkey.init(self, keys, callback, callback_argument)
|
||||
self.druid = self:get_druid()
|
||||
|
||||
self._hotkeys = {}
|
||||
self._modificators = {}
|
||||
self._callback = callback
|
||||
|
||||
if keys then
|
||||
self:add_hotkey(keys, callback_argument)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- Component style params.
|
||||
-- You can override this component styles params in druid styles table
|
||||
-- or create your own style
|
||||
-- @table style
|
||||
-- @tfield string[] MODIFICATORS The list of action_id as hotkey modificators
|
||||
function Hotkey.on_style_change(self, style)
|
||||
self.style = {}
|
||||
self.style.MODIFICATORS = style.MODIFICATORS or {}
|
||||
|
||||
for index = 1, #style.MODIFICATORS do
|
||||
self.style.MODIFICATORS[index] = hash(self.style.MODIFICATORS[index])
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- Add hotkey for component callback
|
||||
-- @tparam Hotkey self @{Hotkey}
|
||||
-- @tparam string[]|hash[]|string|hash Keys that have to be pressed before key pressed to activate
|
||||
function Hotkey.add_hotkey(self, keys, callback_argument)
|
||||
keys = keys or {}
|
||||
if type(keys) == "string" then
|
||||
keys = { keys }
|
||||
end
|
||||
|
||||
local modificators = {}
|
||||
local key = nil
|
||||
|
||||
for index = 1, #keys do
|
||||
local key_hash = hash(keys[index])
|
||||
if helper.contains(self.style.MODIFICATORS, key_hash) then
|
||||
table.insert(modificators, key_hash)
|
||||
else
|
||||
if not key then
|
||||
key = key_hash
|
||||
else
|
||||
error("The hotkey keys should contains only one key (except modificator keys)")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
table.insert(self._hotkeys, {
|
||||
modificators = modificators,
|
||||
key = key,
|
||||
is_processing = false,
|
||||
callback_argument = callback_argument,
|
||||
})
|
||||
|
||||
-- Current hotkey status
|
||||
for index = 1, #self.style.MODIFICATORS do
|
||||
local modificator = hash(self.style.MODIFICATORS[index])
|
||||
self._modificators[modificator] = self._modificators[modificator] or false
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
function Hotkey.on_input(self, action_id, action)
|
||||
if not action_id then
|
||||
return
|
||||
end
|
||||
|
||||
if self._modificators[action_id] ~= nil then
|
||||
if action.pressed then
|
||||
self._modificators[action_id] = true
|
||||
end
|
||||
if action.released then
|
||||
self._modificators[action_id] = false
|
||||
end
|
||||
end
|
||||
|
||||
for index = 1, #self._hotkeys do
|
||||
local hotkey = self._hotkeys[index]
|
||||
if action_id == hotkey.key then
|
||||
local is_modificator_ok = true
|
||||
|
||||
-- Check only required modificators pressed
|
||||
for i = 1, #self.style.MODIFICATORS do
|
||||
local mod = self.style.MODIFICATORS[i]
|
||||
if helper.contains(hotkey.modificators, mod) and self._modificators[mod] == false then
|
||||
is_modificator_ok = false
|
||||
end
|
||||
if not helper.contains(hotkey.modificators, mod) and self._modificators[mod] == true then
|
||||
is_modificator_ok = false
|
||||
end
|
||||
end
|
||||
|
||||
if action.pressed and is_modificator_ok then
|
||||
hotkey.is_processing = 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)
|
||||
else
|
||||
self._callback(self:get_context())
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return Hotkey
|
@@ -281,8 +281,8 @@ function Input.select(self)
|
||||
gui.reset_keyboard()
|
||||
self.marked_value = ""
|
||||
if not self.is_selected then
|
||||
self:set_input_priority(const.PRIORITY_INPUT_MAX)
|
||||
self.button:set_input_priority(const.PRIORITY_INPUT_MAX)
|
||||
self:set_input_priority(const.PRIORITY_INPUT_MAX, true)
|
||||
self.button:set_input_priority(const.PRIORITY_INPUT_MAX, true)
|
||||
self.previous_value = self.value
|
||||
self.is_selected = true
|
||||
|
||||
|
@@ -14,6 +14,7 @@
|
||||
|
||||
---
|
||||
|
||||
local const = require("druid.const")
|
||||
local Event = require("druid.event")
|
||||
local settings = require("druid.system.settings")
|
||||
local component = require("druid.component")
|
||||
|
134
druid/extended/layout.lua
Normal file
134
druid/extended/layout.lua
Normal file
@@ -0,0 +1,134 @@
|
||||
-- Copyright (c) 2021 Maksim Tuprikov <insality@gmail.com>. This code is licensed under MIT license
|
||||
|
||||
--- Layout management on node
|
||||
-- @module Layout
|
||||
-- @within BaseComponent
|
||||
-- @alias druid.layout
|
||||
|
||||
---
|
||||
|
||||
|
||||
local const = require("druid.const")
|
||||
local helper = require("druid.helper")
|
||||
local component = require("druid.component")
|
||||
local Event = require("druid.event")
|
||||
|
||||
---@class layout : druid.base_component
|
||||
local Layout = component.create("layout")
|
||||
|
||||
|
||||
function Layout:init(node, mode, on_size_changed_callback)
|
||||
self.node = self:get_node(node)
|
||||
|
||||
self._min_size = nil
|
||||
self._max_size = nil
|
||||
self._inited = false
|
||||
|
||||
self.gui_size = vmath.vector3(gui.get_width(), gui.get_height(), 0)
|
||||
self.mode = mode or const.LAYOUT_MODE.FIT
|
||||
|
||||
self.on_size_changed = Event(on_size_changed_callback)
|
||||
end
|
||||
|
||||
|
||||
function Layout:on_late_init()
|
||||
self._inited = true
|
||||
self.origin_size = self.origin_size or gui.get_size(self.node)
|
||||
self.fit_size = self.fit_size or vmath.vector3(self.origin_size)
|
||||
self.pivot = helper.get_pivot_offset(gui.get_pivot(self.node))
|
||||
self.origin_position = gui.get_position(self.node)
|
||||
self.position = vmath.vector3(self.origin_position)
|
||||
gui.set_size_mode(self.node, gui.SIZE_MODE_MANUAL)
|
||||
gui.set_adjust_mode(self.node, gui.ADJUST_FIT)
|
||||
self:on_window_resized()
|
||||
end
|
||||
|
||||
|
||||
function Layout:on_window_resized()
|
||||
if not self._inited then
|
||||
return
|
||||
end
|
||||
|
||||
local window_x, window_y = window.get_size()
|
||||
local stretch_x = window_x / self.gui_size.x
|
||||
local stretch_y = window_y / self.gui_size.y
|
||||
|
||||
local x_koef = self.fit_size.x / self.origin_size.x * stretch_x / math.min(stretch_x, stretch_y)
|
||||
local y_koef = self.fit_size.y / self.origin_size.y * stretch_y / math.min(stretch_x, stretch_y)
|
||||
|
||||
local new_size = vmath.vector3(self.origin_size)
|
||||
|
||||
if self.mode == const.LAYOUT_MODE.STRETCH_X or self.mode == const.LAYOUT_MODE.STRETCH then
|
||||
new_size.x = new_size.x * x_koef
|
||||
end
|
||||
if self.mode == const.LAYOUT_MODE.STRETCH_Y or self.mode == const.LAYOUT_MODE.STRETCH then
|
||||
new_size.y = new_size.y * y_koef
|
||||
end
|
||||
|
||||
-- Fit to the stretched container (node size or other defined)
|
||||
if self.mode == const.LAYOUT_MODE.ZOOM_MIN then
|
||||
new_size = new_size * math.min(x_koef, y_koef)
|
||||
end
|
||||
if self.mode == const.LAYOUT_MODE.ZOOM_MAX then
|
||||
new_size = new_size * math.max(x_koef, y_koef)
|
||||
end
|
||||
|
||||
if self._min_size then
|
||||
new_size.x = math.max(new_size.x, self._min_size.x)
|
||||
new_size.y = math.max(new_size.y, self._min_size.y)
|
||||
end
|
||||
if self._max_size then
|
||||
new_size.x = math.min(new_size.x, self._max_size.x)
|
||||
new_size.y = math.min(new_size.y, self._max_size.y)
|
||||
end
|
||||
gui.set_size(self.node, new_size)
|
||||
|
||||
self.position.x = self.origin_position.x + self.origin_position.x * (x_koef - 1)
|
||||
self.position.y = self.origin_position.y + self.origin_position.y * (y_koef - 1)
|
||||
gui.set_position(self.node, self.position)
|
||||
|
||||
self.on_size_changed:trigger(self:get_context(), new_size)
|
||||
end
|
||||
|
||||
|
||||
function Layout:set_min_size(min_size)
|
||||
self._min_size = min_size
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
function Layout:set_max_size(max_size)
|
||||
self._max_size = max_size
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
function Layout:set_origin_position(new_origin_position)
|
||||
self.origin_position = new_origin_position or self.origin_position
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
function Layout:set_origin_size(new_origin_size)
|
||||
self.origin_size = new_origin_size or self.origin_size
|
||||
self:on_window_resized()
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
function Layout:fit_into_size(target_size)
|
||||
self.fit_size = target_size
|
||||
self:on_window_resized()
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
function Layout:fit_into_window()
|
||||
return self:fit_into_size(vmath.vector3(
|
||||
gui.get_width(),
|
||||
gui.get_height(),
|
||||
0))
|
||||
end
|
||||
|
||||
|
||||
return Layout
|
@@ -103,11 +103,14 @@ function Progress.init(self, node, key, init_value)
|
||||
self.prop = hash("scale."..key)
|
||||
self.key = key
|
||||
|
||||
self._init_value = init_value or 1
|
||||
self.node = self:get_node(node)
|
||||
self.scale = gui.get_scale(self.node)
|
||||
self.size = gui.get_size(self.node)
|
||||
self.max_size = self.size[self.key]
|
||||
self.slice = gui.get_slice9(self.node)
|
||||
self.last_value = self._init_value
|
||||
|
||||
if key == const.SIDE.X then
|
||||
self.slice_size = self.slice.x + self.slice.z
|
||||
else
|
||||
@@ -115,8 +118,12 @@ function Progress.init(self, node, key, init_value)
|
||||
end
|
||||
|
||||
self.on_change = Event()
|
||||
end
|
||||
|
||||
self:set_to(init_value or 1)
|
||||
|
||||
-- @tparam Progress self @{Progress}
|
||||
function Progress.on_late_init(self)
|
||||
self:set_to(self._init_value)
|
||||
end
|
||||
|
||||
|
||||
@@ -204,4 +211,15 @@ function Progress.to(self, to, callback)
|
||||
end
|
||||
|
||||
|
||||
--- Set progress bar max node size
|
||||
-- @tparam Progress self @{Progress}
|
||||
-- @tparam vector3 max_size The new node maximum (full) size
|
||||
-- @treturn Progress @{Progress}
|
||||
function Progress:set_max_size(max_size)
|
||||
self.max_size = max_size[self.key]
|
||||
self:set_to(self.last_value)
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
return Progress
|
||||
|
@@ -8,6 +8,7 @@ local const = require("druid.const")
|
||||
|
||||
local M = {}
|
||||
|
||||
|
||||
--- Text node or icon node can be nil
|
||||
local function get_text_width(text_node)
|
||||
if text_node then
|
||||
@@ -97,6 +98,15 @@ function M.centrate_nodes(margin, ...)
|
||||
end
|
||||
|
||||
|
||||
function M.get_screen_aspect_koef()
|
||||
local window_x, window_y = window.get_size()
|
||||
local stretch_x = window_x / gui.get_width()
|
||||
local stretch_y = window_y / gui.get_height()
|
||||
return stretch_x / math.min(stretch_x, stretch_y),
|
||||
stretch_y / math.min(stretch_x, stretch_y)
|
||||
end
|
||||
|
||||
|
||||
function M.step(current, target, step)
|
||||
if current < target then
|
||||
return math.min(current + step, target)
|
||||
|
@@ -30,6 +30,7 @@
|
||||
-- @see Drag
|
||||
-- @see DataList
|
||||
-- @see Hover
|
||||
-- @see Layout
|
||||
|
||||
local helper = require("druid.helper")
|
||||
local class = require("druid.system.middleclass")
|
||||
@@ -57,6 +58,7 @@ local radio_group = require("druid.extended.radio_group")
|
||||
local slider = require("druid.extended.slider")
|
||||
local timer = require("druid.extended.timer")
|
||||
local data_list = require("druid.extended.data_list")
|
||||
local layout = require("druid.extended.layout")
|
||||
|
||||
|
||||
local DruidInstance = class("druid.druid_instance")
|
||||
@@ -738,4 +740,14 @@ function DruidInstance.new_progress(self, node, key, init_value)
|
||||
end
|
||||
|
||||
|
||||
--- Create layout component
|
||||
-- @tparam DruidInstance self
|
||||
-- @tparam string|node node Layout node
|
||||
-- @tparam string mode The layout mode
|
||||
-- @treturn Layout layout component
|
||||
function DruidInstance.new_layout(self, node, mode)
|
||||
return helper.extended_component("layout")
|
||||
end
|
||||
|
||||
|
||||
return DruidInstance
|
||||
|
Reference in New Issue
Block a user