@@ -184,6 +184,38 @@ bool GUIFormSpecMenu::checkListboxClick(std::wstring wlistboxname,
184
184
return false ;
185
185
}
186
186
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
+
187
219
std::vector<std::string> split (const std::string &s, char delim) {
188
220
std::vector<std::string> tokens;
189
221
@@ -616,6 +648,13 @@ void GUIFormSpecMenu::parseTextList(parserData* data,std::string element) {
616
648
e->setSelected (data->listbox_selections [fname_w]);
617
649
}
618
650
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
+
619
658
if (str_initial_selection != " " )
620
659
e->setSelected (stoi (str_initial_selection.c_str ())-1 );
621
660
@@ -1417,11 +1456,18 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
1417
1456
1418
1457
// preserve listboxes
1419
1458
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 ();
1421
1463
if (selection != -1 ) {
1422
- std::wstring listboxname = m_listboxes[i].first .fname ;
1423
1464
mydata.listbox_selections [listboxname] = selection;
1424
1465
}
1466
+
1467
+ gui::IGUIScrollBar *scrollbar = getListboxScrollbar (listbox);
1468
+ if (scrollbar) {
1469
+ mydata.listbox_scroll [listboxname] = scrollbar->getPos ();
1470
+ }
1425
1471
}
1426
1472
1427
1473
// Remove children
0 commit comments