@@ -627,7 +627,7 @@ void GUIFormSpecMenu::parseCheckbox(parserData* data, const std::string &element
627
627
auto style = getDefaultStyleForElement (" checkbox" , name);
628
628
e->setNotClipped (style.getBool (StyleSpec::NOCLIP, false ));
629
629
630
- if (spec.fname == data-> focused_fieldname ) {
630
+ if (spec.fname == m_focused_element ) {
631
631
Environment->setFocus (e);
632
632
}
633
633
@@ -703,6 +703,10 @@ void GUIFormSpecMenu::parseScrollBar(parserData* data, const std::string &elemen
703
703
704
704
e->setPageSize (scrollbar_size * (max - min + 1 ) / data->scrollbar_options .thumb_size );
705
705
706
+ if (spec.fname == m_focused_element) {
707
+ Environment->setFocus (e);
708
+ }
709
+
706
710
m_scrollbars.emplace_back (spec,e);
707
711
m_fields.push_back (spec);
708
712
return ;
@@ -1029,7 +1033,7 @@ void GUIFormSpecMenu::parseButton(parserData* data, const std::string &element,
1029
1033
auto style = getStyleForElement (type, name, (type != " button" ) ? " button" : " " );
1030
1034
e->setStyles (style);
1031
1035
1032
- if (spec.fname == data-> focused_fieldname ) {
1036
+ if (spec.fname == m_focused_element ) {
1033
1037
Environment->setFocus (e);
1034
1038
}
1035
1039
@@ -1218,7 +1222,7 @@ void GUIFormSpecMenu::parseTable(parserData* data, const std::string &element)
1218
1222
GUITable *e = new GUITable (Environment, data->current_parent , spec.fid ,
1219
1223
rect, m_tsrc);
1220
1224
1221
- if (spec.fname == data-> focused_fieldname ) {
1225
+ if (spec.fname == m_focused_element ) {
1222
1226
Environment->setFocus (e);
1223
1227
}
1224
1228
@@ -1295,7 +1299,7 @@ void GUIFormSpecMenu::parseTextList(parserData* data, const std::string &element
1295
1299
GUITable *e = new GUITable (Environment, data->current_parent , spec.fid ,
1296
1300
rect, m_tsrc);
1297
1301
1298
- if (spec.fname == data-> focused_fieldname ) {
1302
+ if (spec.fname == m_focused_element ) {
1299
1303
Environment->setFocus (e);
1300
1304
}
1301
1305
@@ -1373,7 +1377,7 @@ void GUIFormSpecMenu::parseDropDown(parserData* data, const std::string &element
1373
1377
gui::IGUIComboBox *e = Environment->addComboBox (rect, data->current_parent ,
1374
1378
spec.fid );
1375
1379
1376
- if (spec.fname == data-> focused_fieldname ) {
1380
+ if (spec.fname == m_focused_element ) {
1377
1381
Environment->setFocus (e);
1378
1382
}
1379
1383
@@ -1460,7 +1464,7 @@ void GUIFormSpecMenu::parsePwdField(parserData* data, const std::string &element
1460
1464
gui::IGUIEditBox *e = Environment->addEditBox (0 , rect, true ,
1461
1465
data->current_parent , spec.fid );
1462
1466
1463
- if (spec.fname == data-> focused_fieldname ) {
1467
+ if (spec.fname == m_focused_element ) {
1464
1468
Environment->setFocus (e);
1465
1469
}
1466
1470
@@ -1537,7 +1541,7 @@ void GUIFormSpecMenu::createTextField(parserData *data, FieldSpec &spec,
1537
1541
auto style = getDefaultStyleForElement (is_multiline ? " textarea" : " field" , spec.fname );
1538
1542
1539
1543
if (e) {
1540
- if (is_editable && spec.fname == data-> focused_fieldname )
1544
+ if (is_editable && spec.fname == m_focused_element )
1541
1545
Environment->setFocus (e);
1542
1546
1543
1547
if (is_multiline) {
@@ -1986,7 +1990,7 @@ void GUIFormSpecMenu::parseImageButton(parserData* data, const std::string &elem
1986
1990
GUIButtonImage *e = GUIButtonImage::addButton (Environment, rect, m_tsrc,
1987
1991
data->current_parent , spec.fid , spec.flabel .c_str ());
1988
1992
1989
- if (spec.fname == data-> focused_fieldname ) {
1993
+ if (spec.fname == m_focused_element ) {
1990
1994
Environment->setFocus (e);
1991
1995
}
1992
1996
@@ -2099,10 +2103,6 @@ void GUIFormSpecMenu::parseTabHeader(parserData* data, const std::string &elemen
2099
2103
irr::gui::EGUIA_UPPERLEFT, irr::gui::EGUIA_LOWERRIGHT);
2100
2104
e->setTabHeight (geom.Y );
2101
2105
2102
- if (spec.fname == data->focused_fieldname ) {
2103
- Environment->setFocus (e);
2104
- }
2105
-
2106
2106
auto style = getDefaultStyleForElement (" tabheader" , name);
2107
2107
e->setNotClipped (style.getBool (StyleSpec::NOCLIP, true ));
2108
2108
@@ -2194,7 +2194,7 @@ void GUIFormSpecMenu::parseItemImageButton(parserData* data, const std::string &
2194
2194
auto style = getStyleForElement (" item_image_button" , spec_btn.fname , " image_button" );
2195
2195
e_btn->setStyles (style);
2196
2196
2197
- if (spec_btn.fname == data-> focused_fieldname ) {
2197
+ if (spec_btn.fname == m_focused_element ) {
2198
2198
Environment->setFocus (e_btn);
2199
2199
}
2200
2200
@@ -2665,6 +2665,27 @@ bool GUIFormSpecMenu::parseStyle(parserData *data, const std::string &element, b
2665
2665
return true ;
2666
2666
}
2667
2667
2668
+ void GUIFormSpecMenu::parseSetFocus (const std::string &element)
2669
+ {
2670
+ std::vector<std::string> parts = split (element, ' ;' );
2671
+
2672
+ if (parts.size () <= 2 ||
2673
+ (parts.size () > 2 && m_formspec_version > FORMSPEC_API_VERSION))
2674
+ {
2675
+ if (m_is_form_regenerated)
2676
+ return ; // Never focus on resizing
2677
+
2678
+ bool force_focus = parts.size () >= 2 && is_yes (parts[1 ]);
2679
+ if (force_focus || m_text_dst->m_formname != m_last_formname)
2680
+ setFocus (parts[0 ]);
2681
+
2682
+ return ;
2683
+ }
2684
+
2685
+ errorstream << " Invalid set_focus element (" << parts.size () << " ): '" << element
2686
+ << " '" << std::endl;
2687
+ }
2688
+
2668
2689
void GUIFormSpecMenu::parseElement (parserData* data, const std::string &element)
2669
2690
{
2670
2691
// some prechecks
@@ -2856,43 +2877,50 @@ void GUIFormSpecMenu::parseElement(parserData* data, const std::string &element)
2856
2877
return ;
2857
2878
}
2858
2879
2880
+ if (type == " set_focus" ) {
2881
+ parseSetFocus (description);
2882
+ return ;
2883
+ }
2884
+
2859
2885
// Ignore others
2860
2886
infostream << " Unknown DrawSpec: type=" << type << " , data=\" " << description << " \" "
2861
2887
<< std::endl;
2862
2888
}
2863
2889
2864
2890
void GUIFormSpecMenu::regenerateGui (v2u32 screensize)
2865
2891
{
2866
- /* useless to regenerate without a screensize */
2892
+ // Useless to regenerate without a screensize
2867
2893
if ((screensize.X <= 0 ) || (screensize.Y <= 0 )) {
2868
2894
return ;
2869
2895
}
2870
2896
2871
2897
parserData mydata;
2872
2898
2873
- // preserve tables
2874
- for (auto &m_table : m_tables) {
2875
- std::string tablename = m_table.first .fname ;
2876
- GUITable *table = m_table.second ;
2877
- mydata.table_dyndata [tablename] = table->getDynamicData ();
2878
- }
2879
-
2880
- // set focus
2881
- if (!m_focused_element.empty ())
2882
- mydata.focused_fieldname = m_focused_element;
2899
+ // Preserve stuff only on same form, not on a new form.
2900
+ if (m_text_dst->m_formname == m_last_formname) {
2901
+ // Preserve tables/textlists
2902
+ for (auto &m_table : m_tables) {
2903
+ std::string tablename = m_table.first .fname ;
2904
+ GUITable *table = m_table.second ;
2905
+ mydata.table_dyndata [tablename] = table->getDynamicData ();
2906
+ }
2883
2907
2884
- // preserve focus
2885
- gui::IGUIElement *focused_element = Environment->getFocus ();
2886
- if (focused_element && focused_element->getParent () == this ) {
2887
- s32 focused_id = focused_element->getID ();
2888
- if (focused_id > 257 ) {
2889
- for (const GUIFormSpecMenu::FieldSpec &field : m_fields) {
2890
- if (field.fid == focused_id) {
2891
- mydata.focused_fieldname = field.fname ;
2892
- break ;
2908
+ // Preserve focus
2909
+ gui::IGUIElement *focused_element = Environment->getFocus ();
2910
+ if (focused_element && focused_element->getParent () == this ) {
2911
+ s32 focused_id = focused_element->getID ();
2912
+ if (focused_id > 257 ) {
2913
+ for (const GUIFormSpecMenu::FieldSpec &field : m_fields) {
2914
+ if (field.fid == focused_id) {
2915
+ m_focused_element = field.fname ;
2916
+ break ;
2917
+ }
2893
2918
}
2894
2919
}
2895
2920
}
2921
+ } else {
2922
+ // Don't keep old focus value
2923
+ m_focused_element = " " ;
2896
2924
}
2897
2925
2898
2926
// Remove children
@@ -3253,8 +3281,8 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
3253
3281
}
3254
3282
}
3255
3283
3256
- // set initial focus if parser didn't set it
3257
- focused_element = Environment->getFocus ();
3284
+ // Set initial focus if parser didn't set it
3285
+ gui::IGUIElement * focused_element = Environment->getFocus ();
3258
3286
if (!focused_element
3259
3287
|| !isMyChild (focused_element)
3260
3288
|| focused_element->getType () == gui::EGUIET_TAB_CONTROL)
@@ -3265,6 +3293,13 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
3265
3293
// legacy sorting
3266
3294
if (m_formspec_version < 3 )
3267
3295
legacySortElements (legacy_sort_start);
3296
+
3297
+ // Formname and regeneration setting
3298
+ if (!m_is_form_regenerated) {
3299
+ // Only set previous form name if we purposefully showed a new formspec
3300
+ m_last_formname = m_text_dst->m_formname ;
3301
+ m_is_form_regenerated = true ;
3302
+ }
3268
3303
}
3269
3304
3270
3305
void GUIFormSpecMenu::legacySortElements (core::list<IGUIElement *>::Iterator from)
@@ -3382,6 +3417,7 @@ void GUIFormSpecMenu::drawMenu()
3382
3417
const std::string &newform = m_form_src->getForm ();
3383
3418
if (newform != m_formspec_string) {
3384
3419
m_formspec_string = newform;
3420
+ m_is_form_regenerated = false ;
3385
3421
regenerateGui (m_screensize_old);
3386
3422
}
3387
3423
}
0 commit comments