Formspec: Fix priorities for version < 3 (#9121)

* Formspec: Fix priorities for version < 3

1) Introduce 'priority' to 'FieldSpec'
2) Sort elements based on 'priority'
3) Assign 'name' to the Item Image Button's image to show tooltips again
This commit is contained in:
SmallJoker 2019-11-20 19:39:10 +01:00 committed by GitHub
parent 60bff1e6cb
commit b50a166bb0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 53 additions and 60 deletions

View file

@ -21,8 +21,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <cstdlib> #include <cstdlib>
#include <algorithm> #include <algorithm>
#include <iterator> #include <iterator>
#include <sstream>
#include <limits> #include <limits>
#include <sstream>
#include "guiFormSpecMenu.h" #include "guiFormSpecMenu.h"
#include "constants.h" #include "constants.h"
#include "gamedef.h" #include "gamedef.h"
@ -427,7 +427,8 @@ void GUIFormSpecMenu::parseList(parserData* data, const std::string &element)
"", "",
L"", L"",
L"", L"",
258 + m_fields.size() 258 + m_fields.size(),
3
); );
v2s32 pos; v2s32 pos;
@ -671,7 +672,8 @@ void GUIFormSpecMenu::parseImage(parserData* data, const std::string &element)
name, name,
L"", L"",
L"", L"",
258 + m_fields.size() 258 + m_fields.size(),
1
); );
core::rect<s32> rect(pos, pos + geom); core::rect<s32> rect(pos, pos + geom);
gui::IGUIImage *e = Environment->addImage(rect, this, spec.fid, 0, true); gui::IGUIImage *e = Environment->addImage(rect, this, spec.fid, 0, true);
@ -750,7 +752,8 @@ void GUIFormSpecMenu::parseItemImage(parserData* data, const std::string &elemen
"", "",
L"", L"",
L"", L"",
258 + m_fields.size() 258 + m_fields.size(),
2
); );
spec.ftype = f_ItemImage; spec.ftype = f_ItemImage;
@ -1654,7 +1657,8 @@ void GUIFormSpecMenu::parseLabel(parserData* data, const std::string &element)
"", "",
wlabel_colors, wlabel_colors,
L"", L"",
258 + m_fields.size() 258 + m_fields.size(),
4
); );
gui::IGUIStaticText *e = gui::StaticText::add(Environment, gui::IGUIStaticText *e = gui::StaticText::add(Environment,
spec.flabel.c_str(), rect, false, false, this, spec.fid); spec.flabel.c_str(), rect, false, false, this, spec.fid);
@ -2015,7 +2019,8 @@ void GUIFormSpecMenu::parseItemImageButton(parserData* data, const std::string &
name, name,
utf8_to_wide(label), utf8_to_wide(label),
utf8_to_wide(item_name), utf8_to_wide(item_name),
258 + m_fields.size() 258 + m_fields.size(),
2
); );
gui::IGUIButton *e_btn = GUIButton::addButton(Environment, rect, this, spec_btn.fid, L""); gui::IGUIButton *e_btn = GUIButton::addButton(Environment, rect, this, spec_btn.fid, L"");
@ -2035,10 +2040,11 @@ void GUIFormSpecMenu::parseItemImageButton(parserData* data, const std::string &
// the spec for the item-image // the spec for the item-image
FieldSpec spec_img( FieldSpec spec_img(
"", name,
L"", L"",
L"", L"",
258 + m_fields.size() 258 + m_fields.size(),
2
); );
GUIItemImage *e_img = new GUIItemImage(Environment, e_btn, spec_img.fid, GUIItemImage *e_img = new GUIItemImage(Environment, e_btn, spec_img.fid,
@ -2086,7 +2092,8 @@ void GUIFormSpecMenu::parseBox(parserData* data, const std::string &element)
"", "",
L"", L"",
L"", L"",
258 + m_fields.size() 258 + m_fields.size(),
-2
); );
spec.ftype = f_Box; spec.ftype = f_Box;
@ -2987,14 +2994,16 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
void GUIFormSpecMenu::legacySortElements(core::list<IGUIElement *>::Iterator from) void GUIFormSpecMenu::legacySortElements(core::list<IGUIElement *>::Iterator from)
{ {
/* /*
* The order was: Draw order for formspec_version <= 2:
* (0. background colors and backgrounds) -3 bgcolor
* 1. boxes -2 background
* 2. all normal elements (like buttons) -1 box
* 3. images 0 All other elements
* 4. item images 1 image
* 5. item lists (TODO) 2 item_image, item_image_button
*/ 3 list
4 label
*/
if (from == Children.end()) if (from == Children.end())
from = Children.begin(); from = Children.begin();
@ -3002,44 +3011,25 @@ void GUIFormSpecMenu::legacySortElements(core::list<IGUIElement *>::Iterator fro
from++; from++;
core::list<IGUIElement *>::Iterator to = Children.end(); core::list<IGUIElement *>::Iterator to = Children.end();
// 1: Copy into a sortable container
std::vector<IGUIElement *> elements;
for (auto it = from; it != to; ++it)
elements.emplace_back(*it);
// step 1: move all boxes to back and all images to front // 2: Sort the container
// (drawn in back = drawn first = in front of list) std::sort(elements.begin(), elements.end(),
for (auto i = from; i != to;) { [this] (const IGUIElement *a, const IGUIElement *b) -> bool {
if (getTypeByID((*i)->getID()) == f_Box && i != from) { const FieldSpec *spec_a = getSpecByID(a->getID());
auto e = *i; const FieldSpec *spec_b = getSpecByID(b->getID());
i = Children.erase(i); return spec_a && spec_b &&
Children.insert_before(from, e); spec_a->priority < spec_b->priority;
} else if ((*i)->hasType(gui::EGUIET_IMAGE)) { });
auto e = *i;
i = Children.erase(i); // 3: Re-assign the pointers
Children.push_back(e); for (auto e : elements) {
if (to == Children.end()) *from = e;
to = Children.getLast(); // do not touch sorted back from++;
if (i == Children.end())
break;
} else {
i++;
}
} }
// step 2: move all item images to front
for (auto i = from; i != to;) {
if (getTypeByID((*i)->getID()) == f_ItemImage) {
auto e = *i;
i = Children.erase(i);
Children.push_back(e);
if (to == Children.end())
to = Children.getLast(); // do not touch sorted back
if (i == Children.end())
break;
} else {
i++;
}
}
// step 3: move all item lists to front
// TODO when item lists are drawn in order
} }
#ifdef __ANDROID__ #ifdef __ANDROID__
@ -4403,13 +4393,13 @@ std::string GUIFormSpecMenu::getNameByID(s32 id)
} }
FormspecFieldType GUIFormSpecMenu::getTypeByID(s32 id) const GUIFormSpecMenu::FieldSpec *GUIFormSpecMenu::getSpecByID(s32 id)
{ {
for (FieldSpec &spec : m_fields) { for (FieldSpec &spec : m_fields) {
if (spec.fid == id) if (spec.fid == id)
return spec.ftype; return &spec;
} }
return f_Unknown; return nullptr;
} }
/** /**

View file

@ -143,24 +143,27 @@ class GUIFormSpecMenu : public GUIModalMenu
FieldSpec() = default; FieldSpec() = default;
FieldSpec(const std::string &name, const std::wstring &label, FieldSpec(const std::string &name, const std::wstring &label,
const std::wstring &default_text, int id) : const std::wstring &default_text, s32 id, int priority = 0) :
fname(name), fname(name),
flabel(label), flabel(label),
fdefault(unescape_enriched(translate_string(default_text))), fdefault(unescape_enriched(translate_string(default_text))),
fid(id), fid(id),
send(false), send(false),
ftype(f_Unknown), ftype(f_Unknown),
is_exit(false) is_exit(false),
priority(priority)
{ {
} }
std::string fname; std::string fname;
std::wstring flabel; std::wstring flabel;
std::wstring fdefault; std::wstring fdefault;
int fid; s32 fid;
bool send; bool send;
FormspecFieldType ftype; FormspecFieldType ftype;
bool is_exit; bool is_exit;
// Draw priority for formspec version < 3
int priority;
core::rect<s32> rect; core::rect<s32> rect;
}; };
@ -309,7 +312,7 @@ class GUIFormSpecMenu : public GUIModalMenu
} }
std::wstring getLabelByID(s32 id); std::wstring getLabelByID(s32 id);
std::string getNameByID(s32 id); std::string getNameByID(s32 id);
FormspecFieldType getTypeByID(s32 id); const FieldSpec *getSpecByID(s32 id);
v2s32 getElementBasePos(const std::vector<std::string> *v_pos); v2s32 getElementBasePos(const std::vector<std::string> *v_pos);
v2s32 getRealCoordinateBasePos(const std::vector<std::string> &v_pos); v2s32 getRealCoordinateBasePos(const std::vector<std::string> &v_pos);
v2s32 getRealCoordinateGeometry(const std::vector<std::string> &v_geom); v2s32 getRealCoordinateGeometry(const std::vector<std::string> &v_geom);