diff options
-rw-r--r-- | doc/lua_api.txt | 16 | ||||
-rw-r--r-- | src/guiFormSpecMenu.cpp | 127 | ||||
-rw-r--r-- | src/guiFormSpecMenu.h | 29 |
3 files changed, 124 insertions, 48 deletions
diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 6ed560869..58c3a133f 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -918,8 +918,14 @@ listcolors[<slot_bg_normal>;<slot_bg_hover>;<slot_border>;<tooltip_bgcolor>;<too ^ Sets background color of slots in HEX-Color format ^ Sets background color of slots on mouse hovering ^ Sets color of slots border -^ Sets background color of tooltips -^ Sets font color of tooltips +^ Sets default background color of tooltips +^ Sets default font color of tooltips + +tooltip[<gui_element_name>;<tooltip_text>;<bgcolor>,<fontcolor>] +^ Adds tooltip for an element +^ <bgcolor> tooltip background color in HEX-Color format (optional) +^ <fontcolor> tooltip font color in HEX-Color format (optional) + image[<X>,<Y>;<W>,<H>;<texture name>] ^ Show an image @@ -986,13 +992,12 @@ vertlabel[<X>,<Y>;<label>] ^ label is the text on the label ^ Position and size units are inventory slots -button[<X>,<Y>;<W>,<H>;<name>;<label>;<tooltip>] +button[<X>,<Y>;<W>,<H>;<name>;<label>] ^ Clickable button. When clicked, fields will be sent. ^ x, y and name work as per field ^ w and h are the size of the button ^ label is the text on the button ^ Position and size units are inventory slots -^ tooltip is optional image_button[<X>,<Y>;<W>,<H>;<texture name>;<name>;<label>] ^ x, y, w, h, and name work as per button @@ -1000,19 +1005,18 @@ image_button[<X>,<Y>;<W>,<H>;<texture name>;<name>;<label>] ^ Position and size units are inventory slots image_button[<X>,<Y>;<W>,<H>;<texture name>;<name>;<label>;<noclip>;<drawborder>;<pressed texture name>] -image_button[<X>,<Y>;<W>,<H>;<texture name>;<name>;<label>;<noclip>;<drawborder>;<pressed texture name>;<tooltip>] ^ x, y, w, h, and name work as per button ^ texture name is the filename of an image ^ Position and size units are inventory slots ^ noclip true meand imagebutton doesn't need to be within specified formsize ^ drawborder draw button bodrer or not ^ pressed texture name is the filename of an image on pressed state -^ tooltip is optional item_image_button[<X>,<Y>;<W>,<H>;<item name>;<name>;<label>] ^ x, y, w, h, name and label work as per button ^ item name is the registered name of an item/node, tooltip will be made out of its descritption + to override it use tooltip element ^ Position and size units are inventory slots button_exit[<X>,<Y>;<W>,<H>;<name>;<label>] diff --git a/src/guiFormSpecMenu.cpp b/src/guiFormSpecMenu.cpp index 802093284..3ff0274f8 100644 --- a/src/guiFormSpecMenu.cpp +++ b/src/guiFormSpecMenu.cpp @@ -405,7 +405,7 @@ void GUIFormSpecMenu::parseCheckbox(parserData* data,std::string element) { std::vector<std::string> parts = split(element,';'); - if ((parts.size() >= 3) || (parts.size() <= 5)) { + if ((parts.size() >= 3) || (parts.size() <= 4)) { std::vector<std::string> v_pos = split(parts[0],','); std::string name = parts[1]; std::string label = parts[2]; @@ -446,8 +446,7 @@ void GUIFormSpecMenu::parseCheckbox(parserData* data,std::string element) if (spec.fname == data->focused_fieldname) { Environment->setFocus(e); } - if (parts.size() >= 5) - spec.tooltip = parts[4]; + m_checkboxes.push_back(std::pair<FieldSpec,gui::IGUICheckBox*>(spec,e)); m_fields.push_back(spec); return; @@ -532,7 +531,7 @@ void GUIFormSpecMenu::parseButton(parserData* data,std::string element, { std::vector<std::string> parts = split(element,';'); - if (parts.size() == 4 || parts.size() == 5) { + if (parts.size() == 4) { std::vector<std::string> v_pos = split(parts[0],','); std::vector<std::string> v_geom = split(parts[1],','); std::string name = parts[2]; @@ -575,8 +574,6 @@ void GUIFormSpecMenu::parseButton(parserData* data,std::string element, if (spec.fname == data->focused_fieldname) { Environment->setFocus(e); } - if (parts.size() >= 5) - spec.tooltip = parts[4]; m_fields.push_back(spec); return; @@ -1202,7 +1199,7 @@ void GUIFormSpecMenu::parseImageButton(parserData* data,std::string element, { std::vector<std::string> parts = split(element,';'); - if (((parts.size() >= 5) && (parts.size() <= 9)) && (parts.size() != 6)) { + if (((parts.size() >= 5) && (parts.size() <= 8)) && (parts.size() != 6)) { std::vector<std::string> v_pos = split(parts[0],','); std::vector<std::string> v_geom = split(parts[1],','); std::string image_name = parts[2]; @@ -1268,9 +1265,7 @@ void GUIFormSpecMenu::parseImageButton(parserData* data,std::string element, if (spec.fname == data->focused_fieldname) { Environment->setFocus(e); } - if (parts.size() >= 9) - spec.tooltip = parts[8]; - + e->setUseAlphaChannel(true); e->setImage(texture); e->setPressedImage(pressed_texture); @@ -1392,7 +1387,11 @@ void GUIFormSpecMenu::parseItemImageButton(parserData* data,std::string element) ItemStack item; item.deSerialize(item_name, idef); video::ITexture *texture = idef->getInventoryTexture(item.getDefinition(idef).name, m_gamedef); - std::string tooltip = item.getDefinition(idef).description; + + m_tooltips[narrow_to_wide(name.c_str())] = + TooltipSpec (item.getDefinition(idef).description, + m_default_tooltip_bgcolor, + m_default_tooltip_color); label = unescape_string(label); FieldSpec spec( @@ -1415,7 +1414,6 @@ void GUIFormSpecMenu::parseItemImageButton(parserData* data,std::string element) spec.ftype = f_Button; rect+=data->basepos-padding; spec.rect=rect; - spec.tooltip = tooltip; m_fields.push_back(spec); return; } @@ -1489,15 +1487,33 @@ void GUIFormSpecMenu::parseListColors(parserData* data,std::string element) video::SColor tmp_color; if (parseColor(parts[3], tmp_color, false)) - m_tooltip_element->setBackgroundColor(tmp_color); + m_default_tooltip_bgcolor = tmp_color; if (parseColor(parts[4], tmp_color, false)) - m_tooltip_element->setOverrideColor(tmp_color); + m_default_tooltip_color = tmp_color; } return; } errorstream<< "Invalid listcolors element(" << parts.size() << "): '" << element << "'" << std::endl; } +void GUIFormSpecMenu::parseTooltip(parserData* data, std::string element) +{ + std::vector<std::string> 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); + return; + } else if (parts.size() == 4) { + std::string name = parts[0]; + video::SColor tmp_color1, tmp_color2; + if ( parseColor(parts[2], tmp_color1, false) && parseColor(parts[3], tmp_color2, false) ) { + m_tooltips[narrow_to_wide(name.c_str())] = TooltipSpec (parts[1], tmp_color1, tmp_color2); + return; + } + } + errorstream<< "Invalid tooltip element(" << parts.size() << "): '" << element << "'" << std::endl; +} + void GUIFormSpecMenu::parseElement(parserData* data,std::string element) { //some prechecks @@ -1639,6 +1655,11 @@ void GUIFormSpecMenu::parseElement(parserData* data,std::string element) return; } + if (type == "tooltip") { + parseTooltip(data,description); + return; + } + // Ignore others infostream << "Unknown DrawSpec: type="<<type<<", data=\""<<description<<"\"" @@ -1708,7 +1729,8 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) m_checkboxes.clear(); m_fields.clear(); m_boxes.clear(); - + m_tooltips.clear(); + // Set default values (fits old formspec values) m_bgcolor = video::SColor(140,0,0,0); m_bgfullscreen = false; @@ -1716,6 +1738,9 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) m_slotbg_n = video::SColor(255,128,128,128); m_slotbg_h = video::SColor(255,192,192,192); + m_default_tooltip_bgcolor = video::SColor(255,110,130,60); + m_default_tooltip_color = video::SColor(255,255,255,255); + m_slotbordercolor = video::SColor(200,0,0,0); m_slotborder = false; @@ -1726,10 +1751,10 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) // Note: parent != this so that the tooltip isn't clipped by the menu rectangle m_tooltip_element = Environment->addStaticText(L"",core::rect<s32>(0,0,110,18)); m_tooltip_element->enableOverrideColor(true); - m_tooltip_element->setBackgroundColor(video::SColor(255,110,130,60)); + m_tooltip_element->setBackgroundColor(m_default_tooltip_bgcolor); m_tooltip_element->setDrawBackground(true); m_tooltip_element->setDrawBorder(true); - m_tooltip_element->setOverrideColor(video::SColor(255,255,255,255)); + m_tooltip_element->setOverrideColor(m_default_tooltip_color); m_tooltip_element->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER); m_tooltip_element->setWordWrap(false); //we're not parent so no autograb for this one! @@ -1899,6 +1924,8 @@ void GUIFormSpecMenu::drawList(const ListDrawSpec &s, int phase) tooltip_text = item.getDefinition(m_gamedef->idef()).description; if(tooltip_text != "") { + m_tooltip_element->setBackgroundColor(m_default_tooltip_bgcolor); + 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()); @@ -2101,32 +2128,49 @@ void GUIFormSpecMenu::drawMenu() if (hovered != NULL) { s32 id = hovered->getID(); - for(std::vector<FieldSpec>::iterator iter = m_fields.begin(); + if (id == -1) { + m_old_tooltip_id = id; + m_old_tooltip = ""; + } else if (id != m_old_tooltip_id) { + m_hoovered_time = getTimeMs(); + m_old_tooltip_id = id; + } else if (id == m_old_tooltip_id) { + u32 delta = porting::getDeltaMs(m_hoovered_time, getTimeMs()); + if (delta <= 400) + goto skip_tooltip; + for(std::vector<FieldSpec>::iterator iter = m_fields.begin(); iter != m_fields.end(); iter++) { - if ( (iter->fid == id) && (iter->tooltip != "") ) { - m_tooltip_element->setVisible(true); - this->bringToFront(m_tooltip_element); - m_tooltip_element->setText(narrow_to_wide(iter->tooltip).c_str()); - s32 tooltip_x = m_pointer.X + m_btn_height; - s32 tooltip_y = m_pointer.Y + m_btn_height; - s32 tooltip_width = m_tooltip_element->getTextWidth() + m_btn_height; - if (tooltip_x + tooltip_width > (s32)screenSize.X) - tooltip_x = (s32)screenSize.X - tooltip_width - m_btn_height; - int lines_count = 1; - size_t i = 0; - while ((i = iter->tooltip.find("\n", i)) != std::string::npos) { - lines_count++; - i += 2; - } - s32 tooltip_height = m_tooltip_element->getTextHeight() * lines_count + 5; - m_tooltip_element->setRelativePosition(core::rect<s32>( - core::position2d<s32>(tooltip_x, tooltip_y), - core::dimension2d<s32>(tooltip_width, tooltip_height))); - break; + 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()); + s32 tooltip_x = m_pointer.X + m_btn_height; + s32 tooltip_y = m_pointer.Y + m_btn_height; + s32 tooltip_width = m_tooltip_element->getTextWidth() + m_btn_height; + if (tooltip_x + tooltip_width > (s32)screenSize.X) + tooltip_x = (s32)screenSize.X - tooltip_width - m_btn_height; + int lines_count = 1; + size_t i = 0; + while ((i = m_tooltips[iter->fname].tooltip.find("\n", i)) != std::string::npos) { + lines_count++; + i += 2; + } + s32 tooltip_height = m_tooltip_element->getTextHeight() * lines_count + 5; + m_tooltip_element->setRelativePosition(core::rect<s32>( + core::position2d<s32>(tooltip_x, tooltip_y), + core::dimension2d<s32>(tooltip_width, tooltip_height))); + } + m_tooltip_element->setBackgroundColor(m_tooltips[iter->fname].bgcolor); + m_tooltip_element->setOverrideColor(m_tooltips[iter->fname].color); + m_tooltip_element->setVisible(true); + this->bringToFront(m_tooltip_element); + break; + } } } } + skip_tooltip: /* Draw dragged item stack */ @@ -2403,7 +2447,10 @@ bool GUIFormSpecMenu::preprocessEvent(const SEvent& event) gui::IGUIElement *hovered = Environment->getRootGUIElement()->getElementFromPoint( core::position2d<s32>(x, y)); - + if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN) { + m_old_tooltip_id = -1; + m_old_tooltip = ""; + } if (!isChild(hovered,this)) { if (DoubleClickDetection(event)) { return true; @@ -2504,12 +2551,14 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) } } + if(event.EventType==EET_MOUSE_INPUT_EVENT && event.MouseInput.Event != EMIE_MOUSE_MOVED) { // Mouse event other than movement // Get selected item and hovered/clicked item (s) + m_old_tooltip_id = -1; updateSelectedItem(); ItemSpec s = getItemAtPos(m_pointer); diff --git a/src/guiFormSpecMenu.h b/src/guiFormSpecMenu.h index 81dd7ba16..da0826681 100644 --- a/src/guiFormSpecMenu.h +++ b/src/guiFormSpecMenu.h @@ -159,7 +159,6 @@ class GUIFormSpecMenu : public GUIModalMenu send = false; ftype = f_Unknown; is_exit = false; - tooltip=""; } std::wstring fname; std::wstring flabel; @@ -169,7 +168,6 @@ class GUIFormSpecMenu : public GUIModalMenu FormspecFieldType ftype; bool is_exit; core::rect<s32> rect; - std::string tooltip; }; struct BoxDrawSpec { @@ -184,6 +182,22 @@ class GUIFormSpecMenu : public GUIModalMenu irr::video::SColor color; }; + struct TooltipSpec { + TooltipSpec() + { + } + TooltipSpec(std::string a_tooltip, irr::video::SColor a_bgcolor, + irr::video::SColor a_color): + tooltip(a_tooltip), + bgcolor(a_bgcolor), + color(a_color) + { + } + std::string tooltip; + irr::video::SColor bgcolor; + irr::video::SColor color; + }; + public: GUIFormSpecMenu(irr::IrrlichtDevice* dev, gui::IGUIElement* parent, s32 id, @@ -286,7 +300,8 @@ protected: std::vector<FieldSpec> m_fields; std::vector<std::pair<FieldSpec,GUITable*> > m_tables; std::vector<std::pair<FieldSpec,gui::IGUICheckBox*> > m_checkboxes; - + std::map<std::wstring, TooltipSpec> m_tooltips; + ItemSpec *m_selected_item; u32 m_selected_amount; bool m_selected_dragging; @@ -300,6 +315,10 @@ protected: v2s32 m_pointer; gui::IGUIStaticText *m_tooltip_element; + s32 m_hoovered_time; + s32 m_old_tooltip_id; + std::string m_old_tooltip; + bool m_allowclose; bool m_lock; v2u32 m_lockscreensize; @@ -311,6 +330,9 @@ protected: video::SColor m_slotbg_n; video::SColor m_slotbg_h; video::SColor m_slotbordercolor; + video::SColor m_default_tooltip_bgcolor; + video::SColor m_default_tooltip_color; + private: IFormSource *m_form_src; TextDest *m_text_dst; @@ -366,6 +388,7 @@ private: void parseBox(parserData* data,std::string element); void parseBackgroundColor(parserData* data,std::string element); void parseListColors(parserData* data,std::string element); + void parseTooltip(parserData* data,std::string element); /** * check if event is part of a double click |