#include <sstream>
#include <limits>
#include "guiFormSpecMenu.h"
+#include "guiTable.h"
#include "constants.h"
#include "gamedef.h"
#include "keycode.h"
#include <IGUIButton.h>
#include <IGUIStaticText.h>
#include <IGUIFont.h>
-#include <IGUIListBox.h>
#include <IGUITabControl.h>
-#include <IGUIScrollBar.h>
#include <IGUIComboBox.h>
#include "log.h"
#include "tile.h" // ITextureSource
#include "hud.h" // drawItemStack
+#include "hex.h"
#include "util/string.h"
#include "util/numeric.h"
#include "filesys.h"
*/
GUIFormSpecMenu::GUIFormSpecMenu(irr::IrrlichtDevice* dev,
- gui::IGUIElement* parent, s32 id,
- IMenuManager *menumgr,
- InventoryManager *invmgr,
- IGameDef *gamedef,
- ISimpleTextureSource *tsrc
-):
+ gui::IGUIElement* parent, s32 id, IMenuManager *menumgr,
+ InventoryManager *invmgr, IGameDef *gamedef,
+ ISimpleTextureSource *tsrc) :
GUIModalMenu(dev->getGUIEnvironment(), parent, id, menumgr),
m_device(dev),
m_invmgr(invmgr),
m_selected_item(NULL),
m_selected_amount(0),
m_selected_dragging(false),
- m_listbox_click_fname(),
- m_listbox_click_index(-1),
- m_listbox_click_time(0),
- m_listbox_doubleclick(false),
m_tooltip_element(NULL),
m_allowclose(true),
m_lock(false)
// Set initial focus according to following order of precedence:
// 1. first empty editbox
// 2. first editbox
- // 3. first listbox
+ // 3. first table
// 4. last button
// 5. first focusable (not statictext, not tabheader)
// 6. first child element
}
}
- // 3. first listbox
+ // 3. first table
for (core::list<gui::IGUIElement*>::Iterator it = children.begin();
it != children.end(); ++it) {
- if ((*it)->getType() == gui::EGUIET_LIST_BOX) {
+ if ((*it)->getTypeName() == std::string("GUITable")) {
Environment->setFocus(*it);
return;
}
Environment->setFocus(*(children.begin()));
}
-int GUIFormSpecMenu::getListboxIndex(std::string listboxname) {
-
- std::wstring wlistboxname = narrow_to_wide(listboxname.c_str());
-
- for(unsigned int i=0; i < m_listboxes.size(); i++) {
-
- std::wstring name(m_listboxes[i].first.fname.c_str());
- if ( name == wlistboxname) {
- return m_listboxes[i].second->getSelected();
- }
- }
- return -1;
-}
-
-bool GUIFormSpecMenu::checkListboxClick(std::wstring wlistboxname,
- int eventtype)
+GUITable* GUIFormSpecMenu::getTable(std::wstring tablename)
{
- // WARNING: BLACK IRRLICHT MAGIC
- // Used to fix Irrlicht's subpar reporting of single clicks and double
- // clicks in listboxes (gui::EGET_LISTBOX_CHANGED,
- // gui::EGET_LISTBOX_SELECTED_AGAIN):
- // 1. IGUIListBox::setSelected() is counted as a click.
- // Including the initial setSelected() done by parseTextList().
- // 2. Clicking on a the selected item and then dragging for less
- // than 500ms is counted as a doubleclick, no matter when the
- // item was previously selected (e.g. more than 500ms ago)
-
- // So when Irrlicht reports a doubleclick, we need to check
- // for ourselves if really was a doubleclick. Or just a fake.
-
- for(unsigned int i=0; i < m_listboxes.size(); i++) {
- std::wstring name(m_listboxes[i].first.fname.c_str());
- int selected = m_listboxes[i].second->getSelected();
- if (name == wlistboxname && selected >= 0) {
- u32 now = getTimeMs();
- bool doubleclick =
- (eventtype == gui::EGET_LISTBOX_SELECTED_AGAIN)
- && (name == m_listbox_click_fname)
- && (selected == m_listbox_click_index)
- && (m_listbox_click_time >= now - 500);
- m_listbox_click_fname = name;
- m_listbox_click_index = selected;
- m_listbox_click_time = now;
- m_listbox_doubleclick = doubleclick;
- return true;
- }
+ for (u32 i = 0; i < m_tables.size(); ++i) {
+ if (tablename == m_tables[i].first.fname)
+ return m_tables[i].second;
}
- return false;
-}
-
-gui::IGUIScrollBar* GUIFormSpecMenu::getListboxScrollbar(
- gui::IGUIListBox *listbox)
-{
- // WARNING: BLACK IRRLICHT MAGIC
- // Ordinarily, due to how formspecs work (recreating the entire GUI
- // when something changes), when you select an item in a textlist
- // with more items than fit in the visible area, the newly selected
- // item is scrolled to the bottom of the visible area. This is
- // annoying and breaks GUI designs that use double clicks.
-
- // This function helps fixing this problem by giving direct access
- // to a listbox's scrollbar. This works because CGUIListBox doesn't
- // cache the scrollbar position anywhere.
-
- // If this stops working in a future irrlicht version, consider
- // maintaining a local copy of irr::gui::CGUIListBox, possibly also
- // fixing the other reasons why black irrlicht magic is needed.
-
- core::list<gui::IGUIElement*> children = listbox->getChildren();
- for(core::list<gui::IGUIElement*>::Iterator it = children.begin();
- it != children.end(); ++it) {
- gui::IGUIElement* child = *it;
- if (child && child->getType() == gui::EGUIET_SCROLL_BAR) {
- return static_cast<gui::IGUIScrollBar*>(child);
- }
- }
-
- verbosestream<<"getListboxScrollbar: WARNING: "
- <<"listbox has no scrollbar"<<std::endl;
- return NULL;
+ return 0;
}
std::vector<std::string> split(const std::string &s, char delim) {
return tokens;
}
-void GUIFormSpecMenu::parseSize(parserData* data,std::string element) {
+void GUIFormSpecMenu::parseSize(parserData* data,std::string element)
+{
std::vector<std::string> parts = split(element,',');
- if (parts.size() == 2) {
+ if ((parts.size() == 2) || parts.size() == 3) {
v2f invsize;
if (parts[1].find(';') != std::string::npos)
invsize.X = stof(parts[0]);
invsize.Y = stof(parts[1]);
+ lockSize(false);
+ if (parts.size() == 3) {
+ if (parts[2] == "true") {
+ lockSize(true,v2u32(800,600));
+ }
+ }
+
if (m_lock) {
v2u32 current_screensize = m_device->getVideoDriver()->getScreenSize();
v2u32 delta = current_screensize - m_lockscreensize;
errorstream<< "Invalid size element (" << parts.size() << "): '" << element << "'" << std::endl;
}
-void GUIFormSpecMenu::parseList(parserData* data,std::string element) {
-
+void GUIFormSpecMenu::parseList(parserData* data,std::string element)
+{
if (m_gamedef == 0) {
errorstream<<"WARNING: invalid use of 'list' with m_gamedef==0"<<std::endl;
return;
s32 start_i = 0;
if(startindex != "")
start_i = stoi(startindex);
+
+ if (geom.X < 0 || geom.Y < 0 || start_i < 0) {
+ errorstream<< "Invalid list element: '" << element << "'" << std::endl;
+ return;
+ }
+
if(data->bp_set != 2)
errorstream<<"WARNING: invalid use of list without a size[] element"<<std::endl;
m_inventorylists.push_back(ListDrawSpec(loc, listname, pos, geom, start_i));
errorstream<< "Invalid list element(" << parts.size() << "): '" << element << "'" << std::endl;
}
-void GUIFormSpecMenu::parseCheckbox(parserData* data,std::string element) {
+void GUIFormSpecMenu::parseCheckbox(parserData* data,std::string element)
+{
std::vector<std::string> parts = split(element,';');
if ((parts.size() == 3) || (parts.size() == 4)) {
errorstream<< "Invalid checkbox element(" << parts.size() << "): '" << element << "'" << std::endl;
}
-void GUIFormSpecMenu::parseImage(parserData* data,std::string element) {
+void GUIFormSpecMenu::parseImage(parserData* data,std::string element)
+{
std::vector<std::string> parts = split(element,';');
if (parts.size() == 3) {
errorstream<< "Invalid image element(" << parts.size() << "): '" << element << "'" << std::endl;
}
-void GUIFormSpecMenu::parseItemImage(parserData* data,std::string element) {
+void GUIFormSpecMenu::parseItemImage(parserData* data,std::string element)
+{
std::vector<std::string> parts = split(element,';');
if (parts.size() == 3) {
errorstream<< "Invalid ItemImage element(" << parts.size() << "): '" << element << "'" << std::endl;
}
-void GUIFormSpecMenu::parseButton(parserData* data,std::string element,std::string type) {
+void GUIFormSpecMenu::parseButton(parserData* data,std::string element,
+ std::string type)
+{
std::vector<std::string> parts = split(element,';');
if (parts.size() == 4) {
errorstream<< "Invalid button element(" << parts.size() << "): '" << element << "'" << std::endl;
}
-void GUIFormSpecMenu::parseBackground(parserData* data,std::string element) {
+void GUIFormSpecMenu::parseBackground(parserData* data,std::string element)
+{
std::vector<std::string> parts = split(element,';');
if ((parts.size() == 3) || (parts.size() == 4)) {
errorstream<< "Invalid background element(" << parts.size() << "): '" << element << "'" << std::endl;
}
-void GUIFormSpecMenu::parseTextList(parserData* data,std::string element) {
+void GUIFormSpecMenu::parseTableOptions(parserData* data,std::string element)
+{
+ std::vector<std::string> parts = split(element,';');
+
+ data->table_options.clear();
+ for (size_t i = 0; i < parts.size(); ++i) {
+ // Parse table option
+ std::string opt = unescape_string(parts[i]);
+ data->table_options.push_back(GUITable::splitOption(opt));
+ }
+}
+
+void GUIFormSpecMenu::parseTableColumns(parserData* data,std::string element)
+{
+ std::vector<std::string> parts = split(element,';');
+
+ data->table_columns.clear();
+ for (size_t i = 0; i < parts.size(); ++i) {
+ std::vector<std::string> col_parts = split(parts[i],',');
+ GUITable::TableColumn column;
+ // Parse column type
+ if (!col_parts.empty())
+ column.type = col_parts[0];
+ // Parse column options
+ for (size_t j = 1; j < col_parts.size(); ++j) {
+ std::string opt = unescape_string(col_parts[j]);
+ column.options.push_back(GUITable::splitOption(opt));
+ }
+ data->table_columns.push_back(column);
+ }
+}
+
+void GUIFormSpecMenu::parseTable(parserData* data,std::string element)
+{
std::vector<std::string> parts = split(element,';');
- if ((parts.size() == 5) || (parts.size() == 6)) {
+ if ((parts.size() == 4) || (parts.size() == 5)) {
std::vector<std::string> v_pos = split(parts[0],',');
std::vector<std::string> v_geom = split(parts[1],',');
std::string name = parts[2];
if (parts.size() >= 5)
str_initial_selection = parts[4];
- if (parts.size() >= 6)
- str_transparent = parts[5];
-
- MY_CHECKPOS("textlist",0);
- MY_CHECKGEOM("textlist",1);
+ MY_CHECKPOS("table",0);
+ MY_CHECKGEOM("table",1);
v2s32 pos = padding;
pos.X += stof(v_pos[0]) * (float)spacing.X;
258+m_fields.size()
);
- spec.ftype = f_ListBox;
+ spec.ftype = f_Table;
- //now really show list
- gui::IGUIListBox *e = Environment->addListBox(rect, this,spec.fid);
+ for (unsigned int i = 0; i < items.size(); ++i) {
+ items[i] = unescape_string(items[i]);
+ }
+
+ //now really show table
+ GUITable *e = new GUITable(Environment, this, spec.fid, rect,
+ m_tsrc);
+ e->drop(); // IGUIElement maintains the remaining reference
if (spec.fname == data->focused_fieldname) {
Environment->setFocus(e);
}
- if (str_transparent == "false")
- e->setDrawBackground(true);
+ e->setTable(data->table_options, data->table_columns, items);
- for (unsigned int i=0; i < items.size(); i++) {
- if (items[i].c_str()[0] == '#') {
- if (items[i].c_str()[1] == '#') {
- e->addItem(narrow_to_wide(unescape_string(items[i])).c_str() +1);
- }
- else {
- std::string color = items[i].substr(0,7);
- std::wstring toadd =
- narrow_to_wide(unescape_string(items[i]).c_str() + 7);
+ if (data->table_dyndata.find(fname_w) != data->table_dyndata.end()) {
+ e->setDynamicData(data->table_dyndata[fname_w]);
+ }
- e->addItem(toadd.c_str());
+ if ((str_initial_selection != "") &&
+ (str_initial_selection != "0"))
+ e->setSelected(stoi(str_initial_selection.c_str()));
- video::SColor tmp_color;
+ m_tables.push_back(std::pair<FieldSpec,GUITable*>(spec, e));
+ m_fields.push_back(spec);
+ return;
+ }
+ errorstream<< "Invalid table element(" << parts.size() << "): '" << element << "'" << std::endl;
+}
- if (parseColor(color, tmp_color, false))
- e->setItemOverrideColor(i,tmp_color);
- }
- }
- else {
- e->addItem(narrow_to_wide(unescape_string(items[i])).c_str());
- }
- }
+void GUIFormSpecMenu::parseTextList(parserData* data,std::string element)
+{
+ std::vector<std::string> parts = split(element,';');
+
+ if ((parts.size() == 4) || (parts.size() == 5) || (parts.size() == 6)) {
+ std::vector<std::string> v_pos = split(parts[0],',');
+ std::vector<std::string> v_geom = split(parts[1],',');
+ std::string name = parts[2];
+ std::vector<std::string> items = split(parts[3],',');
+ std::string str_initial_selection = "";
+ std::string str_transparent = "false";
- if (data->listbox_selections.find(fname_w) != data->listbox_selections.end()) {
- e->setSelected(data->listbox_selections[fname_w]);
+ if (parts.size() >= 5)
+ str_initial_selection = parts[4];
+
+ if (parts.size() >= 6)
+ str_transparent = parts[5];
+
+ MY_CHECKPOS("textlist",0);
+ MY_CHECKGEOM("textlist",1);
+
+ v2s32 pos = padding;
+ pos.X += stof(v_pos[0]) * (float)spacing.X;
+ pos.Y += stof(v_pos[1]) * (float)spacing.Y;
+
+ v2s32 geom;
+ geom.X = stof(v_geom[0]) * (float)spacing.X;
+ geom.Y = stof(v_geom[1]) * (float)spacing.Y;
+
+
+ core::rect<s32> rect = core::rect<s32>(pos.X, pos.Y, pos.X+geom.X, pos.Y+geom.Y);
+
+ std::wstring fname_w = narrow_to_wide(name.c_str());
+
+ FieldSpec spec = FieldSpec(
+ fname_w,
+ L"",
+ L"",
+ 258+m_fields.size()
+ );
+
+ spec.ftype = f_Table;
+
+ for (unsigned int i = 0; i < items.size(); ++i) {
+ items[i] = unescape_string(items[i]);
}
- if (data->listbox_scroll.find(fname_w) != data->listbox_scroll.end()) {
- gui::IGUIScrollBar *scrollbar = getListboxScrollbar(e);
- if (scrollbar) {
- scrollbar->setPos(data->listbox_scroll[fname_w]);
- }
+ //now really show list
+ GUITable *e = new GUITable(Environment, this, spec.fid, rect,
+ m_tsrc);
+ e->drop(); // IGUIElement maintains the remaining reference
+
+ if (spec.fname == data->focused_fieldname) {
+ Environment->setFocus(e);
}
- else {
- gui::IGUIScrollBar *scrollbar = getListboxScrollbar(e);
- if (scrollbar) {
- scrollbar->setPos(0);
- }
+
+ e->setTextList(items, is_yes(str_transparent));
+
+ if (data->table_dyndata.find(fname_w) != data->table_dyndata.end()) {
+ e->setDynamicData(data->table_dyndata[fname_w]);
}
if ((str_initial_selection != "") &&
(str_initial_selection != "0"))
- e->setSelected(stoi(str_initial_selection.c_str())-1);
+ e->setSelected(stoi(str_initial_selection.c_str()));
- m_listboxes.push_back(std::pair<FieldSpec,gui::IGUIListBox*>(spec,e));
+ m_tables.push_back(std::pair<FieldSpec,GUITable*>(spec, e));
m_fields.push_back(spec);
return;
}
}
-void GUIFormSpecMenu::parseDropDown(parserData* data,std::string element) {
+void GUIFormSpecMenu::parseDropDown(parserData* data,std::string element)
+{
std::vector<std::string> parts = split(element,';');
if (parts.size() == 5) {
<< element << "'" << std::endl;
}
-void GUIFormSpecMenu::parsePwdField(parserData* data,std::string element) {
+void GUIFormSpecMenu::parsePwdField(parserData* data,std::string element)
+{
std::vector<std::string> parts = split(element,';');
if (parts.size() == 4) {
Environment->setFocus(e);
}
- if (label.length() > 1)
+ if (label.length() >= 1)
{
rect.UpperLeftCorner.Y -= 15;
rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + 15;
errorstream<< "Invalid pwdfield element(" << parts.size() << "): '" << element << "'" << std::endl;
}
-void GUIFormSpecMenu::parseSimpleField(parserData* data,std::vector<std::string> &parts) {
+void GUIFormSpecMenu::parseSimpleField(parserData* data,
+ std::vector<std::string> &parts)
+{
std::string name = parts[0];
std::string label = parts[1];
std::string default_val = parts[2];
evt.KeyInput.PressedDown = true;
e->OnEvent(evt);
- if (label.length() > 1)
+ if (label.length() >= 1)
{
rect.UpperLeftCorner.Y -= 15;
rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + 15;
m_fields.push_back(spec);
}
-void GUIFormSpecMenu::parseTextArea(parserData* data,std::vector<std::string>& parts,std::string type) {
+void GUIFormSpecMenu::parseTextArea(parserData* data,
+ std::vector<std::string>& parts,std::string type)
+{
std::vector<std::string> v_pos = split(parts[0],',');
std::vector<std::string> v_geom = split(parts[1],',');
e->OnEvent(evt);
}
- if (label.length() > 1)
+ if (label.length() >= 1)
{
rect.UpperLeftCorner.Y -= 15;
rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + 15;
m_fields.push_back(spec);
}
-void GUIFormSpecMenu::parseField(parserData* data,std::string element,std::string type) {
+void GUIFormSpecMenu::parseField(parserData* data,std::string element,
+ std::string type)
+{
std::vector<std::string> parts = split(element,';');
if (parts.size() == 3) {
errorstream<< "Invalid field element(" << parts.size() << "): '" << element << "'" << std::endl;
}
-void GUIFormSpecMenu::parseLabel(parserData* data,std::string element) {
+void GUIFormSpecMenu::parseLabel(parserData* data,std::string element)
+{
std::vector<std::string> parts = split(element,';');
if (parts.size() == 2) {
errorstream<< "Invalid label element(" << parts.size() << "): '" << element << "'" << std::endl;
}
-void GUIFormSpecMenu::parseVertLabel(parserData* data,std::string element) {
+void GUIFormSpecMenu::parseVertLabel(parserData* data,std::string element)
+{
std::vector<std::string> parts = split(element,';');
if (parts.size() == 2) {
errorstream<< "Invalid vertlabel element(" << parts.size() << "): '" << element << "'" << std::endl;
}
-void GUIFormSpecMenu::parseImageButton(parserData* data,std::string element,std::string type) {
+void GUIFormSpecMenu::parseImageButton(parserData* data,std::string element,
+ std::string type)
+{
std::vector<std::string> parts = split(element,';');
if ((parts.size() == 5) || (parts.size() == 7) || (parts.size() == 8)) {
errorstream<< "Invalid imagebutton element(" << parts.size() << "): '" << element << "'" << std::endl;
}
-void GUIFormSpecMenu::parseTabHeader(parserData* data,std::string element) {
+void GUIFormSpecMenu::parseTabHeader(parserData* data,std::string element)
+{
std::vector<std::string> parts = split(element,';');
if ((parts.size() == 4) || (parts.size() == 6)) {
errorstream<< "Invalid TabHeader element(" << parts.size() << "): '" << element << "'" << std::endl;
}
-void GUIFormSpecMenu::parseItemImageButton(parserData* data,std::string element) {
+void GUIFormSpecMenu::parseItemImageButton(parserData* data,std::string element)
+{
if (m_gamedef == 0) {
errorstream<<"WARNING: invalid use of item_image_button with m_gamedef==0"<<std::endl;
errorstream<< "Invalid ItemImagebutton element(" << parts.size() << "): '" << element << "'" << std::endl;
}
-void GUIFormSpecMenu::parseBox(parserData* data,std::string element) {
+void GUIFormSpecMenu::parseBox(parserData* data,std::string element)
+{
std::vector<std::string> parts = split(element,';');
if (parts.size() == 3) {
errorstream<< "Invalid Box element(" << parts.size() << "): '" << element << "'" << std::endl;
}
-void GUIFormSpecMenu::parseBackgroundColor(parserData* data,std::string element) {
+void GUIFormSpecMenu::parseBackgroundColor(parserData* data,std::string element)
+{
std::vector<std::string> parts = split(element,';');
if ((parts.size() == 1) || (parts.size() == 2)) {
errorstream<< "Invalid bgcolor element(" << parts.size() << "): '" << element << "'" << std::endl;
}
-void GUIFormSpecMenu::parseListColors(parserData* data,std::string element) {
+void GUIFormSpecMenu::parseListColors(parserData* data,std::string element)
+{
std::vector<std::string> parts = split(element,';');
if ((parts.size() == 2) || (parts.size() == 3) || (parts.size() == 5)) {
errorstream<< "Invalid listcolors element(" << parts.size() << "): '" << element << "'" << std::endl;
}
-void GUIFormSpecMenu::parseElement(parserData* data,std::string element) {
-
+void GUIFormSpecMenu::parseElement(parserData* data,std::string element)
+{
//some prechecks
if (element == "")
return;
return;
}
+ if (type == "tableoptions"){
+ parseTableOptions(data,description);
+ return;
+ }
+
+ if (type == "tablecolumns"){
+ parseTableColumns(data,description);
+ return;
+ }
+
+ if (type == "table"){
+ parseTable(data,description);
+ return;
+ }
+
if (type == "textlist"){
parseTextList(data,description);
return;
{
parserData mydata;
- //preserve listboxes
- for (unsigned int i = 0; i < m_listboxes.size(); i++) {
- std::wstring listboxname = m_listboxes[i].first.fname;
- gui::IGUIListBox *listbox = m_listboxes[i].second;
-
- int selection = listbox->getSelected();
- if (selection != -1) {
- mydata.listbox_selections[listboxname] = selection;
- }
-
- gui::IGUIScrollBar *scrollbar = getListboxScrollbar(listbox);
- if (scrollbar) {
- mydata.listbox_scroll[listboxname] = scrollbar->getPos();
- }
+ //preserve tables
+ for (u32 i = 0; i < m_tables.size(); ++i) {
+ std::wstring tablename = m_tables[i].first.fname;
+ GUITable *table = m_tables[i].second;
+ mydata.table_dyndata[tablename] = table->getDynamicData();
}
//preserve focus
m_images.clear();
m_backgrounds.clear();
m_itemimages.clear();
- m_listboxes.clear();
+ m_tables.clear();
m_checkboxes.clear();
m_fields.clear();
m_boxes.clear();
v2u32 screenSize = driver->getScreenSize();
core::rect<s32> allbg(0, 0, screenSize.X , screenSize.Y);
- if (m_bgfullscreen)
+ if (m_bgfullscreen)
driver->draw2DRectangle(m_bgcolor, allbg, &allbg);
else
driver->draw2DRectangle(m_bgcolor, AbsoluteRect, &AbsoluteClippingRect);
IItemDefManager *idef = m_gamedef->idef();
ItemStack item;
item.deSerialize(spec.name, idef);
- video::ITexture *texture = idef->getInventoryTexture(item.getDefinition(idef).name, m_gamedef);
+ video::ITexture *texture = idef->getInventoryTexture(item.getDefinition(idef).name, m_gamedef);
// Image size on screen
core::rect<s32> imgrect(0, 0, spec.geom.X, spec.geom.Y);
// Image rectangle on screen
if (spec.tooltip != "")
{
core::rect<s32> rect = spec.rect;
- if (rect.isPointInside(m_pointer))
+ if (rect.isPointInside(m_pointer))
{
m_tooltip_element->setVisible(true);
this->bringToFront(m_tooltip_element);
return ItemStack();
}
-void GUIFormSpecMenu::acceptInput(bool quit=false)
+void GUIFormSpecMenu::acceptInput(FormspecQuitMode quitmode=quit_mode_no)
{
if(m_text_dst)
{
std::map<std::string, std::string> fields;
- if (quit) {
+ if (quitmode == quit_mode_accept) {
fields["quit"] = "true";
}
+ if (quitmode == quit_mode_cancel) {
+ fields["quit"] = "true";
+ m_text_dst->gotText(fields);
+ return;
+ }
+
if (current_keys_pending.key_down) {
fields["key_down"] = "true";
current_keys_pending.key_down = false;
for(u32 i=0; i<m_fields.size(); i++)
{
const FieldSpec &s = m_fields[i];
- if(s.send)
+ if(s.send)
{
if(s.ftype == f_Button)
{
fields[wide_to_narrow(s.fname.c_str())] = wide_to_narrow(s.flabel.c_str());
}
- else if(s.ftype == f_ListBox) {
- std::stringstream ss;
-
- if (m_listbox_doubleclick) {
- ss << "DCL:";
- }
- else {
- ss << "CHG:";
+ else if(s.ftype == f_Table) {
+ GUITable *table = getTable(s.fname);
+ if (table) {
+ fields[wide_to_narrow(s.fname.c_str())]
+ = table->checkEvent();
}
- ss << (getListboxIndex(wide_to_narrow(s.fname.c_str()))+1);
- fields[wide_to_narrow(s.fname.c_str())] = ss.str();
}
else if(s.ftype == f_DropDown) {
// no dynamic cast possible due to some distributions shipped
if ((element) && (element->getType() == gui::EGUIET_COMBO_BOX)) {
e = static_cast<gui::IGUIComboBox*>(element);
}
- fields[wide_to_narrow(s.fname.c_str())] =
- wide_to_narrow(e->getItem(e->getSelected()));
+ s32 selected = e->getSelected();
+ if (selected >= 0) {
+ fields[wide_to_narrow(s.fname.c_str())] =
+ wide_to_narrow(e->getItem(selected));
+ }
}
else if (s.ftype == f_TabHeader) {
// no dynamic cast possible due to some distributions shipped
bool GUIFormSpecMenu::preprocessEvent(const SEvent& event)
{
- // Fix Esc/Return key being eaten by checkboxen and listboxen
+ // Fix Esc/Return key being eaten by checkboxen and tables
if(event.EventType==EET_KEY_INPUT_EVENT)
{
KeyPress kp(event.KeyInput);
if (event.KeyInput.PressedDown && (kp == EscapeKey ||
kp == getKeySetting("keymap_inventory")))
{
- if (m_allowclose) {
- acceptInput(true);
+ if (m_allowclose){
+ doPause = false;
+ acceptInput(quit_mode_cancel);
quitMenu();
- } else {
+ } else {
m_text_dst->gotText(narrow_to_wide("MenuQuit"));
}
return true;
break;
}
if (current_keys_pending.key_enter && m_allowclose) {
- acceptInput(true);
+ acceptInput(quit_mode_accept);
quitMenu();
}
else {
if (btn_id == 257) {
if (m_allowclose) {
- acceptInput(true);
+ acceptInput(quit_mode_accept);
quitMenu();
} else {
acceptInput();
for(u32 i=0; i<m_fields.size(); i++)
{
FieldSpec &s = m_fields[i];
- // if its a button, set the send field so
+ // if its a button, set the send field so
// lua knows which button was pressed
if (((s.ftype == f_Button) || (s.ftype == f_CheckBox)) &&
(s.fid == event.GUIEvent.Caller->getID()))
{
s.send = true;
- acceptInput();
if(s.is_exit){
if (m_allowclose) {
- acceptInput(true);
+ acceptInput(quit_mode_accept);
quitMenu();
} else {
m_text_dst->gotText(narrow_to_wide("ExitButton"));
}
return true;
}else{
+ acceptInput();
s.send = false;
return true;
}
{
if (m_allowclose) {
- acceptInput(true);
+ acceptInput(quit_mode_accept);
quitMenu();
}
else {
}
}
- if((event.GUIEvent.EventType==gui::EGET_LISTBOX_SELECTED_AGAIN) ||
- (event.GUIEvent.EventType==gui::EGET_LISTBOX_CHANGED))
+ if(event.GUIEvent.EventType==gui::EGET_TABLE_CHANGED)
{
int current_id = event.GUIEvent.Caller->getID();
if(current_id > 257)
for(u32 i=0; i<m_fields.size(); i++)
{
FieldSpec &s = m_fields[i];
- // if its a listbox, set the send field so
- // lua knows which listbox was changed
- // checkListboxClick() is black magic
- // for properly handling double clicks
- if ((s.ftype == f_ListBox) && (s.fid == current_id)
- && checkListboxClick(s.fname,
- event.GUIEvent.EventType))
+ // if it's a table, set the send field
+ // so lua knows which table was changed
+ if ((s.ftype == f_Table) && (s.fid == current_id))
{
s.send = true;
acceptInput();
return Parent ? Parent->OnEvent(event) : false;
}
-static inline bool hex_digit_decode(char hexdigit, unsigned char &value)
-{
- if(hexdigit >= '0' && hexdigit <= '9')
- value = hexdigit - '0';
- else if(hexdigit >= 'A' && hexdigit <= 'F')
- value = hexdigit - 'A' + 10;
- else if(hexdigit >= 'a' && hexdigit <= 'f')
- value = hexdigit - 'a' + 10;
- else
- return false;
- return true;
-}
-
-bool GUIFormSpecMenu::parseColor(std::string &value, video::SColor &color, bool quiet)
+bool GUIFormSpecMenu::parseColor(const std::string &value, video::SColor &color,
+ bool quiet)
{
const char *hexpattern = NULL;
if (value[0] == '#') {