Skip to content

Commit 003634e

Browse files
sapiersapier
sapier
authored and
sapier
committedJun 12, 2014
Add support for exiting formspecs by doubleclicking outside
1 parent 763a511 commit 003634e

File tree

4 files changed

+136
-27
lines changed

4 files changed

+136
-27
lines changed
 

‎builtin/fstk/ui.lua

-1
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,6 @@ function ui.handle_events(event)
134134
local retval = value:handle_events(event)
135135

136136
if retval then
137-
print("event handled by: " .. key)
138137
return retval
139138
end
140139
end

‎src/guiFormSpecMenu.cpp

+102-21
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
4646
#include "gettime.h"
4747
#include "gettext.h"
4848
#include "scripting_game.h"
49+
#include "porting.h"
4950

5051
#define MY_CHECKPOS(a,b) \
5152
if (v_pos.size() != 2) { \
@@ -91,6 +92,12 @@ GUIFormSpecMenu::GUIFormSpecMenu(irr::IrrlichtDevice* dev,
9192
current_keys_pending.key_enter = false;
9293
current_keys_pending.key_escape = false;
9394

95+
m_doubleclickdetect[0].time = 0;
96+
m_doubleclickdetect[1].time = 0;
97+
98+
m_doubleclickdetect[0].pos = v2s32(0, 0);
99+
m_doubleclickdetect[1].pos = v2s32(0, 0);
100+
94101
}
95102

96103
GUIFormSpecMenu::~GUIFormSpecMenu()
@@ -1171,9 +1178,9 @@ void GUIFormSpecMenu::parseImageButton(parserData* data,std::string element,
11711178
if (parts[6] == "false")
11721179
drawborder = false;
11731180
}
1174-
1181+
11751182
std::string pressed_image_name = "";
1176-
1183+
11771184
if ((parts.size() == 8)) {
11781185
pressed_image_name = parts[7];
11791186
}
@@ -1265,9 +1272,11 @@ void GUIFormSpecMenu::parseTabHeader(parserData* data,std::string element)
12651272
geom.X = data->screensize.Y;
12661273
geom.Y = 30;
12671274

1268-
core::rect<s32> rect = core::rect<s32>(pos.X, pos.Y, pos.X+geom.X, pos.Y+geom.Y);
1275+
core::rect<s32> rect = core::rect<s32>(pos.X, pos.Y, pos.X+geom.X,
1276+
pos.Y+geom.Y);
12691277

1270-
gui::IGUITabControl *e = Environment->addTabControl(rect,this,show_background,show_border,spec.fid);
1278+
gui::IGUITabControl *e = Environment->addTabControl(rect, this,
1279+
show_background, show_border, spec.fid);
12711280

12721281
if (spec.fname == data->focused_fieldname) {
12731282
Environment->setFocus(e);
@@ -1276,7 +1285,7 @@ void GUIFormSpecMenu::parseTabHeader(parserData* data,std::string element)
12761285
e->setNotClipped(true);
12771286

12781287
for (unsigned int i=0; i< buttons.size(); i++) {
1279-
e->addTab(narrow_to_wide(buttons[i]).c_str(),-1);
1288+
e->addTab(narrow_to_wide(buttons[i]).c_str(), -1);
12801289
}
12811290

12821291
if ((tab_index >= 0) &&
@@ -1287,14 +1296,17 @@ void GUIFormSpecMenu::parseTabHeader(parserData* data,std::string element)
12871296
m_fields.push_back(spec);
12881297
return;
12891298
}
1290-
errorstream<< "Invalid TabHeader element(" << parts.size() << "): '" << element << "'" << std::endl;
1299+
errorstream << "Invalid TabHeader element(" << parts.size() << "): '"
1300+
<< element << "'" << std::endl;
12911301
}
12921302

12931303
void GUIFormSpecMenu::parseItemImageButton(parserData* data,std::string element)
12941304
{
12951305

12961306
if (m_gamedef == 0) {
1297-
errorstream<<"WARNING: invalid use of item_image_button with m_gamedef==0"<<std::endl;
1307+
errorstream <<
1308+
"WARNING: invalid use of item_image_button with m_gamedef==0"
1309+
<< std::endl;
12981310
return;
12991311
}
13001312

@@ -1414,7 +1426,7 @@ void GUIFormSpecMenu::parseListColors(parserData* data,std::string element)
14141426
if ((parts.size() == 2) || (parts.size() == 3) || (parts.size() == 5)) {
14151427
parseColor(parts[0], m_slotbg_n, false);
14161428
parseColor(parts[1], m_slotbg_h, false);
1417-
1429+
14181430
if (parts.size() >= 3) {
14191431
if (parseColor(parts[2], m_slotbordercolor, false)) {
14201432
m_slotborder = true;
@@ -1628,9 +1640,9 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
16281640
// A proceed button is added if there is no size[] element
16291641
mydata.bp_set = 0;
16301642

1631-
1643+
16321644
/* Convert m_init_draw_spec to m_inventorylists */
1633-
1645+
16341646
m_inventorylists.clear();
16351647
m_images.clear();
16361648
m_backgrounds.clear();
@@ -1710,7 +1722,7 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
17101722
GUIFormSpecMenu::ItemSpec GUIFormSpecMenu::getItemAtPos(v2s32 p) const
17111723
{
17121724
core::rect<s32> imgrect(0,0,imgsize.X,imgsize.Y);
1713-
1725+
17141726
for(u32 i=0; i<m_inventorylists.size(); i++)
17151727
{
17161728
const ListDrawSpec &s = m_inventorylists[i];
@@ -1741,7 +1753,7 @@ void GUIFormSpecMenu::drawList(const ListDrawSpec &s, int phase)
17411753
gui::IGUISkin* skin = Environment->getSkin();
17421754
if (skin)
17431755
font = skin->getFont();
1744-
1756+
17451757
Inventory *inv = m_invmgr->getInventory(s.inventoryloc);
17461758
if(!inv){
17471759
infostream<<"GUIFormSpecMenu::drawList(): WARNING: "
@@ -1758,9 +1770,9 @@ void GUIFormSpecMenu::drawList(const ListDrawSpec &s, int phase)
17581770
<<std::endl;
17591771
return;
17601772
}
1761-
1773+
17621774
core::rect<s32> imgrect(0,0,imgsize.X,imgsize.Y);
1763-
1775+
17641776
for(s32 i=0; i<s.geom.X*s.geom.Y; i++)
17651777
{
17661778
s32 item_i = i + s.start_item_i;
@@ -1855,7 +1867,7 @@ void GUIFormSpecMenu::drawSelectedItem()
18551867
gui::IGUISkin* skin = Environment->getSkin();
18561868
if (skin)
18571869
font = skin->getFont();
1858-
1870+
18591871
Inventory *inv = m_invmgr->getInventory(m_selected_item->inventoryloc);
18601872
assert(inv);
18611873
InventoryList *list = inv->getList(m_selected_item->listname);
@@ -1886,7 +1898,7 @@ void GUIFormSpecMenu::drawMenu()
18861898
if (!skin)
18871899
return;
18881900
video::IVideoDriver* driver = Environment->getVideoDriver();
1889-
1901+
18901902
v2u32 screenSize = driver->getScreenSize();
18911903
core::rect<s32> allbg(0, 0, screenSize.X , screenSize.Y);
18921904
if (m_bgfullscreen)
@@ -1930,7 +1942,7 @@ void GUIFormSpecMenu::drawMenu()
19301942
errorstream << "\t" << spec.name << std::endl;
19311943
}
19321944
}
1933-
1945+
19341946
/*
19351947
Draw Boxes
19361948
*/
@@ -1979,7 +1991,7 @@ void GUIFormSpecMenu::drawMenu()
19791991
errorstream << "\t" << spec.name << std::endl;
19801992
}
19811993
}
1982-
1994+
19831995
/*
19841996
Draw item images
19851997
*/
@@ -2004,7 +2016,7 @@ void GUIFormSpecMenu::drawMenu()
20042016
core::dimension2di(texture->getOriginalSize())),
20052017
NULL/*&AbsoluteClippingRect*/, colors, true);
20062018
}
2007-
2019+
20082020
/*
20092021
Draw items
20102022
Phase 0: Item slot rectangles
@@ -2021,7 +2033,7 @@ void GUIFormSpecMenu::drawMenu()
20212033
Call base class
20222034
*/
20232035
gui::IGUIElement::draw();
2024-
2036+
20252037
/*
20262038
Draw fields/buttons tooltips
20272039
*/
@@ -2046,7 +2058,7 @@ void GUIFormSpecMenu::drawMenu()
20462058
}
20472059
}
20482060
}
2049-
2061+
20502062
/*
20512063
Draw dragged item stack
20522064
*/
@@ -2276,6 +2288,17 @@ void GUIFormSpecMenu::acceptInput(FormspecQuitMode quitmode=quit_mode_no)
22762288
}
22772289
}
22782290

