diff options
author | Kahrl <kahrl@gmx.net> | 2013-08-15 21:46:55 +0200 |
---|---|---|
committer | Kahrl <kahrl@gmx.net> | 2013-08-16 00:08:19 +0200 |
commit | d8337034b532638d246227d850154ee6b21c7ac9 (patch) | |
tree | 33dba2b884200976b720f5e5a14c3ee2f811865b /src | |
parent | 7921fe2cd1b284b35c28419fdf78873af456fded (diff) | |
download | minetest-d8337034b532638d246227d850154ee6b21c7ac9.tar.gz minetest-d8337034b532638d246227d850154ee6b21c7ac9.tar.bz2 minetest-d8337034b532638d246227d850154ee6b21c7ac9.zip |
Formspec textlist: Black Irrlicht magic to detect fake doubleclicks
Diffstat (limited to 'src')
-rw-r--r-- | src/guiFormSpecMenu.cpp | 62 | ||||
-rw-r--r-- | src/guiFormSpecMenu.h | 14 |
2 files changed, 66 insertions, 10 deletions
diff --git a/src/guiFormSpecMenu.cpp b/src/guiFormSpecMenu.cpp index 049341c14..79497dca1 100644 --- a/src/guiFormSpecMenu.cpp +++ b/src/guiFormSpecMenu.cpp @@ -43,6 +43,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/string.h" #include "util/numeric.h" #include "filesys.h" +#include "gettime.h" #include "gettext.h" @@ -81,6 +82,10 @@ GUIFormSpecMenu::GUIFormSpecMenu(irr::IrrlichtDevice* dev, 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_use_gettext(false), @@ -143,6 +148,42 @@ int GUIFormSpecMenu::getListboxIndex(std::string listboxname) { return -1; } +bool GUIFormSpecMenu::checkListboxClick(std::wstring wlistboxname, + int eventtype) +{ + // 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; + } + } + return false; +} + std::vector<std::string> split(const std::string &s, char delim) { std::vector<std::string> tokens; @@ -1920,7 +1961,7 @@ ItemStack GUIFormSpecMenu::verifySelectedItem() return ItemStack(); } -void GUIFormSpecMenu::acceptInput(int eventtype) +void GUIFormSpecMenu::acceptInput() { if(m_text_dst) { @@ -1957,11 +1998,12 @@ void GUIFormSpecMenu::acceptInput(int eventtype) } else if(s.ftype == f_ListBox) { std::stringstream ss; - if (eventtype == gui::EGET_LISTBOX_CHANGED) { - ss << "CHG:"; + + if (m_listbox_doubleclick) { + ss << "DCL:"; } else { - ss << "DCL:"; + ss << "CHG:"; } ss << (getListboxIndex(wide_to_narrow(s.fname.c_str()))+1); fields[wide_to_narrow(s.fname.c_str())] = ss.str(); @@ -2459,12 +2501,16 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) for(u32 i=0; i<m_fields.size(); i++) { FieldSpec &s = m_fields[i]; - // if its a button, set the send field so - // lua knows which button was pressed - if ((s.ftype == f_ListBox) && (s.fid == current_id)) + // 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)) { s.send = true; - acceptInput(event.GUIEvent.EventType); + acceptInput(); s.send=false; // Restore focus to the full form Environment->setFocus(this); diff --git a/src/guiFormSpecMenu.h b/src/guiFormSpecMenu.h index 84124afc3..28f11d2e7 100644 --- a/src/guiFormSpecMenu.h +++ b/src/guiFormSpecMenu.h @@ -228,9 +228,9 @@ public: void updateSelectedItem(); ItemStack verifySelectedItem(); - void acceptInput(int evttype=-1); + void acceptInput(); bool OnEvent(const SEvent& event); - + int getListboxIndex(std::string listboxname); protected: @@ -272,6 +272,12 @@ protected: ItemStack m_selected_content_guess; InventoryLocation m_selected_content_guess_inventory; + // WARNING: BLACK IRRLICHT MAGIC, see checkListboxClick() + std::wstring m_listbox_click_fname; + int m_listbox_click_index; + u32 m_listbox_click_time; + bool m_listbox_doubleclick; + v2s32 m_pointer; gui::IGUIStaticText *m_tooltip_element; @@ -301,6 +307,10 @@ private: fs_key_pendig current_keys_pending; + // Determine whether listbox click was double click + // (Using some black Irrlicht magic) + bool checkListboxClick(std::wstring wlistboxname, int eventtype); + void parseElement(parserData* data,std::string element); void parseSize(parserData* data,std::string element); |