Skip to content

Commit d833703

Browse files
committedAug 15, 2013
Formspec textlist: Black Irrlicht magic to detect fake doubleclicks
1 parent 7921fe2 commit d833703

File tree

2 files changed

+66
-10
lines changed

2 files changed

+66
-10
lines changed
 

‎src/guiFormSpecMenu.cpp

+54-8
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
4343
#include "util/string.h"
4444
#include "util/numeric.h"
4545
#include "filesys.h"
46+
#include "gettime.h"
4647

4748
#include "gettext.h"
4849

@@ -81,6 +82,10 @@ GUIFormSpecMenu::GUIFormSpecMenu(irr::IrrlichtDevice* dev,
8182
m_selected_item(NULL),
8283
m_selected_amount(0),
8384
m_selected_dragging(false),
85+
m_listbox_click_fname(),
86+
m_listbox_click_index(-1),
87+
m_listbox_click_time(0),
88+
m_listbox_doubleclick(false),
8489
m_tooltip_element(NULL),
8590
m_allowclose(true),
8691
m_use_gettext(false),
@@ -143,6 +148,42 @@ int GUIFormSpecMenu::getListboxIndex(std::string listboxname) {
143148
return -1;
144149
}
145150

151+
bool GUIFormSpecMenu::checkListboxClick(std::wstring wlistboxname,
152+
int eventtype)
153+
{
154+
// WARNING: BLACK IRRLICHT MAGIC
155+
// Used to fix Irrlicht's subpar reporting of single clicks and double
156+
// clicks in listboxes (gui::EGET_LISTBOX_CHANGED,
157+
// gui::EGET_LISTBOX_SELECTED_AGAIN):
158+
// 1. IGUIListBox::setSelected() is counted as a click.
159+
// Including the initial setSelected() done by parseTextList().
160+
// 2. Clicking on a the selected item and then dragging for less
161+
// than 500ms is counted as a doubleclick, no matter when the
162+
// item was previously selected (e.g. more than 500ms ago)
163+
164+
// So when Irrlicht reports a doubleclick, we need to check
165+
// for ourselves if really was a doubleclick. Or just a fake.
166+
167+
for(unsigned int i=0; i < m_listboxes.size(); i++) {
168+
std::wstring name(m_listboxes[i].first.fname.c_str());
169+
int selected = m_listboxes[i].second->getSelected();
170+
if (name == wlistboxname && selected >= 0) {
171+
u32 now = getTimeMs();
172+
bool doubleclick =
173+
(eventtype == gui::EGET_LISTBOX_SELECTED_AGAIN)
174+
&& (name == m_listbox_click_fname)
175+
&& (selected == m_listbox_click_index)
176+
&& (m_listbox_click_time >= now - 500);
177+
m_listbox_click_fname = name;
178+
m_listbox_click_index = selected;
179+
m_listbox_click_time = now;
180+
m_listbox_doubleclick = doubleclick;
181+
return true;
182+
}
183+
}
184+
return false;
185+
}
186+
146187
std::vector<std::string> split(const std::string &s, char delim) {
147188
std::vector<std::string> tokens;
148189

@@ -1920,7 +1961,7 @@ ItemStack GUIFormSpecMenu::verifySelectedItem()
19201961
return ItemStack();
19211962
}
19221963

1923-
void GUIFormSpecMenu::acceptInput(int eventtype)
1964+
void GUIFormSpecMenu::acceptInput()
19241965
{
19251966
if(m_text_dst)
19261967
{
@@ -1957,11 +1998,12 @@ void GUIFormSpecMenu::acceptInput(int eventtype)
19571998
}
19581999
else if(s.ftype == f_ListBox) {
19592000
std::stringstream ss;
1960-
if (eventtype == gui::EGET_LISTBOX_CHANGED) {
1961-
ss << "CHG:";
2001+
2002+
if (m_listbox_doubleclick) {
2003+
ss << "DCL:";
19622004
}
19632005
else {
1964-
ss << "DCL:";
2006+
ss << "CHG:";
19652007
}
19662008
ss << (getListboxIndex(wide_to_narrow(s.fname.c_str()))+1);
19672009
fields[wide_to_narrow(s.fname.c_str())] = ss.str();
@@ -2459,12 +2501,16 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
24592501
for(u32 i=0; i<m_fields.size(); i++)
24602502
{
24612503
FieldSpec &s = m_fields[i];
2462-
// if its a button, set the send field so
2463-
// lua knows which button was pressed
2464-
if ((s.ftype == f_ListBox) && (s.fid == current_id))
2504+
// if its a listbox, set the send field so
2505+
// lua knows which listbox was changed
2506+
// checkListboxClick() is black magic
2507+
// for properly handling double clicks
2508+
if ((s.ftype == f_ListBox) && (s.fid == current_id)
2509+
&& checkListboxClick(s.fname,
2510+
event.GUIEvent.EventType))
24652511
{
24662512
s.send = true;
2467-
acceptInput(event.GUIEvent.EventType);
2513+
acceptInput();
24682514
s.send=false;
24692515
// Restore focus to the full form
24702516
Environment->setFocus(this);

‎src/guiFormSpecMenu.h

+12-2
Original file line numberDiff line numberDiff line change
@@ -228,9 +228,9 @@ class GUIFormSpecMenu : public GUIModalMenu
228228
void updateSelectedItem();
229229
ItemStack verifySelectedItem();
230230

231-
void acceptInput(int evttype=-1);
231+
void acceptInput();
232232
bool OnEvent(const SEvent& event);
233-
233+
234234
int getListboxIndex(std::string listboxname);
235235

236236
protected:
@@ -272,6 +272,12 @@ class GUIFormSpecMenu : public GUIModalMenu
272272
ItemStack m_selected_content_guess;
273273
InventoryLocation m_selected_content_guess_inventory;
274274

275+
// WARNING: BLACK IRRLICHT MAGIC, see checkListboxClick()
276+
std::wstring m_listbox_click_fname;
277+
int m_listbox_click_index;
278+
u32 m_listbox_click_time;
279+
bool m_listbox_doubleclick;
280+
275281
v2s32 m_pointer;
276282
gui::IGUIStaticText *m_tooltip_element;
277283

@@ -301,6 +307,10 @@ class GUIFormSpecMenu : public GUIModalMenu
301307

302308
fs_key_pendig current_keys_pending;
303309

310+
// Determine whether listbox click was double click
311+
// (Using some black Irrlicht magic)
312+
bool checkListboxClick(std::wstring wlistboxname, int eventtype);
313+
304314
void parseElement(parserData* data,std::string element);
305315

306316
void parseSize(parserData* data,std::string element);

0 commit comments

Comments
 (0)
Please sign in to comment.