Initial commit

This commit is contained in:
Patrick Alvin Alcala 2025-06-26 16:53:43 +08:00
commit 209ba130c0
4852 changed files with 1517959 additions and 0 deletions

View file

@ -0,0 +1,237 @@
--
-- NumberBox Widget.
-- @copyright Jefferson Gonzalez
-- @license MIT
--
local core = require "core"
local Widget = require "libraries.widget"
local Button = require "libraries.widget.button"
local TextBox = require "libraries.widget.textbox"
---@class widget.numberbox : widget
---@field private textbox widget.textbox
---@field private decrease_button widget.button
---@field private increase_button widget.button
---@field private minimum number
---@field private maximum number
---@field private step number
local NumberBox = Widget:extend()
---Constructor
---@param parent widget
---@param value number
---@param min? number
---@param max? number
---@param step? number
function NumberBox:new(parent, value, min, max, step)
NumberBox.super.new(self, parent)
self.type_name = "widget.numberbox"
self:set_range(min, max)
self:set_step(step)
self.textbox = TextBox(self, "")
self.textbox.scrollable = true
self.decrease_button = Button(self, "-")
self.increase_button = Button(self, "+")
self:set_value(value)
local this = self
function self.textbox.textview.doc:on_text_change(type)
if not tonumber(this.textbox:get_text()) then
if not this.coroutine_run then
this.coroutine_run = true
core.add_thread(function()
this.textbox:set_text(this.current_text)
this.coroutine_run = false
end)
end
else
this.textbox.placeholder_active = false
this.current_text = this.textbox:get_text()
this:on_change(tonumber(this.current_text))
end
end
function self.textbox:on_mouse_wheel(y)
if self.active then
if y > 0 then this:increase() else this:decrease() end
return true
end
return false
end
function self.decrease_button:on_mouse_pressed(button, x, y, clicks)
if Button.super.on_mouse_pressed(self, button, x, y, clicks) then
this.mouse_is_pressed = true
this:mouse_pressed(false)
return true
end
return false
end
function self.increase_button:on_mouse_pressed(button, x, y, clicks)
if Button.super.on_mouse_pressed(self, button, x, y, clicks) then
this.mouse_is_pressed = true
this:mouse_pressed(true)
return true
end
return false
end
function self.decrease_button:on_mouse_released(button, x, y)
if Button.super.on_mouse_released(self, button, x, y) then
this.mouse_is_pressed = false
return true
end
return false
end
function self.increase_button:on_mouse_released(button, x, y)
if Button.super.on_mouse_released(self, button, x, y) then
this.mouse_is_pressed = false
return true
end
return false
end
self.border.width = 0
self:set_size(
self.textbox:get_width() - 100
+ self.decrease_button:get_width()
+ self.increase_button:get_width()
)
end
---Set a new value.
---@param value number
function NumberBox:set_value(value)
if type(value) == "number" then
self.textbox:set_text(tostring(value))
elseif type(value) == "string" and tonumber(value) then
self.textbox:set_text(value)
else
self.textbox:set_text(tostring(self.minimum))
end
self.textbox.placeholder_active = false
self.current_text = self.textbox:get_text()
self:on_change(tonumber(self.current_text))
end
---Get the current value.
---@return number
function NumberBox:get_value()
return tonumber(self.textbox:get_text()) or self.minimum
end
---Set the minimum and maximum values allowed.
---@param min? number
---@param max? number
function NumberBox:set_range(min, max)
self.minimum = min or math.mininteger
self.maximum = max or math.maxinteger
end
---Set the value used to increase or decrease the number when the
---buttons are pressed.
---@param step number
function NumberBox:set_step(step)
self.step = step or 1
end
---Decrease the current value.
function NumberBox:decrease()
self.textbox.placeholder_active = false
local value = tonumber(self.textbox:get_text()) or self.maximum
if (value - self.step) >= self.minimum then
self:set_value(value - self.step)
end
end
---Increase the current value.
function NumberBox:increase()
self.textbox.placeholder_active = false
local value = tonumber(self.textbox:get_text()) or self.minimum
if (value + self.step) <= self.maximum then
self:set_value(value + self.step)
end
end
---Triggered when the mouse is pressed on the increase/decrease buttons.
---@param increase boolean
function NumberBox:mouse_pressed(increase)
if increase then self:increase() else self:decrease() end
local elapsed = system.get_time() + 0.3
local this = self
core.add_thread(function()
while this.mouse_is_pressed do
if elapsed < system.get_time() then
if increase then
this:increase()
else
this:decrease()
end
core.redraw = true
elapsed = system.get_time() + 0.1
end
coroutine.yield()
end
end)
end
---Overrided to enforce minimum allowed size.
---@param width integer
---@param height? integer Ignored on the number box
function NumberBox:set_size(width, height)
local buttons_w = self.decrease_button:get_width()
+ self.increase_button:get_width()
-- permit a minimum of 100 pixels wide for textbox
if width < (buttons_w + 100) then
width = 100 + buttons_w
end
self.textbox:set_size(width - buttons_w)
NumberBox.super.set_size(
self,
width,
math.max(
self.textbox:get_height(),
self.decrease_button:get_height(),
self.increase_button:get_height()
)
-- TODO: check what causes the need for this border size addition since
-- it shouldn't be needed but for now fixes occasional bottom border cut.
+ self.increase_button.border.width
)
end
function NumberBox:update()
if not NumberBox.super.update(self) then return false end
self:set_size(
self.textbox:get_width()
+ self.decrease_button:get_width()
+ self.increase_button:get_width()
)
self.textbox:set_position(0, 0)
self.decrease_button:set_position(
self.textbox:get_right(),
0
)
self.increase_button:set_position(
self.decrease_button:get_right(),
0
)
return true
end
return NumberBox