Compare commits
15 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
dad54d8de3 | ||
|
7f5be3ffb0 | ||
|
5d3625e2a8 | ||
|
ec15ac053a | ||
|
337a43ae08 | ||
|
fadd0c4c4b | ||
|
5480f175bf | ||
|
c766dc7ba4 | ||
|
13f0922ccc | ||
|
dac1218809 | ||
|
999789c1c8 | ||
|
253ea36817 | ||
|
b5b07cb8d9 | ||
|
bbd41659f9 | ||
|
2e9353afeb |
13
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: insality # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: insality # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
77
README.md
@@ -1,5 +1,8 @@
|
||||
|
||||
[](https://insality.github.io/druid/)
|
||||
|
||||
[](https://github.com/sponsors/insality) [](https://ko-fi.com/insality) [](https://www.buymeacoffee.com/insality)
|
||||
|
||||
[](https://github.com/Insality/druid/releases)
|
||||
[](https://github.com/Insality/druid/actions)
|
||||
[](https://codecov.io/gh/Insality/druid)
|
||||
@@ -115,51 +118,36 @@ druid.on_window_callback(event)
|
||||
|
||||
## Components
|
||||
|
||||
**Druid** provides the following *basic* components:
|
||||
Here is full **Druid** components list:
|
||||
|
||||
- **[Button](docs_md/01-components.md#button)** - Basic Druid button input component. Handles all types of interactions (tap, long-tap, hold-tap, double-tap, simple key triggers, etc)
|
||||
| Name | Description | API page | Example Link | Is Basic component[^1] | Preview |
|
||||
|------|-------------|----------|------------|-------------|---------|
|
||||
| **[Button](docs_md/01-components.md#button)** | Basic input component. Handles all types of interactions: click, long click, hold click, double click, etc | [Button API](https://insality.github.io/druid/modules/Button.html) | [Button Example](https://insality.github.io/druid/druid/?example=general_buttons) | ✅ | <img src="media/preview/button.gif" width="200" height="100"> |
|
||||
| **[Text](docs_md/01-components.md#text)** | Wrap on GUI text node, handle different text size adjusting, providing additional text API | [Text API](https://insality.github.io/druid/modules/Text.html) | [Text Example](https://insality.github.io/druid/druid/?example=texts_general) | ✅ | <img src="media/preview/text.gif" width="200" height="100"> |
|
||||
| **[Scroll](docs_md/01-components.md#scroll)** | Scroll component | [Scroll API](https://insality.github.io/druid/modules/Scroll.html) | [Scroll Example](https://insality.github.io/druid/druid/?example=general_scroll) | ✅ | <img src="media/preview/scroll.gif" width="200" height="100"> |
|
||||
| **[Blocker](docs_md/01-components.md#blocker)** | Block user input in node zone area | [Blocker API](https://insality.github.io/druid/modules/Blocker.html) | ❌ | ✅ | |
|
||||
| **[Back Handler](docs_md/01-components.md#back-handler)** | Handle back button (Android back button, backspace key) | [Back Handler API](https://insality.github.io/druid/modules/BackHandler.html) | ❌ | ✅ | |
|
||||
| **[Static Grid](docs_md/01-components.md#static-grid)** | Component to manage node positions with equal sizes | [Static Grid API](https://insality.github.io/druid/modules/StaticGrid.html) | [Static Gid Example](https://insality.github.io/druid/druid/?example=general_grid) | ✅ | <img src="media/preview/static_grid.gif" width="200" height="100"> |
|
||||
| **[Hover](docs_md/01-components.md#hover)** | Handle hover node state on node | [Hover API](https://insality.github.io/druid/modules/Hover.html) | ❌ | ✅ | <img src="media/preview/hover.gif" width="200" height="100"> |
|
||||
| **[Swipe](docs_md/01-components.md#swipe)** | Handle swipe gestures on node | [Swipe API](https://insality.github.io/druid/modules/Swipe.html) | [Swipe Example](https://insality.github.io/druid/druid/?example=general_swipe) | ✅ | <img src="media/preview/swipe.gif" width="200" height="100"> |
|
||||
| **[Drag](docs_md/01-components.md#drag)** | Handle drag input on node | [Drag API](https://insality.github.io/druid/modules/Drag.html) | [Drag Example](https://insality.github.io/druid/druid/?example=general_drag) | ✅ | <img src="media/preview/drag.gif" width="200" height="100"> |
|
||||
| **[Checkbox](docs_md/01-components.md#checkbox)** | Checkbox component | [Checkbox API](https://insality.github.io/druid/modules/Checkbox.html) | [Checkbox Example](https://insality.github.io/druid/druid/?example=general_checkboxes) | ❌ | <img src="media/preview/checkbox.gif" width="200" height="100"> |
|
||||
| **[Checkbox group](docs_md/01-components.md#checkbox-group)** | Several checkboxes in one group | [Checkbox group API](https://insality.github.io/druid/modules/CheckboxGroup.html) | [Checkbox group Example](https://insality.github.io/druid/druid/?example=general_checkboxes) | ❌ | <img src="media/preview/checkbox_group.gif" width="200" height="100"> |
|
||||
| **[Radio group](docs_md/01-components.md#radio-group)** | Several checkboxes in one group with a single choice | [Radio group API](https://insality.github.io/druid/modules/RadioGroup.html) | [Radio Group Example](https://insality.github.io/druid/druid/?example=general_checkboxes) | ❌ | <img src="media/preview/radio_group.gif" width="200" height="100"> |
|
||||
| **[Dynamic Grid](docs_md/01-components.md#dynamic-grid)** | Component to manage node positions with different sizes. Only in one row or column | [Dynamic Grid API](https://insality.github.io/druid/modules/DynamicGrid.html) | [Dynamic Grid Example](https://insality.github.io/druid/druid/?example=general_grid) | ❌ | <img src="media/preview/dynamic_grid.gif" width="200" height="100"> |
|
||||
| **[Data List](docs_md/01-components.md#data-list)** | Component to manage data for huge datasets in scroll | [Data List API](https://insality.github.io/druid/modules/DataList.html) | [Data List Example](https://insality.github.io/druid/druid/?example=general_data_list) | ❌ | <img src="media/preview/data_list.gif" width="200" height="100"> |
|
||||
| **[Input](docs_md/01-components.md#input)** | User text input component | [Input API](https://insality.github.io/druid/modules/Input.html) | [Input Example](https://insality.github.io/druid/druid/?example=general_input) | ❌ | <img src="media/preview/input.gif" width="200" height="100"> |
|
||||
| **[Lang text](docs_md/01-components.md#lang-text)** | Wrap on Text component to handle localization | [Lang Text API](https://insality.github.io/druid/modules/LangText.html) | ❌ | ❌ | <img src="media/preview/lang_text.gif" width="200" height="100"> |
|
||||
| **[Progress](docs_md/01-components.md#progress)** | Progress bar component | [Progress API](https://insality.github.io/druid/modules/Progress.html) | [Progress Example](https://insality.github.io/druid/druid/?example=general_progress_bar) | ❌ | <img src="media/preview/progress.gif" width="200" height="100"> |
|
||||
| **[Slider](docs_md/01-components.md#slider)** | Slider component | [Slider API](https://insality.github.io/druid/modules/Slider.html) | [Slider Example](https://insality.github.io/druid/druid/?example=general_sliders) | ❌ | <img src="media/preview/slider.gif" width="200" height="100"> |
|
||||
| **[Timer](docs_md/01-components.md#timer)** | Handle timers on GUI text node | [Timer API](https://insality.github.io/druid/modules/Timer.html) | ❌ | ❌ | <img src="media/preview/timer.gif" width="200" height="100"> |
|
||||
| **[Hotkey](docs_md/01-components.md#hotkey)** | Handle keyboard hotkeys with key modificators | [Hotkey API](https://insality.github.io/druid/modules/Hotkey.html) | [Hotkey Example](https://insality.github.io/druid/druid/?example=general_hokey) | ❌ | <img src="media/preview/hotkey.gif" width="200" height="100"> |
|
||||
| **[Layout](docs_md/01-components.md#layout)** | Handle node size depends on layout mode and screen aspect ratio | [Layout API](https://insality.github.io/druid/modules/Layout.html) | [Layout Example](https://insality.github.io/druid/druid/?example=general_layout) | ❌ | <img src="media/preview/layout.gif" width="200" height="100"> |
|
||||
|
||||
- **[Text](docs_md/01-components.md#text)** - Basic Druid text component. Wrap on gui text node, handle text size adjusting.
|
||||
For a complete overview, see: **_[components.md](docs_md/01-components.md)_**.
|
||||
|
||||
- **[Scroll](docs_md/01-components.md#scroll)** - Basic Druid scroll component
|
||||
[^1]: Non basic components before use should be registered first to be included in build
|
||||
|
||||
- **[Blocker](docs_md/01-components.md#blocker)** - Block input in node zone component
|
||||
|
||||
- **[Back Handler](docs_md/01-components.md#back-handler)** - Handle back button (Android back button, backspace key)
|
||||
|
||||
- **[Static Grid](docs_md/01-components.md#static-grid)** - Component to manage node positions with equal sizes
|
||||
|
||||
- **[Hover](docs_md/01-components.md#hover)** - System Druid component, handle hover node state
|
||||
|
||||
- **[Swipe](docs_md/01-components.md#swipe)** - System Druid component, handle swipe gestures on node
|
||||
|
||||
- **[Drag](docs_md/01-components.md#drag)** - System Druid component, handle drag input on node
|
||||
|
||||
**Druid** also provides the following *extended* components:
|
||||
|
||||
***Note**: In the future, to use extended components, you should register them first. This is required to make **Druid** modular - to exclude unused components from builds*
|
||||
|
||||
- **[Checkbox](docs_md/01-components.md#checkbox)** - Checkbox component
|
||||
|
||||
- **[Checkbox group](docs_md/01-components.md#checkbox-group)** - Several checkboxes in one group
|
||||
|
||||
- **[Dynamic Grid](docs_md/01-components.md#dynamic-grid)** - Component to manage node positions with different sizes. Only in one row or column
|
||||
|
||||
- **[Data List](docs_md/01-components.md#data-list)** - Component to manage data for huge dataset in scroll
|
||||
|
||||
- **[Input](docs_md/01-components.md#input)** - User text input component
|
||||
|
||||
- **[Lang text](docs_md/01-components.md#lang-text)** - Wrap on Text component to handle localization
|
||||
|
||||
- **[Progress](docs_md/01-components.md#progress)** - Progress bar component
|
||||
|
||||
- **[Radio group](docs_md/01-components.md#radio-group)** - Several checkboxes in one group with a single choice
|
||||
|
||||
- **[Slider](docs_md/01-components.md#slider)** - Slider component
|
||||
|
||||
- **[Timer](docs_md/01-components.md#timer)** - Handle timer work on gui text node
|
||||
|
||||
For a complete overview, see: _[components.md](docs_md/01-components.md)_.
|
||||
|
||||
|
||||
## Basic usage
|
||||
@@ -285,3 +273,10 @@ https://insality.github.io/druid/
|
||||
## Issues and suggestions
|
||||
|
||||
If you have any issues, questions or suggestions please [create an issue](https://github.com/Insality/druid/issues) or contact me: [insality@gmail.com](mailto:insality@gmail.com)
|
||||
|
||||
|
||||
## ❤️ Support project ❤️
|
||||
|
||||
Please support me if you like this project! It will help me keep engaged to update **Druid** and make it even better!
|
||||
|
||||
[](https://github.com/sponsors/insality) [](https://ko-fi.com/insality) [](https://www.buymeacoffee.com/insality)
|
||||
|
@@ -560,12 +560,12 @@ end
|
||||
|
||||
function Scroll._set_scroll_position(self, position)
|
||||
local available_extra = self.available_pos_extra
|
||||
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)
|
||||
position.x = helper.clamp(position.x, available_extra.x, available_extra.z)
|
||||
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
|
||||
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)
|
||||
|
@@ -47,6 +47,7 @@
|
||||
|
||||
local Event = require("druid.event")
|
||||
local const = require("druid.const")
|
||||
local helper = require("druid.helper")
|
||||
local utf8 = require("druid.system.utf8")
|
||||
local component = require("druid.component")
|
||||
|
||||
@@ -77,7 +78,7 @@ local function update_text_area_size(self)
|
||||
local max_width = self.text_area.x
|
||||
local max_height = self.text_area.y
|
||||
|
||||
local metrics = gui.get_text_metrics_from_node(self.node)
|
||||
local metrics = helper.get_text_metrics_from_node(self.node)
|
||||
|
||||
local scale_modifier = max_width / metrics.width
|
||||
scale_modifier = math.min(scale_modifier, self.start_scale.x)
|
||||
@@ -133,8 +134,8 @@ end
|
||||
-- calculate space width with font
|
||||
local function get_space_width(self, font)
|
||||
if not self._space_width[font] then
|
||||
local no_space = gui.get_text_metrics(font, "1", 0, false, 0, 0).width
|
||||
local with_space = gui.get_text_metrics(font, " 1", 0, false, 0, 0).width
|
||||
local no_space = resource.get_text_metrics(font, "1").width
|
||||
local with_space = resource.get_text_metrics(font, " 1").width
|
||||
self._space_width[font] = with_space - no_space
|
||||
end
|
||||
|
||||
|
@@ -87,6 +87,7 @@ end
|
||||
-- @tfield[opt=false] bool IS_LONGTAP_ERASE Is long tap will erase current input data
|
||||
-- @tfield[opt=*] string MASK_DEFAULT_CHAR Default character mask for password input
|
||||
-- @tfield[opt=false] bool IS_UNSELECT_ON_RESELECT If true, call unselect on select selected input
|
||||
-- @tfield[opt=false] bool NO_CONSUME_INPUT_WHILE_SELECTED If true, will not consume input while input is selected. It's allow to interact with other components while input is selected (text input still captured)
|
||||
-- @tfield function on_select (self, button_node) Callback on input field selecting
|
||||
-- @tfield function on_unselect (self, button_node) Callback on input field unselecting
|
||||
-- @tfield function on_input_wrong (self, button_node) Callback on wrong user input
|
||||
@@ -97,6 +98,7 @@ function Input.on_style_change(self, style)
|
||||
self.style.IS_LONGTAP_ERASE = style.IS_LONGTAP_ERASE or false
|
||||
self.style.MASK_DEFAULT_CHAR = style.MASK_DEFAULT_CHAR or "*"
|
||||
self.style.IS_UNSELECT_ON_RESELECT = style.IS_UNSELECT_ON_RESELECT or false
|
||||
self.style.NO_CONSUME_INPUT_WHILE_SELECTED = style.NO_CONSUME_INPUT_WHILE_SELECTED or false
|
||||
|
||||
self.style.on_select = style.on_select or function(_, button_node) end
|
||||
self.style.on_unselect = style.on_unselect or function(_, button_node) end
|
||||
@@ -214,7 +216,8 @@ function Input.on_input(self, action_id, action)
|
||||
end
|
||||
end
|
||||
|
||||
return self.is_selected
|
||||
local is_consume_input = not self.style.NO_CONSUME_INPUT_WHILE_SELECTED and self.is_selected
|
||||
return is_consume_input
|
||||
end
|
||||
|
||||
|
||||
|
@@ -121,12 +121,8 @@ function Progress.init(self, node, key, init_value)
|
||||
end
|
||||
|
||||
self.on_change = Event()
|
||||
end
|
||||
|
||||
|
||||
-- @tparam Progress self @{Progress}
|
||||
function Progress.on_late_init(self)
|
||||
self:set_to(self._init_value)
|
||||
self:set_to(self.last_value)
|
||||
end
|
||||
|
||||
|
||||
|
@@ -12,7 +12,7 @@ local M = {}
|
||||
--- Text node or icon node can be nil
|
||||
local function get_text_width(text_node)
|
||||
if text_node then
|
||||
local text_metrics = gui.get_text_metrics_from_node(text_node)
|
||||
local text_metrics = M.get_text_metrics_from_node(text_node)
|
||||
local text_scale = gui.get_scale(text_node).x
|
||||
return text_metrics.width * text_scale
|
||||
end
|
||||
@@ -280,6 +280,23 @@ function M.get_border(node, offset)
|
||||
end
|
||||
|
||||
|
||||
function M.get_text_metrics_from_node(node)
|
||||
local font_resource = gui.get_font_resource(gui.get_font(node))
|
||||
local options = {
|
||||
tracking = gui.get_tracking(node),
|
||||
line_break = gui.get_line_break(node),
|
||||
}
|
||||
|
||||
-- Gather other options only if it used in node
|
||||
if options.line_break then
|
||||
options.width = gui.get_size(node).x
|
||||
options.leading = gui.get_leading(node)
|
||||
end
|
||||
|
||||
return resource.get_text_metrics(font_resource, gui.get_text(node), options)
|
||||
end
|
||||
|
||||
|
||||
--- Show deprecated message. Once time per message
|
||||
-- @function helper.deprecated
|
||||
-- @tparam string message The deprecated message
|
||||
|
@@ -113,6 +113,7 @@ M["input"] = {
|
||||
BUTTON_SELECT_INCREASE = 1.06,
|
||||
MASK_DEFAULT_CHAR = "*",
|
||||
IS_UNSELECT_ON_RESELECT = false,
|
||||
NO_CONSUME_INPUT_WHILE_SELECTED = false,
|
||||
|
||||
on_select = function(self, button_node)
|
||||
local target_scale = self.button.start_scale
|
||||
|
@@ -569,7 +569,7 @@ end
|
||||
-- @tparam node node Gui text node
|
||||
-- @tparam[opt] string value Initial text. Default value is node text from GUI scene.
|
||||
-- @tparam[opt] bool no_adjust If true, text will be not auto-adjust size
|
||||
-- @treturn Tet text component
|
||||
-- @treturn Text text component
|
||||
function DruidInstance.new_text(self, node, value, no_adjust)
|
||||
return DruidInstance.new(self, text, node, value, no_adjust)
|
||||
end
|
||||
|
BIN
media/preview/button.gif
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
media/preview/checkbox.gif
Normal file
After Width: | Height: | Size: 6.9 KiB |
BIN
media/preview/checkbox_group.gif
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
media/preview/data_list.gif
Normal file
After Width: | Height: | Size: 72 KiB |
BIN
media/preview/drag.gif
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
media/preview/dynamic_grid.gif
Normal file
After Width: | Height: | Size: 34 KiB |
BIN
media/preview/hotkey.gif
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
media/preview/hover.gif
Normal file
After Width: | Height: | Size: 7.1 KiB |
BIN
media/preview/input.gif
Normal file
After Width: | Height: | Size: 7.2 KiB |
BIN
media/preview/lang_text.gif
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
media/preview/layout.gif
Normal file
After Width: | Height: | Size: 115 KiB |
BIN
media/preview/progress.gif
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
media/preview/radio_group.gif
Normal file
After Width: | Height: | Size: 7.1 KiB |
BIN
media/preview/scroll.gif
Normal file
After Width: | Height: | Size: 128 KiB |
BIN
media/preview/slider.gif
Normal file
After Width: | Height: | Size: 49 KiB |
BIN
media/preview/static_grid.gif
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
media/preview/swipe.gif
Normal file
After Width: | Height: | Size: 9.9 KiB |
BIN
media/preview/text.gif
Normal file
After Width: | Height: | Size: 42 KiB |
BIN
media/preview/timer.gif
Normal file
After Width: | Height: | Size: 4.5 KiB |