mirror of
				https://github.com/luanti-org/luanti.git
				synced 2025-11-04 09:15:29 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			174 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			174 lines
		
	
	
		
			5.1 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 SCROLL_BTN_WIDTH = TOUCHSCREEN_GUI and 0.8 or 0.5
 | 
						|
 | 
						|
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*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 + 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 - 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, 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, 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
 |