Skip to content

Commit

Permalink
Formspec: Fix priorities for version < 3 (#9121)
Browse files Browse the repository at this point in the history
* 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
SmallJoker authored Nov 20, 2019

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent 60bff1e commit b50a166
Showing 2 changed files with 54 additions and 61 deletions.
104 changes: 47 additions & 57 deletions src/gui/guiFormSpecMenu.cpp
Original file line number Diff line number Diff line change
@@ -21,8 +21,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <cstdlib>
#include <algorithm>
#include <iterator>
#include <sstream>
#include <limits>
#include <sstream>
#include "guiFormSpecMenu.h"
#include "constants.h"
#include "gamedef.h"
@@ -427,7 +427,8 @@ void GUIFormSpecMenu::parseList(parserData* data, const std::string &element)
"",
L"",
L"",
258 + m_fields.size()
258 + m_fields.size(),
3
);

v2s32 pos;
@@ -671,7 +672,8 @@ void GUIFormSpecMenu::parseImage(parserData* data, const std::string &element)
name,
L"",
L"",
258 + m_fields.size()
258 + m_fields.size(),
1
);
core::rect<s32> rect(pos, pos + geom);
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"",
258 + m_fields.size()
258 + m_fields.size(),
2
);
spec.ftype = f_ItemImage;

@@ -1654,7 +1657,8 @@ void GUIFormSpecMenu::parseLabel(parserData* data, const std::string &element)
"",
wlabel_colors,
L"",
258 + m_fields.size()
258 + m_fields.size(),
4
);
gui::IGUIStaticText *e = gui::StaticText::add(Environment,
spec.flabel.c_str(), rect, false, false, this, spec.fid);
@@ -2015,7 +2019,8 @@ void GUIFormSpecMenu::parseItemImageButton(parserData* data, const std::string &
name,
utf8_to_wide(label),
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"");
@@ -2035,10 +2040,11 @@ void GUIFormSpecMenu::parseItemImageButton(parserData* data, const std::string &

// the spec for the item-image
FieldSpec spec_img(
"",
name,
L"",
L"",
258 + m_fields.size()
258 + m_fields.size(),
2
);

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"",
258 + m_fields.size()
258 + m_fields.size(),
-2
);
spec.ftype = f_Box;

@@ -2987,59 +2994,42 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
void GUIFormSpecMenu::legacySortElements(core::list<IGUIElement *>::Iterator from)
{
/*
* The order was:
* (0. background colors and backgrounds)
* 1. boxes
* 2. all normal elements (like buttons)
* 3. images
* 4. item images
* 5. item lists (TODO)
*/
Draw order for formspec_version <= 2:
-3 bgcolor
-2 background
-1 box
0 All other elements
1 image
2 item_image, item_image_button
3 list
4 label
*/

if (from == Children.end())
from = Children.begin();
else
from++;

core::list<IGUIElement *>::Iterator to = Children.end();

// step 1: move all boxes to back and all images to front
// (drawn in back = drawn first = in front of list)
for (auto i = from; i != to;) {
if (getTypeByID((*i)->getID()) == f_Box && i != from) {
auto e = *i;
i = Children.erase(i);
Children.insert_before(from, e);
} else if ((*i)->hasType(gui::EGUIET_IMAGE)) {
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 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++;
}
// 1: Copy into a sortable container
std::vector<IGUIElement *> elements;
for (auto it = from; it != to; ++it)
elements.emplace_back(*it);

// 2: Sort the container
std::sort(elements.begin(), elements.end(),
[this] (const IGUIElement *a, const IGUIElement *b) -> bool {
const FieldSpec *spec_a = getSpecByID(a->getID());
const FieldSpec *spec_b = getSpecByID(b->getID());
return spec_a && spec_b &&
spec_a->priority < spec_b->priority;
});

// 3: Re-assign the pointers
for (auto e : elements) {
*from = e;
from++;
}

// step 3: move all item lists to front
// TODO when item lists are drawn in order
}

#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) {
if (spec.fid == id)
return spec.ftype;
return &spec;
}
return f_Unknown;
return nullptr;
}

/**
11 changes: 7 additions & 4 deletions src/gui/guiFormSpecMenu.h
Original file line number Diff line number Diff line change
@@ -143,24 +143,27 @@ class GUIFormSpecMenu : public GUIModalMenu
FieldSpec() = default;

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),
flabel(label),
fdefault(unescape_enriched(translate_string(default_text))),
fid(id),
send(false),
ftype(f_Unknown),
is_exit(false)
is_exit(false),
priority(priority)
{
}

std::string fname;
std::wstring flabel;
std::wstring fdefault;
int fid;
s32 fid;
bool send;
FormspecFieldType ftype;
bool is_exit;
// Draw priority for formspec version < 3
int priority;
core::rect<s32> rect;
};

@@ -309,7 +312,7 @@ class GUIFormSpecMenu : public GUIModalMenu
}
std::wstring getLabelByID(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 getRealCoordinateBasePos(const std::vector<std::string> &v_pos);
v2s32 getRealCoordinateGeometry(const std::vector<std::string> &v_geom);

0 comments on commit b50a166

Please sign in to comment.