errorstream<< "Invalid size element (" << parts.size() << "): '" << element << "'" << std::endl;
}
+void GUIFormSpecMenu::parseContainer(parserData* data, std::string element)
+{
+ std::vector<std::string> parts = split(element, ',');
+
+ if (parts.size() >= 2) {
+ if (parts[1].find(';') != std::string::npos)
+ parts[1] = parts[1].substr(0, parts[1].find(';'));
+
+ container_stack.push(pos_offset);
+ pos_offset.X += MYMAX(0, stof(parts[0]));
+ pos_offset.Y += MYMAX(0, stof(parts[1]));
+ return;
+ }
+ errorstream<< "Invalid container start element (" << parts.size() << "): '" << element << "'" << std::endl;
+}
+
+void GUIFormSpecMenu::parseContainerEnd(parserData* data)
+{
+ if (container_stack.empty()) {
+ errorstream<< "Invalid container end element, no matching container start element" << std::endl;
+ } else {
+ pos_offset = container_stack.top();
+ container_stack.pop();
+ }
+}
+
void GUIFormSpecMenu::parseList(parserData* data,std::string element)
{
if (m_gamedef == 0) {
else
loc.deSerialize(location);
- v2s32 pos = padding + AbsoluteRect.UpperLeftCorner;
+ v2s32 pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
MY_CHECKPOS("checkbox",0);
- v2s32 pos = padding;
+ v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float) spacing.X;
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
MY_CHECKPOS("scrollbar",0);
- v2s32 pos = padding;
+ v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float) spacing.X;
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
std::vector<std::string> v_geom = split(parts[1],',');
std::string name = unescape_string(parts[2]);
- MY_CHECKPOS("image",0);
- MY_CHECKGEOM("image",1);
+ MY_CHECKPOS("image", 0);
+ MY_CHECKGEOM("image", 1);
- v2s32 pos = padding + AbsoluteRect.UpperLeftCorner;
+ v2s32 pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float) spacing.X;
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
geom.X = stof(v_geom[0]) * (float)imgsize.X;
geom.Y = stof(v_geom[1]) * (float)imgsize.Y;
- if(!data->explicit_size)
+ if (!data->explicit_size)
warningstream<<"invalid use of image without a size[] element"<<std::endl;
m_images.push_back(ImageDrawSpec(name, pos, geom));
return;
- }
-
- if (parts.size() == 2) {
+ } else if (parts.size() == 2) {
std::vector<std::string> v_pos = split(parts[0],',');
std::string name = unescape_string(parts[1]);
- MY_CHECKPOS("image",0);
+ MY_CHECKPOS("image", 0);
- v2s32 pos = padding + AbsoluteRect.UpperLeftCorner;
+ v2s32 pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float) spacing.X;
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
- if(!data->explicit_size)
+ if (!data->explicit_size)
warningstream<<"invalid use of image without a size[] element"<<std::endl;
m_images.push_back(ImageDrawSpec(name, pos));
return;
MY_CHECKPOS("itemimage",0);
MY_CHECKGEOM("itemimage",1);
- v2s32 pos = padding + AbsoluteRect.UpperLeftCorner;
+ v2s32 pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float) spacing.X;
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
MY_CHECKPOS("button",0);
MY_CHECKGEOM("button",1);
- v2s32 pos = padding;
+ v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
MY_CHECKPOS("background",0);
MY_CHECKGEOM("background",1);
- v2s32 pos = padding + AbsoluteRect.UpperLeftCorner;
- pos.X += stof(v_pos[0]) * (float)spacing.X - ((float)spacing.X-(float)imgsize.X)/2;
- pos.Y += stof(v_pos[1]) * (float)spacing.Y - ((float)spacing.Y-(float)imgsize.Y)/2;
+ v2s32 pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
+ pos.X += stof(v_pos[0]) * (float)spacing.X - ((float)spacing.X - (float)imgsize.X)/2;
+ pos.Y += stof(v_pos[1]) * (float)spacing.Y - ((float)spacing.Y - (float)imgsize.Y)/2;
v2s32 geom;
geom.X = stof(v_geom[0]) * (float)spacing.X;
geom.Y = stof(v_geom[1]) * (float)spacing.Y;
- if (parts.size() == 4) {
- m_clipbackground = is_yes(parts[3]);
- if (m_clipbackground) {
- pos.X = stoi(v_pos[0]); //acts as offset
- pos.Y = stoi(v_pos[1]); //acts as offset
- }
+ if (!data->explicit_size)
+ warningstream<<"invalid use of background without a size[] element"<<std::endl;
+
+ bool clip = false;
+ if (parts.size() == 4 && is_yes(parts[3])) {
+ pos.X = stoi(v_pos[0]); //acts as offset
+ pos.Y = stoi(v_pos[1]); //acts as offset
+ clip = true;
}
+ m_backgrounds.push_back(ImageDrawSpec(name, pos, geom, clip));
- if(!data->explicit_size)
- warningstream<<"invalid use of background without a size[] element"<<std::endl;
- m_backgrounds.push_back(ImageDrawSpec(name, pos, geom));
return;
}
errorstream<< "Invalid background element(" << parts.size() << "): '" << element << "'" << std::endl;
MY_CHECKPOS("table",0);
MY_CHECKGEOM("table",1);
- v2s32 pos = padding;
+ v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
MY_CHECKPOS("textlist",0);
MY_CHECKGEOM("textlist",1);
- v2s32 pos = padding;
+ v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
MY_CHECKPOS("dropdown",0);
- v2s32 pos = padding;
+ v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
<< element << "'" << std::endl;
}
+void GUIFormSpecMenu::parseFieldCloseOnEnter(parserData *data,
+ const std::string &element)
+{
+ std::vector<std::string> parts = split(element,';');
+ if (parts.size() == 2 ||
+ (parts.size() > 2 && m_formspec_version > FORMSPEC_API_VERSION)) {
+ field_close_on_enter[parts[0]] = is_yes(parts[1]);
+ }
+}
+
void GUIFormSpecMenu::parsePwdField(parserData* data,std::string element)
{
std::vector<std::string> parts = split(element,';');
- if ((parts.size() == 4) ||
- ((parts.size() > 4) && (m_formspec_version > FORMSPEC_API_VERSION)))
+ if ((parts.size() == 4) || (parts.size() == 5) ||
+ ((parts.size() > 5) && (m_formspec_version > FORMSPEC_API_VERSION)))
{
std::vector<std::string> v_pos = split(parts[0],',');
std::vector<std::string> v_geom = split(parts[1],',');
MY_CHECKPOS("pwdfield",0);
MY_CHECKGEOM("pwdfield",1);
- v2s32 pos;
+ v2s32 pos = pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
evt.KeyInput.Shift = 0;
evt.KeyInput.PressedDown = true;
e->OnEvent(evt);
+
+ if (parts.size() >= 5) {
+ // TODO: remove after 2016-11-03
+ warningstream << "pwdfield: use field_close_on_enter[name, enabled]" <<
+ " instead of the 5th param" << std::endl;
+ field_close_on_enter[name] = is_yes(parts[4]);
+ }
+
m_fields.push_back(spec);
return;
}
if(data->explicit_size)
warningstream<<"invalid use of unpositioned \"field\" in inventory"<<std::endl;
- v2s32 pos = padding + AbsoluteRect.UpperLeftCorner;
+ v2s32 pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
pos.Y = ((m_fields.size()+2)*60);
v2s32 size = DesiredRect.getSize();
}
}
+ if (parts.size() >= 4) {
+ // TODO: remove after 2016-11-03
+ warningstream << "field/simple: use field_close_on_enter[name, enabled]" <<
+ " instead of the 4th param" << std::endl;
+ field_close_on_enter[name] = is_yes(parts[3]);
+ }
+
m_fields.push_back(spec);
}
MY_CHECKPOS(type,0);
MY_CHECKGEOM(type,1);
- v2s32 pos;
- pos.X = stof(v_pos[0]) * (float) spacing.X;
- pos.Y = stof(v_pos[1]) * (float) spacing.Y;
+ v2s32 pos = pos_offset * spacing;
+ pos.X += stof(v_pos[0]) * (float) spacing.X;
+ pos.Y += stof(v_pos[1]) * (float) spacing.Y;
v2s32 geom;
addStaticText(Environment, spec.flabel.c_str(), rect, false, true, this, 0);
}
}
+
+ if (parts.size() >= 6) {
+ // TODO: remove after 2016-11-03
+ warningstream << "field/textarea: use field_close_on_enter[name, enabled]" <<
+ " instead of the 6th param" << std::endl;
+ field_close_on_enter[name] = is_yes(parts[5]);
+ }
+
m_fields.push_back(spec);
}
return;
}
- if ((parts.size() == 5) ||
- ((parts.size() > 5) && (m_formspec_version > FORMSPEC_API_VERSION)))
+ if ((parts.size() == 5) || (parts.size() == 6) ||
+ ((parts.size() > 6) && (m_formspec_version > FORMSPEC_API_VERSION)))
{
parseTextArea(data,parts,type);
return;
MY_CHECKPOS("label",0);
- v2s32 pos = padding;
+ v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += (stof(v_pos[1]) + 7.0/30.0) * (float)spacing.Y;
MY_CHECKPOS("vertlabel",1);
- v2s32 pos = padding;
+ v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
MY_CHECKPOS("imagebutton",0);
MY_CHECKGEOM("imagebutton",1);
- v2s32 pos = padding;
+ v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
v2s32 geom;
spec.ftype = f_TabHeader;
- v2s32 pos(0,0);
+ v2s32 pos = pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y - m_btn_height * 2;
v2s32 geom;
MY_CHECKPOS("itemimagebutton",0);
MY_CHECKGEOM("itemimagebutton",1);
- v2s32 pos = padding;
+ v2s32 pos = padding + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float)spacing.X;
pos.Y += stof(v_pos[1]) * (float)spacing.Y;
v2s32 geom;
rect+=data->basepos-padding;
spec.rect=rect;
m_fields.push_back(spec);
- pos = padding + AbsoluteRect.UpperLeftCorner;
+ pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float) spacing.X;
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
m_itemimages.push_back(ImageDrawSpec("", item_name, e, pos, geom));
MY_CHECKPOS("box",0);
MY_CHECKGEOM("box",1);
- v2s32 pos = padding + AbsoluteRect.UpperLeftCorner;
+ v2s32 pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
pos.X += stof(v_pos[0]) * (float) spacing.X;
pos.Y += stof(v_pos[1]) * (float) spacing.Y;
std::string type = trim(parts[0]);
std::string description = trim(parts[1]);
+ if (type == "container") {
+ parseContainer(data, description);
+ return;
+ }
+
+ if (type == "container_end") {
+ parseContainerEnd(data);
+ return;
+ }
+
if (type == "list") {
- parseList(data,description);
+ parseList(data, description);
return;
}
}
if (type == "checkbox") {
- parseCheckbox(data,description);
+ parseCheckbox(data, description);
return;
}
if (type == "image") {
- parseImage(data,description);
+ parseImage(data, description);
return;
}
if (type == "item_image") {
- parseItemImage(data,description);
+ parseItemImage(data, description);
return;
}
- if ((type == "button") || (type == "button_exit")) {
- parseButton(data,description,type);
+ if (type == "button" || type == "button_exit") {
+ parseButton(data, description, type);
return;
}
return;
}
+ if (type == "field_close_on_enter") {
+ parseFieldCloseOnEnter(data, description);
+ return;
+ }
+
if (type == "pwdfield") {
parsePwdField(data,description);
return;
m_slotbordercolor = video::SColor(200,0,0,0);
m_slotborder = false;
- m_clipbackground = false;
// Add tooltip
{
assert(m_tooltip_element == NULL);
gui::IGUIFont *old_font = skin->getFont();
skin->setFont(m_font);
+ pos_offset = v2s32();
for (; i< elements.size(); i++) {
parseElement(&mydata, elements[i]);
}
+ if (!container_stack.empty()) {
+ errorstream << "Invalid formspec string: container was never closed!"
+ << std::endl;
+ }
+
// If there are fields without explicit size[], add a "Proceed"
// button and adjust size to fit all the fields.
if (m_fields.size() && !mydata.explicit_size) {
// Image rectangle on screen
core::rect<s32> rect = imgrect + spec.pos;
- if (m_clipbackground) {
+ if (spec.clip) {
core::dimension2d<s32> absrec_size = AbsoluteRect.getSize();
rect = core::rect<s32>(AbsoluteRect.UpperLeftCorner.X - spec.pos.X,
AbsoluteRect.UpperLeftCorner.Y - spec.pos.Y,
core::rect<s32>(core::position2d<s32>(0,0),
core::dimension2di(texture->getOriginalSize())),
NULL/*&AbsoluteClippingRect*/, colors, true);
- }
- else {
+ } else {
errorstream << "GUIFormSpecMenu::drawMenu() Draw backgrounds unable to load texture:" << std::endl;
errorstream << "\t" << spec.name << std::endl;
}
if (!current_field_enter_pending.empty()) {
fields["key_enter_field"] = current_field_enter_pending;
+ current_field_enter_pending = "";
}
if (current_keys_pending.key_escape) {
if (event.GUIEvent.EventType == gui::EGET_EDITBOX_ENTER) {
if (event.GUIEvent.Caller->getID() > 257) {
+ bool close_on_enter = true;
for (u32 i = 0; i < m_fields.size(); i++) {
FieldSpec &s = m_fields[i];
if (s.ftype == f_Unknown &&
s.fid == event.GUIEvent.Caller->getID()) {
current_field_enter_pending = s.fname;
+ UNORDERED_MAP<std::string, bool>::const_iterator it =
+ field_close_on_enter.find(s.fname);
+ if (it != field_close_on_enter.end())
+ close_on_enter = (*it).second;
+
+ break;
}
}
- if (m_allowclose) {
+ if (m_allowclose && close_on_enter) {
current_keys_pending.key_enter = true;
acceptInput(quit_mode_accept);
quitMenu();