2291+
static bool isChild(gui::IGUIElement * tocheck, gui::IGUIElement * parent)
2292+
{
2293+
while(tocheck != NULL) {
2294+
if (tocheck == parent) {
2295+
return true;
2296+
}
2297+
tocheck = tocheck->getParent();
2298+
}
2299+
return false;
2300+
}
2301+
22792302
bool GUIFormSpecMenu::preprocessEvent(const SEvent& event)
22802303
{
22812304
// Fix Esc/Return key being eaten by checkboxen and tables
@@ -2306,6 +2329,64 @@ bool GUIFormSpecMenu::preprocessEvent(const SEvent& event)
23062329
}
23072330
}
23082331

2332+
if (event.EventType == EET_MOUSE_INPUT_EVENT) {
2333+
s32 x = event.MouseInput.X;
2334+
s32 y = event.MouseInput.Y;
2335+
gui::IGUIElement *hovered =
2336+
Environment->getRootGUIElement()->getElementFromPoint(
2337+
core::position2d<s32>(x, y));
2338+
2339+
if (!isChild(hovered,this)) {
2340+
if (DoubleClickDetection(event)) {
2341+
return true;
2342+
}
2343+
}
2344+
}
2345+
2346+
return false;
2347+
}
2348+
2349+
/******************************************************************************/
2350+
bool GUIFormSpecMenu::DoubleClickDetection(const SEvent event)
2351+
{
2352+
if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN) {
2353+
m_doubleclickdetect[0].pos = m_doubleclickdetect[1].pos;
2354+
m_doubleclickdetect[0].time = m_doubleclickdetect[1].time;
2355+
2356+
m_doubleclickdetect[1].pos = m_pointer;
2357+
m_doubleclickdetect[1].time = getTimeMs();
2358+
}
2359+
else if (event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP) {
2360+
u32 delta = porting::getDeltaMs(m_doubleclickdetect[0].time, getTimeMs());
2361+
if (delta > 400) {
2362+
return false;
2363+
}
2364+
2365+
double squaredistance =
2366+
m_doubleclickdetect[0].pos
2367+
.getDistanceFromSQ(m_doubleclickdetect[1].pos);
2368+
2369+
if (squaredistance > (30*30)) {
2370+
return false;
2371+
}
2372+
2373+
SEvent* translated = new SEvent();
2374+
assert(translated != 0);
2375+
//translate doubleclick to escape
2376+
memset(translated, 0, sizeof(SEvent));
2377+
translated->EventType = irr::EET_KEY_INPUT_EVENT;
2378+
translated->KeyInput.Key = KEY_ESCAPE;
2379+
translated->KeyInput.Control = false;
2380+
translated->KeyInput.Shift = false;
2381+
translated->KeyInput.PressedDown = true;
2382+
translated->KeyInput.Char = 0;
2383+
OnEvent(*translated);
2384+
2385+
// no need to send the key up event as we're already deleted
2386+
// and no one else did notice this event
2387+
delete translated;
2388+
return true;
2389+
}
23092390
return false;
23102391
}
23112392

