2022-06-11 20:44:31 +00:00
|
|
|
-- Spinbox Numeric Graphics Element
|
|
|
|
|
|
|
|
local util = require("scada-common.util")
|
|
|
|
|
2022-11-25 03:49:35 +00:00
|
|
|
local element = require("graphics.element")
|
|
|
|
|
2022-06-11 20:44:31 +00:00
|
|
|
---@class spinbox_args
|
|
|
|
---@field default? number default value, defaults to 0.0
|
2022-11-17 16:58:14 +00:00
|
|
|
---@field min? number default 0, currently must be 0 or greater
|
|
|
|
---@field max? number default max number that can be displayed with the digits configuration
|
2022-06-11 20:44:31 +00:00
|
|
|
---@field whole_num_precision integer number of whole number digits
|
|
|
|
---@field fractional_precision integer number of fractional digits
|
|
|
|
---@field arrow_fg_bg cpair arrow foreground/background colors
|
|
|
|
---@field parent graphics_element
|
2022-07-28 14:09:34 +00:00
|
|
|
---@field id? string element id
|
2022-06-11 20:44:31 +00:00
|
|
|
---@field x? integer 1 if omitted
|
|
|
|
---@field y? integer 1 if omitted
|
2022-06-11 21:06:32 +00:00
|
|
|
---@field fg_bg? cpair foreground/background colors
|
2022-06-11 20:44:31 +00:00
|
|
|
|
2022-07-24 00:08:52 +00:00
|
|
|
-- new spinbox control (minimum value is 0)
|
2022-06-11 20:44:31 +00:00
|
|
|
---@param args spinbox_args
|
2022-07-28 14:09:34 +00:00
|
|
|
---@return graphics_element element, element_id id
|
2022-06-11 20:44:31 +00:00
|
|
|
local function spinbox(args)
|
|
|
|
-- properties
|
|
|
|
local digits = {}
|
|
|
|
local wn_prec = args.whole_num_precision
|
|
|
|
local fr_prec = args.fractional_precision
|
|
|
|
|
2022-06-16 15:19:32 +00:00
|
|
|
assert(util.is_int(wn_prec), "graphics.element.controls.spinbox_numeric: whole number precision must be an integer")
|
|
|
|
assert(util.is_int(fr_prec), "graphics.element.controls.spinbox_numeric: fractional precision must be an integer")
|
2022-06-11 20:44:31 +00:00
|
|
|
|
2022-07-24 00:08:52 +00:00
|
|
|
local fmt = "%" .. (wn_prec + fr_prec + 1) .. "." .. fr_prec .. "f"
|
|
|
|
local fmt_init = "%0" .. (wn_prec + fr_prec + 1) .. "." .. fr_prec .. "f"
|
2022-07-16 17:25:07 +00:00
|
|
|
local dec_point_x = args.whole_num_precision + 1
|
|
|
|
|
2022-06-11 21:06:32 +00:00
|
|
|
assert(type(args.arrow_fg_bg) == "table", "graphics.element.spinbox_numeric: arrow_fg_bg is a required field")
|
|
|
|
|
2022-06-11 20:44:31 +00:00
|
|
|
-- determine widths
|
|
|
|
args.width = wn_prec + fr_prec + util.trinary(fr_prec > 0, 1, 0)
|
|
|
|
args.height = 3
|
|
|
|
|
|
|
|
-- create new graphics element base object
|
|
|
|
local e = element.new(args)
|
|
|
|
|
2022-09-12 16:59:28 +00:00
|
|
|
-- set initial value
|
|
|
|
e.value = args.default or 0.0
|
|
|
|
|
2022-06-11 20:44:31 +00:00
|
|
|
-- draw the arrows
|
|
|
|
e.window.setBackgroundColor(args.arrow_fg_bg.bkg)
|
|
|
|
e.window.setTextColor(args.arrow_fg_bg.fgd)
|
|
|
|
e.window.setCursorPos(1, 1)
|
|
|
|
e.window.write(util.strrep("\x1e", wn_prec))
|
|
|
|
e.window.setCursorPos(1, 3)
|
|
|
|
e.window.write(util.strrep("\x1f", wn_prec))
|
|
|
|
if fr_prec > 0 then
|
2022-07-16 17:25:07 +00:00
|
|
|
e.window.setCursorPos(1 + wn_prec, 1)
|
2022-06-11 20:44:31 +00:00
|
|
|
e.window.write(" " .. util.strrep("\x1e", fr_prec))
|
2022-07-16 17:25:07 +00:00
|
|
|
e.window.setCursorPos(1 + wn_prec, 3)
|
2022-06-11 20:44:31 +00:00
|
|
|
e.window.write(" " .. util.strrep("\x1f", fr_prec))
|
|
|
|
end
|
|
|
|
|
2022-10-07 15:21:17 +00:00
|
|
|
-- populate digits from current value
|
|
|
|
local function set_digits()
|
|
|
|
local initial_str = util.sprintf(fmt_init, e.value)
|
2022-07-24 00:08:52 +00:00
|
|
|
|
2022-11-17 16:58:14 +00:00
|
|
|
digits = {}
|
2022-10-07 15:21:17 +00:00
|
|
|
---@diagnostic disable-next-line: discard-returns
|
|
|
|
initial_str:gsub("%d", function (char) table.insert(digits, char) end)
|
2022-09-12 16:59:28 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
-- update the value per digits table
|
|
|
|
local function update_value()
|
|
|
|
e.value = 0
|
|
|
|
for i = 1, #digits do
|
|
|
|
local pow = math.abs(wn_prec - i)
|
|
|
|
if i <= wn_prec then
|
|
|
|
e.value = e.value + (digits[i] * (10 ^ pow))
|
|
|
|
else
|
|
|
|
e.value = e.value + (digits[i] * (10 ^ -pow))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-10-07 15:21:17 +00:00
|
|
|
-- print out the current value
|
|
|
|
local function show_num()
|
|
|
|
-- enforce limits
|
2022-09-12 16:59:28 +00:00
|
|
|
-- min 0
|
|
|
|
if e.value < 0 then
|
2022-10-07 15:21:17 +00:00
|
|
|
for i = 1, #digits do digits[i] = 0 end
|
|
|
|
e.value = 0
|
2022-11-17 16:58:14 +00:00
|
|
|
-- min configured
|
|
|
|
elseif (type(args.min) == "number") and (e.value < args.min) then
|
|
|
|
-- cap at min
|
|
|
|
e.value = args.min
|
|
|
|
set_digits()
|
|
|
|
else
|
|
|
|
-- max printable
|
|
|
|
if string.len(util.sprintf(fmt, e.value)) > args.width then
|
|
|
|
-- max out to all 9s
|
|
|
|
for i = 1, #digits do digits[i] = 9 end
|
|
|
|
update_value()
|
|
|
|
-- max configured
|
|
|
|
elseif (type(args.max) == "number") and (e.value > args.max) then
|
|
|
|
-- cap at max
|
|
|
|
e.value = args.max
|
|
|
|
set_digits()
|
|
|
|
end
|
2022-09-12 16:59:28 +00:00
|
|
|
end
|
|
|
|
|
2022-10-07 15:21:17 +00:00
|
|
|
-- draw
|
|
|
|
e.window.setBackgroundColor(e.fg_bg.bkg)
|
|
|
|
e.window.setTextColor(e.fg_bg.fgd)
|
|
|
|
e.window.setCursorPos(1, 2)
|
|
|
|
e.window.write(util.sprintf(fmt, e.value))
|
2022-07-16 17:25:07 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
-- init with the default value
|
|
|
|
show_num()
|
|
|
|
|
2022-06-11 20:44:31 +00:00
|
|
|
-- handle touch
|
|
|
|
---@param event monitor_touch monitor touch event
|
|
|
|
function e.handle_touch(event)
|
|
|
|
-- only handle if on an increment or decrement arrow
|
2022-10-20 16:22:45 +00:00
|
|
|
if e.enabled and event.x ~= dec_point_x then
|
2022-06-11 20:44:31 +00:00
|
|
|
local idx = util.trinary(event.x > dec_point_x, event.x - 1, event.x)
|
2022-11-17 16:58:14 +00:00
|
|
|
if digits[idx] ~= nil then
|
|
|
|
if event.y == 1 then
|
|
|
|
-- increment
|
|
|
|
digits[idx] = digits[idx] + 1
|
|
|
|
elseif event.y == 3 then
|
|
|
|
-- decrement
|
|
|
|
digits[idx] = digits[idx] - 1
|
|
|
|
end
|
|
|
|
|
|
|
|
update_value()
|
|
|
|
show_num()
|
2022-06-11 20:44:31 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-09-12 16:59:28 +00:00
|
|
|
-- set the value
|
|
|
|
---@param val number number to show
|
|
|
|
function e.set_value(val)
|
|
|
|
e.value = val
|
2022-10-07 15:21:17 +00:00
|
|
|
|
|
|
|
set_digits()
|
|
|
|
show_num()
|
2022-09-12 16:59:28 +00:00
|
|
|
end
|
2022-06-11 20:44:31 +00:00
|
|
|
|
2022-11-17 16:58:14 +00:00
|
|
|
-- set minimum input value
|
|
|
|
---@param min integer minimum allowed value
|
|
|
|
function e.set_min(min)
|
2022-11-17 17:00:00 +00:00
|
|
|
if min >= 0 then
|
|
|
|
args.min = min
|
|
|
|
show_num()
|
|
|
|
end
|
2022-11-17 16:58:14 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
-- set maximum input value
|
|
|
|
---@param max integer maximum allowed value
|
|
|
|
function e.set_max(max)
|
|
|
|
args.max = max
|
2022-11-17 17:00:00 +00:00
|
|
|
show_num()
|
2022-11-17 16:58:14 +00:00
|
|
|
end
|
|
|
|
|
2022-07-28 15:17:34 +00:00
|
|
|
return e.get()
|
2022-06-11 20:44:31 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
return spinbox
|