1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-06-27 16:36:03 +00:00

Fix scrollbar on ContentDB grid by adding an area label (#16042)

Co-authored-by: rubenwardy <rw@rubenwardy.com>
This commit is contained in:
grorp 2025-04-21 06:33:41 -04:00 committed by GitHub
parent 5c6e4d35b0
commit 0cf1c47f6c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 108 additions and 60 deletions

View file

@ -310,9 +310,17 @@ local function get_formspec(dlgdata)
})
local img_w = cell_h * 3 / 2
-- Use as much of the available space as possible (so no padding on the
-- right/bottom), but don't quite allow the text to touch the border.
local text_w = cell_w - img_w - 0.25 - 0.025
local text_h = cell_h - 0.25 - 0.025
local start_idx = (cur_page - 1) * num_per_page + 1
for i=start_idx, math.min(#contentdb.packages, start_idx+num_per_page-1) do
local package = contentdb.packages[i]
local text = core.colorize(mt_color_green, package.title) ..
core.colorize("#BFBFBF", " by " .. package.author) .. "\n" ..
package.short_description
table.insert_all(formspec, {
"container[",
@ -327,13 +335,14 @@ local function get_formspec(dlgdata)
"image[0,0;", img_w, ",", cell_h, ";",
core.formspec_escape(get_screenshot(package, package.thumbnail, 2)), "]",
"label[", img_w + 0.25 + 0.05, ",0.5;",
core.formspec_escape(
core.colorize(mt_color_green, package.title) ..
core.colorize("#BFBFBF", " by " .. package.author)), "]",
"label[", img_w + 0.25, ",0.25;", text_w, ",", text_h, ";",
core.formspec_escape(text), "]",
"textarea[", img_w + 0.25, ",0.75;", cell_w - img_w - 0.25, ",", cell_h - 0.75, ";;;",
core.formspec_escape(package.short_description), "]",
-- Add a tooltip in case the label overflows and the short description is cut off.
"tooltip[", img_w + 0.25, ",0.25;", text_w, ",", text_h, ";",
-- Text in tooltips doesn't wrap automatically, so we do it manually to
-- avoid everything being one long line.
core.formspec_escape(core.wrap_text(package.short_description, 80)), "]",
"style[view_", i, ";border=false]",
"style[view_", i, ":hovered;bgimg=", core.formspec_escape(defaulttexturedir .. "button_hover_semitrans.png"), "]",
@ -349,7 +358,7 @@ local function get_formspec(dlgdata)
end
table.insert_all(formspec, {
"container[", cell_w - 0.625,",", 0.25, "]",
"container[", cell_w - 0.625,",", 0.125, "]",
})
if package.downloading then

View file

@ -2842,6 +2842,9 @@ Version History
* Add field_enter_after_edit[] (experimental)
* Formspec version 8 (5.10.0)
* scroll_container[]: content padding parameter
* Formspec version 9 (5.12.0)
* Add allow_close[]
* label[]: Add "area label" variant
Elements
--------
@ -3154,9 +3157,11 @@ Elements
### `textarea[<X>,<Y>;<W>,<H>;<name>;<label>;<default>]`
* Same as fields above, but with multi-line input
* Text is wrapped to fit within the given bounds.
* If the text overflows, a vertical scrollbar is added.
* If the name is empty, the textarea is read-only and
the background is not shown, which corresponds to a multi-line label.
See also `label[<X>,<Y>;<W>,<H>;<label>]` for an alternative.
### `label[<X>,<Y>;<label>]`
@ -3171,6 +3176,16 @@ Elements
half a coordinate. With the old system, newlines are spaced 2/5 of
an inventory slot.
### `label[<X>,<Y>;<W>,<H>;<label>]`
* The "area label" formspec element displays the text set in `label`
at the specified position and size.
* Text is wrapped to fit within the given bounds.
* If the text overflows, it is currently simply truncated, but this behavior is
subject to change. There is no scrollbar.
* See also `textarea` for an alternative.
* Only available with the new coordinate system.
### `hypertext[<X>,<Y>;<W>,<H>;<name>;<text>]`
* Displays a static formatted text with hyperlinks.
* **Note**: This element is currently unstable and subject to change.

View file

@ -1768,12 +1768,19 @@ void GUIFormSpecMenu::parseHyperText(parserData *data, const std::string &elemen
void GUIFormSpecMenu::parseLabel(parserData* data, const std::string &element)
{
std::vector<std::string> parts;
if (!precheckElement("label", element, 2, 2, parts))
if (!precheckElement("label", element, 2, data->real_coordinates ? 3 : 2, parts))
return;
std::vector<std::string> v_pos = split(parts[0],',');
std::vector<std::string> v_pos = split(parts[0], ',');
MY_CHECKPOS("label", 0);
MY_CHECKPOS("label",0);
bool has_size = parts.size() >= 3;
v2s32 geom;
if (has_size) {
std::vector<std::string> v_geom = split(parts[1], ',');
MY_CHECKGEOM("label", 1);
geom = getRealCoordinateGeometry(v_geom);
}
if(!data->explicit_size)
warningstream<<"invalid use of label without a size[] element"<<std::endl;
@ -1783,53 +1790,8 @@ void GUIFormSpecMenu::parseLabel(parserData* data, const std::string &element)
if (!font)
font = m_font;
EnrichedString str(unescape_string(utf8_to_wide(parts[1])));
size_t str_pos = 0;
for (size_t i = 0; str_pos < str.size(); ++i) {
EnrichedString line = str.getNextLine(&str_pos);
core::rect<s32> rect;
if (data->real_coordinates) {
// Lines are spaced at the distance of 1/2 imgsize.
// This alows lines that line up with the new elements
// easily without sacrificing good line distance. If
// it was one whole imgsize, it would have too much
// spacing.
v2s32 pos = getRealCoordinateBasePos(v_pos);
// Labels are positioned by their center, not their top.
pos.Y += (((float) imgsize.Y) / -2) + (((float) imgsize.Y) * i / 2);
rect = core::rect<s32>(
pos.X, pos.Y,
pos.X + font->getDimension(line.c_str()).Width,
pos.Y + imgsize.Y);
} else {
// Lines are spaced at the nominal distance of
// 2/5 inventory slot, even if the font doesn't
// quite match that. This provides consistent
// form layout, at the expense of sometimes
// having sub-optimal spacing for the font.
// We multiply by 2 and then divide by 5, rather
// than multiply by 0.4, to get exact results
// in the integer cases: 0.4 is not exactly
// representable in binary floating point.
v2s32 pos = getElementBasePos(nullptr);
pos.X += stof(v_pos[0]) * spacing.X;
pos.Y += (stof(v_pos[1]) + 7.0f / 30.0f) * spacing.Y;
pos.Y += ((float) i) * spacing.Y * 2.0 / 5.0;
rect = core::rect<s32>(
pos.X, pos.Y - m_btn_height,
pos.X + font->getDimension(line.c_str()).Width,
pos.Y + m_btn_height);
}
auto add_label = [&](core::rect<s32> rect, const EnrichedString &text,
EGUI_ALIGNMENT align_h, EGUI_ALIGNMENT align_v, bool word_wrap) {
FieldSpec spec(
"",
L"",
@ -1838,9 +1800,10 @@ void GUIFormSpecMenu::parseLabel(parserData* data, const std::string &element)
4
);
gui::IGUIStaticText *e = gui::StaticText::add(Environment,
line, rect, false, false, data->current_parent,
text, rect, false, false, data->current_parent,
spec.fid);
e->setTextAlignment(gui::EGUIA_UPPERLEFT, gui::EGUIA_CENTER);
e->setTextAlignment(align_h, align_v);
e->setWordWrap(word_wrap);
e->setNotClipped(style.getBool(StyleSpec::NOCLIP, false));
e->setOverrideColor(style.getColor(StyleSpec::TEXTCOLOR, video::SColor(0xFFFFFFFF)));
@ -1851,6 +1814,67 @@ void GUIFormSpecMenu::parseLabel(parserData* data, const std::string &element)
// labels should let events through
e->grab();
m_clickthrough_elements.push_back(e);
};
EnrichedString str(unescape_string(utf8_to_wide(parts[has_size ? 2 : 1])));
if (geom == v2s32()) {
size_t str_pos = 0;
for (size_t i = 0; str_pos < str.size(); ++i) {
EnrichedString line = str.getNextLine(&str_pos);
core::rect<s32> rect;
if (data->real_coordinates) {
// Lines are spaced at the distance of 1/2 imgsize.
// This alows lines that line up with the new elements
// easily without sacrificing good line distance. If
// it was one whole imgsize, it would have too much
// spacing.
v2s32 pos = getRealCoordinateBasePos(v_pos);
// Labels are positioned by their center, not their top.
pos.Y += (((float) imgsize.Y) / -2) + (((float) imgsize.Y) * i / 2);
rect = core::rect<s32>(
pos.X, pos.Y,
pos.X + font->getDimension(line.c_str()).Width,
pos.Y + imgsize.Y);
} else {
// Lines are spaced at the nominal distance of
// 2/5 inventory slot, even if the font doesn't
// quite match that. This provides consistent
// form layout, at the expense of sometimes
// having sub-optimal spacing for the font.
// We multiply by 2 and then divide by 5, rather
// than multiply by 0.4, to get exact results
// in the integer cases: 0.4 is not exactly
// representable in binary floating point.
v2s32 pos = getElementBasePos(nullptr);
pos.X += stof(v_pos[0]) * spacing.X;
pos.Y += (stof(v_pos[1]) + 7.0f / 30.0f) * spacing.Y;
pos.Y += ((float) i) * spacing.Y * 2.0 / 5.0;
rect = core::rect<s32>(
pos.X, pos.Y - m_btn_height,
pos.X + font->getDimension(line.c_str()).Width,
pos.Y + m_btn_height);
}
add_label(rect, line, gui::EGUIA_UPPERLEFT, gui::EGUIA_CENTER, false);
}
} else {
v2s32 pos = getRealCoordinateBasePos(v_pos);
core::rect<s32> rect(
pos.X, pos.Y,
pos.X + geom.X,
pos.Y + geom.Y);
add_label(rect, str, gui::EGUIA_UPPERLEFT, gui::EGUIA_UPPERLEFT, true);
}
}

View file

@ -71,4 +71,4 @@
const u16 LATEST_PROTOCOL_VERSION = 48;
// See also formspec [Version History] in doc/lua_api.md
const u16 FORMSPEC_API_VERSION = 8;
const u16 FORMSPEC_API_VERSION = 9;