mirror of https://github.com/minetest/minetest.git
201 lines
5.8 KiB
Lua
201 lines
5.8 KiB
Lua
--[[
|
|
Minetest
|
|
Copyright (C) 2023 v-rob, Vincent Robinson <robinsonvincent89@gmail.com>
|
|
|
|
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.
|
|
--]]
|
|
|
|
ui.Style = core.class()
|
|
|
|
function ui.Style:new(props)
|
|
self._sel = ui._parse_sel(props.sel or "*")
|
|
self._props = ui._cascade_props(props.props or props, {})
|
|
self._nested = table.merge(props.nested or props)
|
|
self._reset = props.reset
|
|
end
|
|
|
|
function ui.Style:_get_flat()
|
|
local flat_styles = {}
|
|
self:_get_flat_impl(flat_styles, ui._parse_sel("*"))
|
|
return flat_styles
|
|
end
|
|
|
|
function ui.Style:_get_flat_impl(flat_styles, parent_sel)
|
|
-- Intersect our selector with our parent selector, resulting in a fully
|
|
-- qualified selector.
|
|
local full_sel = ui._intersect_sels({parent_sel, self._sel})
|
|
|
|
-- Copy this style's properties into a new style with the full selector.
|
|
local flat = ui.Style{
|
|
reset = self._reset,
|
|
props = self._props,
|
|
}
|
|
flat._sel = full_sel
|
|
|
|
table.insert(flat_styles, flat)
|
|
|
|
-- For each sub-style of this style, cascade it with our full selector and
|
|
-- add it to the list of flat styles.
|
|
for _, nested in ipairs(self._nested) do
|
|
nested:_get_flat_impl(flat_styles, full_sel)
|
|
end
|
|
end
|
|
|
|
local function cascade_layer(new, add, props, p)
|
|
new[p.."_image"] = add[p.."_image"] or props[p.."_image"]
|
|
new[p.."_fill"] = add[p.."_fill"] or props[p.."_fill"]
|
|
new[p.."_tint"] = add[p.."_tint"] or props[p.."_tint"]
|
|
|
|
new[p.."_source"] = add[p.."_source"] or props[p.."_source"]
|
|
new[p.."_middle"] = add[p.."_middle"] or props[p.."_middle"]
|
|
new[p.."_middle_scale"] = add[p.."_middle_scale"] or props[p.."_middle_scale"]
|
|
|
|
new[p.."_frames"] = add[p.."_frames"] or props[p.."_frames"]
|
|
new[p.."_frame_time"] = add[p.."_frame_time"] or props[p.."_frame_time"]
|
|
end
|
|
|
|
function ui._cascade_props(add, props)
|
|
local new = {}
|
|
|
|
new.size = add.size or props.size
|
|
|
|
new.rel_pos = add.rel_pos or props.rel_pos
|
|
new.rel_anchor = add.rel_anchor or props.rel_anchor
|
|
new.rel_size = add.rel_size or props.rel_size
|
|
|
|
new.margin = add.margin or props.margin
|
|
new.padding = add.padding or props.padding
|
|
|
|
cascade_layer(new, add, props, "bg")
|
|
cascade_layer(new, add, props, "fg")
|
|
|
|
new.fg_scale = add.fg_scale or props.fg_scale
|
|
new.fg_halign = add.fg_halign or props.fg_halign
|
|
new.fg_valign = add.fg_valign or props.fg_valign
|
|
|
|
new.visible = ui._apply_bool(add.visible, props.visible)
|
|
new.noclip = ui._apply_bool(add.noclip, props.noclip)
|
|
|
|
return new
|
|
end
|
|
|
|
local halign_map = {left = 0, center = 1, right = 2}
|
|
local valign_map = {top = 0, center = 1, bottom = 2}
|
|
local spacing_map = {
|
|
before = 0,
|
|
after = 1,
|
|
outside = 2,
|
|
around = 3,
|
|
between = 4,
|
|
evenly = 5,
|
|
remove = 6,
|
|
}
|
|
|
|
local function encode_layer(props, p)
|
|
local fl = ui._make_flags()
|
|
|
|
if ui._shift_flag(fl, props[p.."_image"]) then
|
|
ui._encode_flag(fl, "z", props[p.."_image"])
|
|
end
|
|
if ui._shift_flag(fl, props[p.."_fill"]) then
|
|
ui._encode_flag(fl, "I", core.colorspec_to_colorint(props[p.."_fill"]))
|
|
end
|
|
if ui._shift_flag(fl, props[p.."_tint"]) then
|
|
ui._encode_flag(fl, "I", core.colorspec_to_colorint(props[p.."_tint"]))
|
|
end
|
|
|
|
if ui._shift_flag(fl, props[p.."_source"]) then
|
|
ui._encode_flag(fl, "ffff", unpack(props[p.."_source"]))
|
|
end
|
|
if ui._shift_flag(fl, props[p.."_middle"]) then
|
|
ui._encode_flag(fl, "ffff", unpack(props[p.."_middle"]))
|
|
end
|
|
if ui._shift_flag(fl, props[p.."_middle_scale"]) then
|
|
ui._encode_flag(fl, "f", props[p.."_middle_scale"])
|
|
end
|
|
|
|
if ui._shift_flag(fl, props[p.."_frames"]) then
|
|
ui._encode_flag(fl, "I", props[p.."_frames"])
|
|
end
|
|
if ui._shift_flag(fl, props[p.."_frame_time"]) then
|
|
ui._encode_flag(fl, "I", props[p.."_frame_time"])
|
|
end
|
|
|
|
return fl
|
|
end
|
|
|
|
function ui._encode_props(props)
|
|
local fl = ui._make_flags()
|
|
|
|
if ui._shift_flag(fl, props.size) then
|
|
ui._encode_flag(fl, "ff", unpack(props.size))
|
|
end
|
|
|
|
if ui._shift_flag(fl, props.rel_pos) then
|
|
ui._encode_flag(fl, "ff", unpack(props.rel_pos))
|
|
end
|
|
if ui._shift_flag(fl, props.rel_anchor) then
|
|
ui._encode_flag(fl, "ff", unpack(props.rel_anchor))
|
|
end
|
|
if ui._shift_flag(fl, props.rel_size) then
|
|
ui._encode_flag(fl, "ff", unpack(props.rel_size))
|
|
end
|
|
|
|
if ui._shift_flag(fl, props.margin) then
|
|
ui._encode_flag(fl, "ffff", unpack(props.margin))
|
|
end
|
|
if ui._shift_flag(fl, props.padding) then
|
|
ui._encode_flag(fl, "ffff", unpack(props.padding))
|
|
end
|
|
|
|
local bg_fl = encode_layer(props, "bg")
|
|
if ui._shift_flag(fl, bg_fl.flags ~= 0) then
|
|
ui._encode_flag(fl, "s", ui._encode_flags(bg_fl))
|
|
end
|
|
local fg_fl = encode_layer(props, "fg")
|
|
if ui._shift_flag(fl, fg_fl.flags ~= 0) then
|
|
ui._encode_flag(fl, "s", ui._encode_flags(fg_fl))
|
|
end
|
|
|
|
if ui._shift_flag(fl, props.fg_scale) then
|
|
ui._encode_flag(fl, "f", props.fg_scale)
|
|
end
|
|
if ui._shift_flag(fl, props.fg_halign) then
|
|
ui._encode_flag(fl, "B", halign_map[props.fg_halign])
|
|
end
|
|
if ui._shift_flag(fl, props.fg_valign) then
|
|
ui._encode_flag(fl, "B", valign_map[props.fg_valign])
|
|
end
|
|
|
|
if ui._shift_flag(fl, props.visible ~= nil) then
|
|
ui._shift_flag(fl, props.visible)
|
|
end
|
|
if ui._shift_flag(fl, props.noclip ~= nil) then
|
|
ui._shift_flag(fl, props.noclip)
|
|
end
|
|
|
|
return ui._encode("s", ui._encode_flags(fl))
|
|
end
|
|
|
|
local default_theme = ui.Style{}
|
|
|
|
function ui.get_default_theme()
|
|
return default_theme
|
|
end
|
|
|
|
function ui.set_default_theme(theme)
|
|
default_theme = theme
|
|
end
|