‎src/guiFormSpecMenu.h

+19-5
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ class GUIFormSpecMenu : public GUIModalMenu
143143
v2s32 geom;
144144
bool scale;
145145
};
146-
146+
147147
struct FieldSpec
148148
{
149149
FieldSpec()
@@ -205,7 +205,7 @@ class GUIFormSpecMenu : public GUIModalMenu
205205
m_current_inventory_location = current_inventory_location;
206206
regenerateGui(m_screensize_old);
207207
}
208-
208+
209209
// form_src is deleted by this GUIFormSpecMenu
210210
void setFormSource(IFormSource *form_src)
211211
{
@@ -240,7 +240,7 @@ class GUIFormSpecMenu : public GUIModalMenu
240240
Remove and re-add (or reposition) stuff
241241
*/
242242
void regenerateGui(v2u32 screensize);
243-
243+
244244
ItemSpec getItemAtPos(v2s32 p) const;
245245
void drawList(const ListDrawSpec &s, int phase);
246246
void drawSelectedItem();
@@ -269,7 +269,7 @@ class GUIFormSpecMenu : public GUIModalMenu
269269
v2s32 spacing;
270270
v2s32 imgsize;
271271
v2s32 offset;
272-
272+
273273
irr::IrrlichtDevice* m_device;
274274
InventoryManager *m_invmgr;
275275
IGameDef *m_gamedef;
@@ -290,7 +290,7 @@ class GUIFormSpecMenu : public GUIModalMenu
290290
ItemSpec *m_selected_item;
291291
u32 m_selected_amount;
292292
bool m_selected_dragging;
293-
293+
294294
// WARNING: BLACK MAGIC
295295
// Used to guess and keep up with some special things the server can do.
296296
// If name is "", no guess exists.
@@ -366,6 +366,20 @@ class GUIFormSpecMenu : public GUIModalMenu
366366
void parseBox(parserData* data,std::string element);
367367
void parseBackgroundColor(parserData* data,std::string element);
368368
void parseListColors(parserData* data,std::string element);
369+
370+
/**
371+
* check if event is part of a double click
372+
* @param event event to evaluate
373+
* @return true/false if a doubleclick was detected
374+
*/
375+
bool DoubleClickDetection(const SEvent event);
376+
377+
struct clickpos
378+
{
379+
v2s32 pos;
380+
s32 time;
381+
};
382+
clickpos m_doubleclickdetect[2];
369383
};
370384

371385
class FormspecFormSource: public IFormSource

‎src/porting.h

+15
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,21 @@ inline u32 getTime(TimePrecision prec)
275275
return 0;
276276
}
277277

278+
/**
279+
* Delta calculation function taking two 32bit arguments.
280+
* @param old_time_ms old time for delta calculation (order is relevant!)
281+
* @param new_time_ms new time for delta calculation (order is relevant!)
282+
* @return positive 32bit delta value
283+
*/
284+
inline u32 getDeltaMs(u32 old_time_ms, u32 new_time_ms)
285+
{
286+
if (new_time_ms >= old_time_ms) {
287+
return (new_time_ms - old_time_ms);
288+
} else {
289+
return (old_time_ms - new_time_ms);
290+
}
291+
}
292+
278293
#if defined(linux) || defined(__linux)
279294
#include <sys/prctl.h>
280295

0 commit comments

Comments
 (0)
Please sign in to comment.