mirror of
https://github.com/minetest/minetest.git
synced 2024-11-30 11:33:44 +01:00
34286d77c7
Signed-off-by: David Heidelberg <david@ixit.cz> Co-authored-by: Gregor Parzefall <gregor.parzefall@posteo.de>
176 lines
5.2 KiB
Lua
176 lines
5.2 KiB
Lua
--Minetest
|
|
--Copyright (C) 2014 sapier
|
|
--Copyright (C) 2023 Gregor Parzefall
|
|
--
|
|
--This program is free software; you can redistribute it and/or modify
|
|
--it under the terms of the GNU Lesser General Public License as published by
|
|
--the Free Software Foundation; either version 2.1 of the License, or
|
|
--(at your option) any later version.
|
|
--
|
|
--This program is distributed in the hope that it will be useful,
|
|
--but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
--MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
--GNU Lesser General Public License for more details.
|
|
--
|
|
--You should have received a copy of the GNU Lesser General Public License along
|
|
--with this program; if not, write to the Free Software Foundation, Inc.,
|
|
--51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
|
|
local BASE_SPACING = 0.1
|
|
local function get_scroll_btn_width()
|
|
return core.settings:get_bool("enable_touch") and 0.8 or 0.5
|
|
end
|
|
|
|
local function buttonbar_formspec(self)
|
|
if self.hidden then
|
|
return ""
|
|
end
|
|
|
|
local formspec = {
|
|
"style_type[box;noclip=true]",
|
|
string.format("box[%f,%f;%f,%f;%s]", self.pos.x, self.pos.y, self.size.x,
|
|
self.size.y, self.bgcolor),
|
|
"style_type[box;noclip=false]",
|
|
}
|
|
|
|
local btn_size = self.size.y - 2*BASE_SPACING
|
|
|
|
-- Spacing works like CSS Flexbox with `justify-content: space-evenly;`.
|
|
-- `BASE_SPACING` is used as the minimum spacing, like `gap` in CSS Flexbox.
|
|
|
|
-- The number of buttons per page is always calculated as if the scroll
|
|
-- buttons were visible.
|
|
local avail_space = self.size.x - 2*BASE_SPACING - 2*get_scroll_btn_width()
|
|
local btns_per_page = math.floor((avail_space - BASE_SPACING) / (btn_size + BASE_SPACING))
|
|
|
|
self.num_pages = math.ceil(#self.buttons / btns_per_page)
|
|
self.cur_page = math.min(self.cur_page, self.num_pages)
|
|
local first_btn = (self.cur_page - 1) * btns_per_page + 1
|
|
|
|
local show_scroll_btns = self.num_pages > 1
|
|
|
|
-- In contrast, the button spacing calculation takes hidden scroll buttons
|
|
-- into account.
|
|
local real_avail_space = show_scroll_btns and avail_space or self.size.x
|
|
local btn_spacing = (real_avail_space - btns_per_page * btn_size) / (btns_per_page + 1)
|
|
|
|
local btn_start_x = self.pos.x + btn_spacing
|
|
if show_scroll_btns then
|
|
btn_start_x = btn_start_x + BASE_SPACING + get_scroll_btn_width()
|
|
end
|
|
|
|
for i = first_btn, first_btn + btns_per_page - 1 do
|
|
local btn = self.buttons[i]
|
|
if btn == nil then
|
|
break
|
|
end
|
|
|
|
local btn_pos = {
|
|
x = btn_start_x + (i - first_btn) * (btn_size + btn_spacing),
|
|
y = self.pos.y + BASE_SPACING,
|
|
}
|
|
|
|
table.insert(formspec, string.format("image_button[%f,%f;%f,%f;%s;%s;%s;true;false]tooltip[%s;%s]",
|
|
btn_pos.x, btn_pos.y, btn_size, btn_size, btn.image, btn.name,
|
|
btn.caption, btn.name, btn.tooltip))
|
|
end
|
|
|
|
if show_scroll_btns then
|
|
local btn_prev_pos = {
|
|
x = self.pos.x + BASE_SPACING,
|
|
y = self.pos.y + BASE_SPACING,
|
|
}
|
|
local btn_next_pos = {
|
|
x = self.pos.x + self.size.x - BASE_SPACING - get_scroll_btn_width(),
|
|
y = self.pos.y + BASE_SPACING,
|
|
}
|
|
|
|
table.insert(formspec, string.format("style[%s,%s;noclip=true]",
|
|
self.btn_prev_name, self.btn_next_name))
|
|
|
|
table.insert(formspec, string.format("button[%f,%f;%f,%f;%s;<]",
|
|
btn_prev_pos.x, btn_prev_pos.y, get_scroll_btn_width(), btn_size,
|
|
self.btn_prev_name))
|
|
|
|
table.insert(formspec, string.format("button[%f,%f;%f,%f;%s;>]",
|
|
btn_next_pos.x, btn_next_pos.y, get_scroll_btn_width(), btn_size,
|
|
self.btn_next_name))
|
|
end
|
|
|
|
return table.concat(formspec)
|
|
end
|
|
|
|
local function buttonbar_buttonhandler(self, fields)
|
|
if fields[self.btn_prev_name] and self.cur_page > 1 then
|
|
self.cur_page = self.cur_page - 1
|
|
return true
|
|
end
|
|
|
|
if fields[self.btn_next_name] and self.cur_page < self.num_pages then
|
|
self.cur_page = self.cur_page + 1
|
|
return true
|
|
end
|
|
|
|
for _, btn in ipairs(self.buttons) do
|
|
if fields[btn.name] then
|
|
return self.userbuttonhandler(fields)
|
|
end
|
|
end
|
|
end
|
|
|
|
local buttonbar_metatable = {
|
|
handle_buttons = buttonbar_buttonhandler,
|
|
handle_events = function(self, event) end,
|
|
get_formspec = buttonbar_formspec,
|
|
|
|
hide = function(self) self.hidden = true end,
|
|
show = function(self) self.hidden = false end,
|
|
|
|
delete = function(self) ui.delete(self) end,
|
|
|
|
add_button = function(self, name, caption, image, tooltip)
|
|
if caption == nil then caption = "" end
|
|
if image == nil then image = "" end
|
|
if tooltip == nil then tooltip = "" end
|
|
|
|
table.insert(self.buttons, {
|
|
name = name,
|
|
caption = caption,
|
|
image = image,
|
|
tooltip = tooltip,
|
|
})
|
|
end,
|
|
}
|
|
|
|
buttonbar_metatable.__index = buttonbar_metatable
|
|
|
|
function buttonbar_create(name, pos, size, bgcolor, cbf_buttonhandler)
|
|
assert(type(name) == "string" )
|
|
assert(type(pos) == "table" )
|
|
assert(type(size) == "table" )
|
|
assert(type(bgcolor) == "string" )
|
|
assert(type(cbf_buttonhandler) == "function")
|
|
|
|
local self = {}
|
|
self.type = "addon"
|
|
self.name = name
|
|
self.pos = pos
|
|
self.size = size
|
|
self.bgcolor = bgcolor
|
|
self.userbuttonhandler = cbf_buttonhandler
|
|
|
|
self.hidden = false
|
|
self.buttons = {}
|
|
self.num_pages = 1
|
|
self.cur_page = 1
|
|
|
|
self.btn_prev_name = "btnbar_prev_" .. self.name
|
|
self.btn_next_name = "btnbar_next_" .. self.name
|
|
|
|
setmetatable(self, buttonbar_metatable)
|
|
|
|
ui.add(self)
|
|
return self
|
|
end
|