X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2FguiFormSpecMenu.cpp;h=0414dc41f0e27cb1464462b82e3392ec84aba494;hb=c977fbd9288d0e80019554411a2f1885f7760568;hp=80afe594a6685fa93e091b05ba1bf19039e89ecd;hpb=083d19b3fc8f60468e124c801296c13b66c41abc;p=dragonfireclient.git diff --git a/src/guiFormSpecMenu.cpp b/src/guiFormSpecMenu.cpp index 80afe594a..0414dc41f 100644 --- a/src/guiFormSpecMenu.cpp +++ b/src/guiFormSpecMenu.cpp @@ -37,21 +37,24 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #include "log.h" -#include "tile.h" // ITextureSource +#include "client/tile.h" // ITextureSource #include "hud.h" // drawItemStack -#include "hex.h" -#include "util/string.h" -#include "util/numeric.h" #include "filesys.h" #include "gettime.h" #include "gettext.h" #include "scripting_game.h" #include "porting.h" -#include "main.h" #include "settings.h" #include "client.h" -#include "util/string.h" // for parseColorString() #include "fontengine.h" +#include "util/hex.h" +#include "util/numeric.h" +#include "util/string.h" // for parseColorString() +#include "guiscalingfilter.h" + +#if USE_FREETYPE && IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 9 +#include "intlGUIEditBox.h" +#endif #define MY_CHECKPOS(a,b) \ if (v_pos.size() != 2) { \ @@ -74,44 +77,11 @@ static unsigned int font_line_height(gui::IGUIFont *font) return font->getDimension(L"Ay").Height + font->getKerningHeight(); } -static gui::IGUIFont *select_font_by_line_height(double target_line_height) -{ - // We don't get to directly select a font according to its - // baseline-to-baseline height. Rather, we select by em size. - // The ratio between these varies between fonts. The font - // engine also takes its size parameter not specified in pixels, - // as we want, but scaled by display density and gui_scaling, - // so invert that scaling here. Use a binary search among - // requested sizes to find the right font. Our starting bounds - // are an em height of 1 (being careful not to request size 0, - // which crashes the freetype system) and an em height of the - // target baseline-to-baseline height. - unsigned int loreq = ceil(1 / porting::getDisplayDensity() - / g_settings->getFloat("gui_scaling")); - unsigned int hireq = ceil(target_line_height - / porting::getDisplayDensity() - / g_settings->getFloat("gui_scaling")); - unsigned int lohgt = font_line_height(g_fontengine->getFont(loreq)); - unsigned int hihgt = font_line_height(g_fontengine->getFont(hireq)); - while(hireq - loreq > 1 && lohgt != hihgt) { - unsigned int nureq = (loreq + hireq) >> 1; - unsigned int nuhgt = font_line_height(g_fontengine->getFont(nureq)); - if(nuhgt < target_line_height) { - loreq = nureq; - lohgt = nuhgt; - } else { - hireq = nureq; - hihgt = nuhgt; - } - } - return g_fontengine->getFont(target_line_height - lohgt < hihgt - target_line_height ? loreq : hireq); -} - GUIFormSpecMenu::GUIFormSpecMenu(irr::IrrlichtDevice* dev, gui::IGUIElement* parent, s32 id, IMenuManager *menumgr, InventoryManager *invmgr, IGameDef *gamedef, ISimpleTextureSource *tsrc, IFormSource* fsrc, TextDest* tdst, - Client* client) : + Client* client, bool remap_dbl_click) : GUIModalMenu(dev->getGUIEnvironment(), parent, id, menumgr), m_device(dev), m_invmgr(invmgr), @@ -130,9 +100,11 @@ GUIFormSpecMenu::GUIFormSpecMenu(irr::IrrlichtDevice* dev, m_form_src(fsrc), m_text_dst(tdst), m_formspec_version(0), - m_font(NULL) + m_focused_element(""), + m_font(NULL), + m_remap_dbl_click(remap_dbl_click) #ifdef __ANDROID__ - ,m_JavaDialogFieldName(L"") + , m_JavaDialogFieldName("") #endif { current_keys_pending.key_down = false; @@ -259,7 +231,7 @@ void GUIFormSpecMenu::setInitialFocus() Environment->setFocus(*(children.begin())); } -GUITable* GUIFormSpecMenu::getTable(std::wstring tablename) +GUITable* GUIFormSpecMenu::getTable(const std::string &tablename) { for (u32 i = 0; i < m_tables.size(); ++i) { if (tablename == m_tables[i].first.fname) @@ -268,28 +240,27 @@ GUITable* GUIFormSpecMenu::getTable(std::wstring tablename) return 0; } -std::vector split(const std::string &s, char delim) { +static std::vector split(const std::string &s, char delim) +{ std::vector tokens; std::string current = ""; bool last_was_escape = false; - for(unsigned int i=0; i < s.size(); i++) { + for (unsigned int i = 0; i < s.size(); i++) { + char si = s.c_str()[i]; if (last_was_escape) { current += '\\'; - current += s.c_str()[i]; + current += si; last_was_escape = false; - } - else { - if (s.c_str()[i] == delim) { + } else { + if (si == delim) { tokens.push_back(current); current = ""; last_was_escape = false; - } - else if (s.c_str()[i] == '\\'){ + } else if (si == '\\') { last_was_escape = true; - } - else { - current += s.c_str()[i]; + } else { + current += si; last_was_escape = false; } } @@ -381,11 +352,45 @@ void GUIFormSpecMenu::parseList(parserData* data,std::string element) errorstream<< "Invalid list element(" << parts.size() << "): '" << element << "'" << std::endl; } +void GUIFormSpecMenu::parseListRing(parserData* data, std::string element) +{ + if (m_gamedef == 0) { + errorstream << "WARNING: invalid use of 'listring' with m_gamedef==0" << std::endl; + return; + } + + std::vector parts = split(element, ';'); + + if (parts.size() == 2) { + std::string location = parts[0]; + std::string listname = parts[1]; + + InventoryLocation loc; + + if (location == "context" || location == "current_name") + loc = m_current_inventory_location; + else + loc.deSerialize(location); + + m_inventory_rings.push_back(ListRingSpec(loc, listname)); + return; + } else if ((element == "") && (m_inventorylists.size() > 1)) { + size_t siz = m_inventorylists.size(); + // insert the last two inv list elements into the list ring + const ListDrawSpec &spa = m_inventorylists[siz - 2]; + const ListDrawSpec &spb = m_inventorylists[siz - 1]; + m_inventory_rings.push_back(ListRingSpec(spa.inventoryloc, spa.listname)); + m_inventory_rings.push_back(ListRingSpec(spb.inventoryloc, spb.listname)); + } + errorstream<< "Invalid list ring element(" << parts.size() << ", " + << m_inventorylists.size() << "): '" << element << "'" << std::endl; +} + void GUIFormSpecMenu::parseCheckbox(parserData* data,std::string element) { std::vector parts = split(element,';'); - if (((parts.size() >= 3) || (parts.size() <= 4)) || + if (((parts.size() >= 3) && (parts.size() <= 4)) || ((parts.size() > 4) && (m_formspec_version > FORMSPEC_API_VERSION))) { std::vector v_pos = split(parts[0],','); @@ -407,7 +412,7 @@ void GUIFormSpecMenu::parseCheckbox(parserData* data,std::string element) if (selected == "true") fselected = true; - std::wstring wlabel = narrow_to_wide(label.c_str()); + std::wstring wlabel = utf8_to_wide(label); core::rect rect = core::rect( pos.X, pos.Y + ((imgsize.Y/2) - m_btn_height), @@ -415,7 +420,7 @@ void GUIFormSpecMenu::parseCheckbox(parserData* data,std::string element) pos.Y + ((imgsize.Y/2) + m_btn_height)); FieldSpec spec( - narrow_to_wide(name.c_str()), + name, wlabel, //Needed for displaying text on MSVC wlabel, 258+m_fields.size() @@ -467,7 +472,7 @@ void GUIFormSpecMenu::parseScrollBar(parserData* data, std::string element) core::rect(pos.X, pos.Y, pos.X + dim.X, pos.Y + dim.Y); FieldSpec spec( - narrow_to_wide(name.c_str()), + name, L"", L"", 258+m_fields.size() @@ -605,10 +610,10 @@ void GUIFormSpecMenu::parseButton(parserData* data,std::string element, label = unescape_string(label); - std::wstring wlabel = narrow_to_wide(label.c_str()); + std::wstring wlabel = utf8_to_wide(label); FieldSpec spec( - narrow_to_wide(name.c_str()), + name, wlabel, L"", 258+m_fields.size() @@ -730,10 +735,8 @@ void GUIFormSpecMenu::parseTable(parserData* data,std::string element) core::rect rect = core::rect(pos.X, pos.Y, pos.X+geom.X, pos.Y+geom.Y); - std::wstring fname_w = narrow_to_wide(name.c_str()); - FieldSpec spec( - fname_w, + name, L"", L"", 258+m_fields.size() @@ -755,8 +758,8 @@ void GUIFormSpecMenu::parseTable(parserData* data,std::string element) e->setTable(data->table_options, data->table_columns, items); - if (data->table_dyndata.find(fname_w) != data->table_dyndata.end()) { - e->setDynamicData(data->table_dyndata[fname_w]); + if (data->table_dyndata.find(name) != data->table_dyndata.end()) { + e->setDynamicData(data->table_dyndata[name]); } if ((str_initial_selection != "") && @@ -804,10 +807,8 @@ void GUIFormSpecMenu::parseTextList(parserData* data,std::string element) core::rect rect = core::rect(pos.X, pos.Y, pos.X+geom.X, pos.Y+geom.Y); - std::wstring fname_w = narrow_to_wide(name.c_str()); - FieldSpec spec( - fname_w, + name, L"", L"", 258+m_fields.size() @@ -829,8 +830,8 @@ void GUIFormSpecMenu::parseTextList(parserData* data,std::string element) 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 (data->table_dyndata.find(name) != data->table_dyndata.end()) { + e->setDynamicData(data->table_dyndata[name]); } if ((str_initial_selection != "") && @@ -869,10 +870,8 @@ void GUIFormSpecMenu::parseDropDown(parserData* data,std::string element) core::rect rect = core::rect(pos.X, pos.Y, pos.X + width, pos.Y + (m_btn_height * 2)); - std::wstring fname_w = narrow_to_wide(name.c_str()); - FieldSpec spec( - fname_w, + name, L"", L"", 258+m_fields.size() @@ -889,7 +888,7 @@ void GUIFormSpecMenu::parseDropDown(parserData* data,std::string element) } for (unsigned int i=0; i < items.size(); i++) { - e->addItem(narrow_to_wide(items[i]).c_str()); + e->addItem(utf8_to_wide(items[i]).c_str()); } if (str_initial_selection != "") @@ -932,10 +931,10 @@ void GUIFormSpecMenu::parsePwdField(parserData* data,std::string element) label = unescape_string(label); - std::wstring wlabel = narrow_to_wide(label.c_str()); + std::wstring wlabel = utf8_to_wide(label); FieldSpec spec( - narrow_to_wide(name.c_str()), + name, wlabel, L"", 258+m_fields.size() @@ -950,7 +949,7 @@ void GUIFormSpecMenu::parsePwdField(parserData* data,std::string element) if (label.length() >= 1) { - int font_height = font_line_height(m_font); + int font_height = g_fontengine->getTextHeight(); rect.UpperLeftCorner.Y -= font_height; rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + font_height; Environment->addStaticText(spec.flabel.c_str(), rect, false, true, this, 0); @@ -998,12 +997,12 @@ void GUIFormSpecMenu::parseSimpleField(parserData* data, default_val = unescape_string(default_val); label = unescape_string(label); - std::wstring wlabel = narrow_to_wide(label.c_str()); + std::wstring wlabel = utf8_to_wide(label); FieldSpec spec( - narrow_to_wide(name.c_str()), + name, wlabel, - narrow_to_wide(default_val.c_str()), + utf8_to_wide(default_val), 258+m_fields.size() ); @@ -1015,9 +1014,17 @@ void GUIFormSpecMenu::parseSimpleField(parserData* data, else { spec.send = true; - gui::IGUIEditBox *e = - Environment->addEditBox(spec.fdefault.c_str(), rect, true, this, spec.fid); - + gui::IGUIElement *e; +#if USE_FREETYPE && IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 9 + if (g_settings->getBool("freetype")) { + e = (gui::IGUIElement *) new gui::intlGUIEditBox(spec.fdefault.c_str(), + true, Environment, this, spec.fid, rect); + } else { +#else + { +#endif + e = Environment->addEditBox(spec.fdefault.c_str(), rect, true, this, spec.fid); + } if (spec.fname == data->focused_fieldname) { Environment->setFocus(e); } @@ -1033,7 +1040,7 @@ void GUIFormSpecMenu::parseSimpleField(parserData* data, if (label.length() >= 1) { - int font_height = font_line_height(m_font); + int font_height = g_fontengine->getTextHeight(); rect.UpperLeftCorner.Y -= font_height; rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + font_height; Environment->addStaticText(spec.flabel.c_str(), rect, false, true, this, 0); @@ -1088,12 +1095,12 @@ void GUIFormSpecMenu::parseTextArea(parserData* data, default_val = unescape_string(default_val); label = unescape_string(label); - std::wstring wlabel = narrow_to_wide(label.c_str()); + std::wstring wlabel = utf8_to_wide(label); FieldSpec spec( - narrow_to_wide(name.c_str()), + name, wlabel, - narrow_to_wide(default_val.c_str()), + utf8_to_wide(default_val), 258+m_fields.size() ); @@ -1105,8 +1112,18 @@ void GUIFormSpecMenu::parseTextArea(parserData* data, else { spec.send = true; - gui::IGUIEditBox *e = - Environment->addEditBox(spec.fdefault.c_str(), rect, true, this, spec.fid); + + gui::IGUIEditBox *e; +#if USE_FREETYPE && IRRLICHT_VERSION_MAJOR == 1 && IRRLICHT_VERSION_MINOR < 9 + if (g_settings->getBool("freetype")) { + e = (gui::IGUIEditBox *) new gui::intlGUIEditBox(spec.fdefault.c_str(), + true, Environment, this, spec.fid, rect); + } else { +#else + { +#endif + e = Environment->addEditBox(spec.fdefault.c_str(), rect, true, this, spec.fid); + } if (spec.fname == data->focused_fieldname) { Environment->setFocus(e); @@ -1130,7 +1147,7 @@ void GUIFormSpecMenu::parseTextArea(parserData* data, if (label.length() >= 1) { - int font_height = font_line_height(m_font); + int font_height = g_fontengine->getTextHeight(); rect.UpperLeftCorner.Y -= font_height; rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + font_height; Environment->addStaticText(spec.flabel.c_str(), rect, false, true, this, 0); @@ -1177,8 +1194,6 @@ void GUIFormSpecMenu::parseLabel(parserData* data,std::string element) if(!data->explicit_size) errorstream<<"WARNING: invalid use of label without a size[] element"< lines = split(text, '\n'); @@ -1193,13 +1208,13 @@ void GUIFormSpecMenu::parseLabel(parserData* data,std::string element) // in the integer cases: 0.4 is not exactly // representable in binary floating point. s32 posy = pos.Y + ((float)i) * spacing.Y * 2.0 / 5.0; - std::wstring wlabel = narrow_to_wide(lines[i].c_str()); + std::wstring wlabel = utf8_to_wide(lines[i]); core::rect rect = core::rect( - pos.X, posy - font_height, + pos.X, posy - m_btn_height, pos.X + m_font->getDimension(wlabel.c_str()).Width, - posy + font_height); + posy + m_btn_height); FieldSpec spec( - L"", + "", wlabel, L"", 258+m_fields.size() @@ -1225,7 +1240,7 @@ void GUIFormSpecMenu::parseVertLabel(parserData* data,std::string element) ((parts.size() > 2) && (m_formspec_version > FORMSPEC_API_VERSION))) { std::vector v_pos = split(parts[0],','); - std::wstring text = narrow_to_wide(unescape_string(parts[1])); + std::wstring text = utf8_to_wide(unescape_string(parts[1])); MY_CHECKPOS("vertlabel",1); @@ -1252,7 +1267,7 @@ void GUIFormSpecMenu::parseVertLabel(parserData* data,std::string element) } FieldSpec spec( - L"", + "", label, L"", 258+m_fields.size() @@ -1314,12 +1329,12 @@ void GUIFormSpecMenu::parseImageButton(parserData* data,std::string element, pressed_image_name = unescape_string(pressed_image_name); label = unescape_string(label); - std::wstring wlabel = narrow_to_wide(label.c_str()); + std::wstring wlabel = utf8_to_wide(label); FieldSpec spec( - narrow_to_wide(name.c_str()), + name, wlabel, - narrow_to_wide(image_name.c_str()), + utf8_to_wide(image_name), 258+m_fields.size() ); spec.ftype = f_Button; @@ -1341,8 +1356,10 @@ void GUIFormSpecMenu::parseImageButton(parserData* data,std::string element, } e->setUseAlphaChannel(true); - e->setImage(texture); - e->setPressedImage(pressed_texture); + e->setImage(guiScalingImageButton( + Environment->getVideoDriver(), texture, geom.X, geom.Y)); + e->setPressedImage(guiScalingImageButton( + Environment->getVideoDriver(), pressed_texture, geom.X, geom.Y)); e->setScaleImage(true); e->setNotClipped(noclip); e->setDrawBorder(drawborder); @@ -1379,7 +1396,7 @@ void GUIFormSpecMenu::parseTabHeader(parserData* data,std::string element) } FieldSpec spec( - narrow_to_wide(name.c_str()), + name, L"", L"", 258+m_fields.size() @@ -1409,8 +1426,8 @@ void GUIFormSpecMenu::parseTabHeader(parserData* data,std::string element) e->setNotClipped(true); - for (unsigned int i=0; i< buttons.size(); i++) { - e->addTab(narrow_to_wide(buttons[i]).c_str(), -1); + for (unsigned int i = 0; i < buttons.size(); i++) { + e->addTab(utf8_to_wide(buttons[i]).c_str(), -1); } if ((tab_index >= 0) && @@ -1466,17 +1483,17 @@ void GUIFormSpecMenu::parseItemImageButton(parserData* data,std::string element) item.deSerialize(item_name, idef); video::ITexture *texture = idef->getInventoryTexture(item.getDefinition(idef).name, m_gamedef); - m_tooltips[narrow_to_wide(name.c_str())] = - TooltipSpec (item.getDefinition(idef).description, + m_tooltips[name] = + TooltipSpec(item.getDefinition(idef).description, m_default_tooltip_bgcolor, m_default_tooltip_color); label = unescape_string(label); FieldSpec spec( - narrow_to_wide(name.c_str()), - narrow_to_wide(label.c_str()), - narrow_to_wide(item_name.c_str()), - 258+m_fields.size() + name, + utf8_to_wide(label), + utf8_to_wide(item_name), + 258 + m_fields.size() ); gui::IGUIButton *e = Environment->addButton(rect, this, spec.fid, spec.flabel.c_str()); @@ -1486,8 +1503,8 @@ void GUIFormSpecMenu::parseItemImageButton(parserData* data,std::string element) } e->setUseAlphaChannel(true); - e->setImage(texture); - e->setPressedImage(texture); + e->setImage(guiScalingImageButton(Environment->getVideoDriver(), texture, geom.X, geom.Y)); + e->setPressedImage(guiScalingImageButton(Environment->getVideoDriver(), texture, geom.X, geom.Y)); e->setScaleImage(true); spec.ftype = f_Button; rect+=data->basepos-padding; @@ -1585,13 +1602,15 @@ void GUIFormSpecMenu::parseTooltip(parserData* data, std::string element) std::vector parts = split(element,';'); if (parts.size() == 2) { std::string name = parts[0]; - m_tooltips[narrow_to_wide(name.c_str())] = TooltipSpec (parts[1], m_default_tooltip_bgcolor, m_default_tooltip_color); + m_tooltips[name] = TooltipSpec(unescape_string(parts[1]), + m_default_tooltip_bgcolor, m_default_tooltip_color); return; } else if (parts.size() == 4) { std::string name = parts[0]; video::SColor tmp_color1, tmp_color2; if ( parseColorString(parts[2], tmp_color1, false) && parseColorString(parts[3], tmp_color2, false) ) { - m_tooltips[narrow_to_wide(name.c_str())] = TooltipSpec (parts[1], tmp_color1, tmp_color2); + m_tooltips[name] = TooltipSpec(unescape_string(parts[1]), + tmp_color1, tmp_color2); return; } } @@ -1676,6 +1695,11 @@ void GUIFormSpecMenu::parseElement(parserData* data, std::string element) return; } + if (type == "listring") { + parseListRing(data, description); + return; + } + if (type == "checkbox") { parseCheckbox(data,description); return; @@ -1792,8 +1816,6 @@ void GUIFormSpecMenu::parseElement(parserData* data, std::string element) <getDynamicData(); } + //set focus + if (!m_focused_element.empty()) + mydata.focused_fieldname = m_focused_element; + //preserve focus gui::IGUIElement *focused_element = Environment->getFocus(); if (focused_element && focused_element->getParent() == this) { @@ -1974,11 +2000,9 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) imgsize = v2s32(use_imgsize, use_imgsize); spacing = v2s32(use_imgsize*5.0/4, use_imgsize*15.0/13); padding = v2s32(use_imgsize*3.0/8, use_imgsize*3.0/8); - double target_font_height = use_imgsize*15.0/13 * 0.4; - target_font_height *= g_settings->getFloat("font_size")/TTF_DEFAULT_FONT_SIZE; m_btn_height = use_imgsize*15.0/13 * 0.35; - m_font = select_font_by_line_height(target_font_height); + m_font = g_fontengine->getFont(); mydata.size = v2s32( padding.X*2+spacing.X*(mydata.invsize.X-1.0)+imgsize.X, @@ -2008,7 +2032,7 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) m_tooltip_element->setOverrideFont(m_font); gui::IGUISkin* skin = Environment->getSkin(); - assert(skin != NULL); + sanity_check(skin != NULL); gui::IGUIFont *old_font = skin->getFont(); skin->setFont(m_font); @@ -2037,7 +2061,7 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) mydata.rect = core::rect(size.X/2-70, pos.Y, (size.X/2-70)+140, pos.Y + (m_btn_height*2)); - wchar_t* text = wgettext("Proceed"); + const wchar_t *text = wgettext("Proceed"); Environment->addButton(mydata.rect, this, 257, text); delete[] text; } @@ -2058,7 +2082,7 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) bool GUIFormSpecMenu::getAndroidUIInput() { /* no dialog shown */ - if (m_JavaDialogFieldName == L"") { + if (m_JavaDialogFieldName == "") { return false; } @@ -2067,8 +2091,8 @@ bool GUIFormSpecMenu::getAndroidUIInput() return true; } - std::wstring fieldname = m_JavaDialogFieldName; - m_JavaDialogFieldName = L""; + std::string fieldname = m_JavaDialogFieldName; + m_JavaDialogFieldName = ""; /* no value abort dialog processing */ if (porting::getInputDialogState() != 0) { @@ -2094,7 +2118,7 @@ bool GUIFormSpecMenu::getAndroidUIInput() std::string text = porting::getInputDialogValue(); ((gui::IGUIEditBox*) tochange)-> - setText(narrow_to_wide(text).c_str()); + setText(utf8_to_wide(text).c_str()); } return false; } @@ -2218,7 +2242,7 @@ void GUIFormSpecMenu::drawList(const ListDrawSpec &s, int phase) m_tooltip_element->setOverrideColor(m_default_tooltip_color); m_tooltip_element->setVisible(true); this->bringToFront(m_tooltip_element); - m_tooltip_element->setText(narrow_to_wide(tooltip_text).c_str()); + m_tooltip_element->setText(utf8_to_wide(tooltip_text).c_str()); s32 tooltip_width = m_tooltip_element->getTextWidth() + m_btn_height; s32 tooltip_height = m_tooltip_element->getTextHeight() * tt_rows.size() + 5; v2u32 screenSize = driver->getScreenSize(); @@ -2252,9 +2276,9 @@ void GUIFormSpecMenu::drawSelectedItem() video::IVideoDriver* driver = Environment->getVideoDriver(); Inventory *inv = m_invmgr->getInventory(m_selected_item->inventoryloc); - assert(inv); + sanity_check(inv); InventoryList *list = inv->getList(m_selected_item->listname); - assert(list); + sanity_check(list); ItemStack stack = list->getItem(m_selected_item->i); stack.count = m_selected_amount; @@ -2274,7 +2298,7 @@ void GUIFormSpecMenu::drawMenu() } gui::IGUISkin* skin = Environment->getSkin(); - assert(skin != NULL); + sanity_check(skin != NULL); gui::IGUIFont *old_font = skin->getFont(); skin->setFont(m_font); @@ -2315,7 +2339,7 @@ void GUIFormSpecMenu::drawMenu() const video::SColor color(255,255,255,255); const video::SColor colors[] = {color,color,color,color}; - driver->draw2DImage(texture, rect, + draw2DImageFilterScaled(driver, texture, rect, core::rect(core::position2d(0,0), core::dimension2di(texture->getOriginalSize())), NULL/*&AbsoluteClippingRect*/, colors, true); @@ -2365,7 +2389,7 @@ void GUIFormSpecMenu::drawMenu() core::rect rect = imgrect + spec.pos; const video::SColor color(255,255,255,255); const video::SColor colors[] = {color,color,color,color}; - driver->draw2DImage(texture, rect, + draw2DImageFilterScaled(driver, texture, rect, core::rect(core::position2d(0,0),img_origsize), NULL/*&AbsoluteClippingRect*/, colors, true); } @@ -2394,7 +2418,7 @@ void GUIFormSpecMenu::drawMenu() core::rect rect = imgrect + spec.pos; const video::SColor color(255,255,255,255); const video::SColor colors[] = {color,color,color,color}; - driver->draw2DImage(texture, rect, + draw2DImageFilterScaled(driver, texture, rect, core::rect(core::position2d(0,0), core::dimension2di(texture->getOriginalSize())), NULL/*&AbsoluteClippingRect*/, colors, true); @@ -2450,7 +2474,7 @@ void GUIFormSpecMenu::drawMenu() if ( (iter->fid == id) && (m_tooltips[iter->fname].tooltip != "") ){ if (m_old_tooltip != m_tooltips[iter->fname].tooltip) { m_old_tooltip = m_tooltips[iter->fname].tooltip; - m_tooltip_element->setText(narrow_to_wide(m_tooltips[iter->fname].tooltip).c_str()); + m_tooltip_element->setText(utf8_to_wide(m_tooltips[iter->fname].tooltip).c_str()); std::vector tt_rows = str_split(m_tooltips[iter->fname].tooltip, '\n'); s32 tooltip_width = m_tooltip_element->getTextWidth() + m_btn_height; s32 tooltip_height = m_tooltip_element->getTextHeight() * tt_rows.size() + 5; @@ -2609,7 +2633,7 @@ void GUIFormSpecMenu::acceptInput(FormspecQuitMode quitmode=quit_mode_no) { if(m_text_dst) { - std::map fields; + StringMap fields; if (quitmode == quit_mode_accept) { fields["quit"] = "true"; @@ -2644,11 +2668,10 @@ void GUIFormSpecMenu::acceptInput(FormspecQuitMode quitmode=quit_mode_no) for(unsigned int i=0; icheckEvent(); @@ -2665,7 +2688,7 @@ void GUIFormSpecMenu::acceptInput(FormspecQuitMode quitmode=quit_mode_no) s32 selected = e->getSelected(); if (selected >= 0) { fields[name] = - wide_to_narrow(e->getItem(selected)); + wide_to_utf8(e->getItem(selected)); } } else if (s.ftype == f_TabHeader) { @@ -2721,7 +2744,7 @@ void GUIFormSpecMenu::acceptInput(FormspecQuitMode quitmode=quit_mode_no) { IGUIElement* e = getElementFromId(s.fid); if(e != NULL) { - fields[name] = wide_to_narrow(e->getText()); + fields[name] = wide_to_utf8(e->getText()); } } } @@ -2760,7 +2783,7 @@ bool GUIFormSpecMenu::preprocessEvent(const SEvent& event) if (hovered && isMyChild(hovered) && hovered->getType() == gui::EGUIET_TAB_CONTROL) { gui::IGUISkin* skin = Environment->getSkin(); - assert(skin != NULL); + sanity_check(skin != NULL); gui::IGUIFont *old_font = skin->getFont(); skin->setFont(m_font); bool retval = hovered->OnEvent(event); @@ -2829,7 +2852,7 @@ bool GUIFormSpecMenu::preprocessEvent(const SEvent& event) } m_JavaDialogFieldName = getNameByID(hovered->getID()); std::string message = gettext("Enter "); - std::string label = wide_to_narrow(getLabelByID(hovered->getID())); + std::string label = wide_to_utf8(getLabelByID(hovered->getID())); if (label == "") { label = "text"; } @@ -2849,7 +2872,7 @@ bool GUIFormSpecMenu::preprocessEvent(const SEvent& event) } porting::showInputDialog(gettext("ok"), "", - wide_to_narrow(((gui::IGUIEditBox*) hovered)->getText()), + wide_to_utf8(((gui::IGUIEditBox*) hovered)->getText()), type); return retval; } @@ -2971,6 +2994,19 @@ bool GUIFormSpecMenu::preprocessEvent(const SEvent& event) /******************************************************************************/ bool GUIFormSpecMenu::DoubleClickDetection(const SEvent event) { + /* The following code is for capturing double-clicks of the mouse button + * and translating the double-click into an EET_KEY_INPUT_EVENT event + * -- which closes the form -- under some circumstances. + * + * There have been many github issues reporting this as a bug even though it + * was an intended feature. For this reason, remapping the double-click as + * an ESC must be explicitly set when creating this class via the + * /p remap_dbl_click parameter of the constructor. + */ + + if (!m_remap_dbl_click) + return false; + if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN) { m_doubleclickdetect[0].pos = m_doubleclickdetect[1].pos; m_doubleclickdetect[0].time = m_doubleclickdetect[1].time; @@ -3009,6 +3045,7 @@ bool GUIFormSpecMenu::DoubleClickDetection(const SEvent event) delete translated; return true; } + return false; } @@ -3023,7 +3060,7 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) acceptInput(quit_mode_cancel); quitMenu(); } else { - m_text_dst->gotText(narrow_to_wide("MenuQuit")); + m_text_dst->gotText(L"MenuQuit"); } return true; } else if (m_client != NULL && event.KeyInput.PressedDown && @@ -3048,7 +3085,7 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) break; default: //can't happen at all! - assert("reached a source line that can't ever been reached" == 0); + FATAL_ERROR("Reached a source line that can't ever been reached"); break; } if (current_keys_pending.key_enter && m_allowclose) { @@ -3082,8 +3119,8 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) if(m_selected_item) { inv_selected = m_invmgr->getInventory(m_selected_item->inventoryloc); - assert(inv_selected); - assert(inv_selected->getList(m_selected_item->listname) != NULL); + sanity_check(inv_selected); + sanity_check(inv_selected->getList(m_selected_item->listname) != NULL); } u32 s_count = 0; @@ -3147,6 +3184,10 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) // from m_selected_item to s. u32 move_amount = 0; + // Set this number to a positive value to generate a move action + // from s to the next inventory ring. + u32 shift_move_amount = 0; + // Set this number to a positive value to generate a drop action // from m_selected_item. u32 drop_amount = 0; @@ -3168,18 +3209,29 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) } else if(m_selected_item == NULL) { if(s_count != 0) { - // Non-empty stack has been clicked: select it + // Non-empty stack has been clicked: select or shift-move it m_selected_item = new ItemSpec(s); + u32 count; if(button == 1) // right - m_selected_amount = (s_count + 1) / 2; + count = (s_count + 1) / 2; else if(button == 2) // middle - m_selected_amount = MYMIN(s_count, 10); + count = MYMIN(s_count, 10); else // left - m_selected_amount = s_count; + count = s_count; - m_selected_dragging = true; - m_rmouse_auto_place = false; + if (!event.MouseInput.Shift) { + // no shift: select item + m_selected_amount = count; + m_selected_dragging = true; + m_rmouse_auto_place = false; + } else { + // shift pressed: move item + if (button != 1) + shift_move_amount = count; + else // count of 1 at left click like after drag & drop + shift_move_amount = 1; + } } } else { // m_selected_item != NULL @@ -3261,8 +3313,7 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) } // Possibly send inventory action to server - if(move_amount > 0) - { + if (move_amount > 0) { // Send IACTION_MOVE assert(m_selected_item && m_selected_item->isValid()); @@ -3310,8 +3361,57 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) a->to_list = s.listname; a->to_i = s.i; m_invmgr->inventoryAction(a); - } - else if(drop_amount > 0) { + } else if (shift_move_amount > 0) { + u32 mis = m_inventory_rings.size(); + u32 i = 0; + for (; i < mis; i++) { + const ListRingSpec &sp = m_inventory_rings[i]; + if (sp.inventoryloc == s.inventoryloc + && sp.listname == s.listname) + break; + } + do { + if (i >= mis) // if not found + break; + u32 to_inv_ind = (i + 1) % mis; + const ListRingSpec &to_inv_sp = m_inventory_rings[to_inv_ind]; + InventoryList *list_from = inv_s->getList(s.listname); + if (!list_from) + break; + Inventory *inv_to = m_invmgr->getInventory(to_inv_sp.inventoryloc); + if (!inv_to) + break; + InventoryList *list_to = inv_to->getList(to_inv_sp.listname); + if (!list_to) + break; + ItemStack stack_from = list_from->getItem(s.i); + assert(shift_move_amount <= stack_from.count); + + // find a place (or more than one) to add the new item + u32 slot_to = 0; + u32 ilt_size = list_to->getSize(); + ItemStack leftover; + for (; slot_to < ilt_size && shift_move_amount > 0; slot_to++) { + list_to->itemFits(slot_to, stack_from, &leftover); + if (leftover.count < stack_from.count) { + infostream << "Handing IACTION_MOVE to manager" << std::endl; + IMoveAction *a = new IMoveAction(); + a->count = MYMIN(shift_move_amount, + (u32) (stack_from.count - leftover.count)); + shift_move_amount -= a->count; + a->from_inv = s.inventoryloc; + a->from_list = s.listname; + a->from_i = s.i; + a->to_inv = to_inv_sp.inventoryloc; + a->to_list = to_inv_sp.listname; + a->to_i = slot_to; + m_invmgr->inventoryAction(a); + stack_from = leftover; + } + } + } while (0); + + } else if (drop_amount > 0) { m_selected_content_guess = ItemStack(); // Clear // Send IACTION_DROP @@ -3397,7 +3497,7 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) quitMenu(); } else { acceptInput(); - m_text_dst->gotText(narrow_to_wide("ExitButton")); + m_text_dst->gotText(L"ExitButton"); } // quitMenu deallocates menu return true; @@ -3416,7 +3516,7 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) acceptInput(quit_mode_accept); quitMenu(); } else { - m_text_dst->gotText(narrow_to_wide("ExitButton")); + m_text_dst->gotText(L"ExitButton"); } return true; } else { @@ -3499,7 +3599,7 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) * @param id of element * @return name string or empty string */ -std::wstring GUIFormSpecMenu::getNameByID(s32 id) +std::string GUIFormSpecMenu::getNameByID(s32 id) { for(std::vector::iterator iter = m_fields.begin(); iter != m_fields.end(); iter++) { @@ -3507,7 +3607,7 @@ std::wstring GUIFormSpecMenu::getNameByID(s32 id) return iter->fname; } } - return L""; + return ""; } /**