summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKahrl <kahrl@gmx.net>2013-08-15 21:46:55 +0200
committerKahrl <kahrl@gmx.net>2013-08-16 00:08:19 +0200
commitd8337034b532638d246227d850154ee6b21c7ac9 (patch)
tree33dba2b884200976b720f5e5a14c3ee2f811865b /src
parent7921fe2cd1b284b35c28419fdf78873af456fded (diff)
downloadminetest-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.cpp62
-rw-r--r--src/guiFormSpecMenu.h14
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);