Skip to content

Commit 5e312dc

Browse files
committedAug 15, 2013
Don't automatically scroll listbox when selecting an item in the middle
1 parent d833703 commit 5e312dc

File tree

2 files changed

+51
-2
lines changed

2 files changed

+51
-2
lines changed
 

‎src/guiFormSpecMenu.cpp

+48-2
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,38 @@ bool GUIFormSpecMenu::checkListboxClick(std::wstring wlistboxname,
184184
return false;
185185
}
186186

187+
gui::IGUIScrollBar* GUIFormSpecMenu::getListboxScrollbar(
188+
gui::IGUIListBox *listbox)
189+
{
190+
// WARNING: BLACK IRRLICHT MAGIC
191+
// Ordinarily, due to how formspecs work (recreating the entire GUI
192+
// when something changes), when you select an item in a textlist
193+
// with more items than fit in the visible area, the newly selected
194+
// item is scrolled to the bottom of the visible area. This is
195+
// annoying and breaks GUI designs that use double clicks.
196+
197+
// This function helps fixing this problem by giving direct access
198+
// to a listbox's scrollbar. This works because CGUIListBox doesn't
199+
// cache the scrollbar position anywhere.
200+
201+
// If this stops working in a future irrlicht version, consider
202+
// maintaining a local copy of irr::gui::CGUIListBox, possibly also
203+
// fixing the other reasons why black irrlicht magic is needed.
204+
205+
core::list<gui::IGUIElement*> children = listbox->getChildren();
206+
for(core::list<gui::IGUIElement*>::Iterator it = children.begin();
207+
it != children.end(); ++it) {
208+
gui::IGUIElement* child = *it;
209+
if (child && child->getType() == gui::EGUIET_SCROLL_BAR) {
210+
return static_cast<gui::IGUIScrollBar*>(child);
211+
}
212+
}
213+
214+
verbosestream<<"getListboxScrollbar: WARNING: "
215+
<<"listbox has no scrollbar"<<std::endl;
216+
return NULL;
217+
}
218+
187219
std::vector<std::string> split(const std::string &s, char delim) {
188220
std::vector<std::string> tokens;
189221

@@ -616,6 +648,13 @@ void GUIFormSpecMenu::parseTextList(parserData* data,std::string element) {
616648
e->setSelected(data->listbox_selections[fname_w]);
617649
}
618650

651+
if (data->listbox_scroll.find(fname_w) != data->listbox_scroll.end()) {
652+
gui::IGUIScrollBar *scrollbar = getListboxScrollbar(e);
653+
if (scrollbar) {
654+
scrollbar->setPos(data->listbox_scroll[fname_w]);
655+
}
656+
}
657+
619658
if (str_initial_selection != "")
620659
e->setSelected(stoi(str_initial_selection.c_str())-1);
621660

@@ -1417,11 +1456,18 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
14171456

14181457
//preserve listboxes
14191458
for (unsigned int i = 0; i < m_listboxes.size(); i++) {
1420-
int selection = m_listboxes[i].second->getSelected();
1459+
std::wstring listboxname = m_listboxes[i].first.fname;
1460+
gui::IGUIListBox *listbox = m_listboxes[i].second;
1461+
1462+
int selection = listbox->getSelected();
14211463
if (selection != -1) {
1422-
std::wstring listboxname = m_listboxes[i].first.fname;
14231464
mydata.listbox_selections[listboxname] = selection;
14241465
}
1466+
1467+
gui::IGUIScrollBar *scrollbar = getListboxScrollbar(listbox);
1468+
if (scrollbar) {
1469+
mydata.listbox_scroll[listboxname] = scrollbar->getPos();
1470+
}
14251471
}
14261472

14271473
// Remove children

‎src/guiFormSpecMenu.h

+3
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ class GUIFormSpecMenu : public GUIModalMenu
294294
int bp_set;
295295
v2u32 screensize;
296296
std::map<std::wstring,int> listbox_selections;
297+
std::map<std::wstring,int> listbox_scroll;
297298
} parserData;
298299

299300
typedef struct {
@@ -311,6 +312,8 @@ class GUIFormSpecMenu : public GUIModalMenu
311312
// (Using some black Irrlicht magic)
312313
bool checkListboxClick(std::wstring wlistboxname, int eventtype);
313314

315+
gui::IGUIScrollBar* getListboxScrollbar(gui::IGUIListBox *listbox);
316+
314317
void parseElement(parserData* data,std::string element);
315318

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

0 commit comments

Comments
 (0)
Please sign in to comment.