Browse Source

Formspec: Make dropdowns optionally return event based on index, not value (#9496)

v-rob 3 years ago
parent
commit
b1ff04e06d
4 changed files with 39 additions and 20 deletions
  1. 12 3
      doc/lua_api.txt
  2. 23 16
      src/gui/guiFormSpecMenu.cpp
  3. 1 0
      src/gui/guiFormSpecMenu.h
  4. 3 1
      src/network/networkprotocol.h

+ 12 - 3
doc/lua_api.txt

@@ -2443,7 +2443,7 @@ Elements
 * `color` is color specified as a `ColorString`.
   If the alpha component is left blank, the box will be semitransparent.
 
-### `dropdown[<X>,<Y>;<W>;<name>;<item 1>,<item 2>, ...,<item n>;<selected idx>]`
+### `dropdown[<X>,<Y>;<W>;<name>;<item 1>,<item 2>, ...,<item n>;<selected idx>;<index event>]`
 
 * Show a dropdown field
 * **Important note**: There are two different operation modes:
@@ -2454,8 +2454,12 @@ Elements
 * Fieldname data is transferred to Lua
 * Items to be shown in dropdown
 * Index of currently selected dropdown item
+* `index event` (optional, allowed parameter since formspec version 4): Specifies the
+  event field value for selected items.
+    * `true`: Selected item index
+    * `false` (default): Selected item value
 
-### `dropdown[<X>,<Y>;<W>,<H>;<name>;<item 1>,<item 2>, ...,<item n>;<selected idx>]`
+### `dropdown[<X>,<Y>;<W>,<H>;<name>;<item 1>,<item 2>, ...,<item n>;<selected idx>;<index event>]`
 
 * Show a dropdown field
 * **Important note**: This syntax for dropdowns can only be used with the
@@ -2468,6 +2472,10 @@ Elements
 * Fieldname data is transferred to Lua
 * Items to be shown in dropdown
 * Index of currently selected dropdown item
+* `index event` (optional, allowed parameter since formspec version 4): Specifies the
+  event field value for selected items.
+    * `true`: Selected item index
+    * `false` (default): Selected item value
 
 ### `checkbox[<X>,<Y>;<name>;<label>;<selected>]`
 
@@ -4491,7 +4499,8 @@ Call these functions only at load time!
         * `button` and variants: If pressed, contains the user-facing button
           text as value. If not pressed, is `nil`
         * `field`, `textarea` and variants: Text in the field
-        * `dropdown`: Text of selected item
+        * `dropdown`: Either the index or value, depending on the `index event`
+          dropdown argument.
         * `tabheader`: Tab index, starting with `"1"` (only if tab changed)
         * `checkbox`: `"true"` if checked, `"false"` if unchecked
         * `textlist`: See `minetest.explode_textlist_event`

+ 23 - 16
src/gui/guiFormSpecMenu.cpp

@@ -1318,19 +1318,20 @@ void GUIFormSpecMenu::parseTextList(parserData* data, const std::string &element
 	errorstream<< "Invalid textlist element(" << parts.size() << "): '" << element << "'"  << std::endl;
 }
 
-
 void GUIFormSpecMenu::parseDropDown(parserData* data, const std::string &element)
 {
-	std::vector<std::string> parts = split(element,';');
+	std::vector<std::string> parts = split(element, ';');
 
-	if ((parts.size() == 5) ||
-		((parts.size() > 5) && (m_formspec_version > FORMSPEC_API_VERSION)))
+	if (parts.size() == 5 || parts.size() == 6 ||
+		(parts.size() > 6 && m_formspec_version > FORMSPEC_API_VERSION))
 	{
-		std::vector<std::string> v_pos = split(parts[0],',');
+		std::vector<std::string> v_pos = split(parts[0], ',');
 		std::string name = parts[2];
-		std::vector<std::string> items = split(parts[3],',');
-		std::string str_initial_selection;
-		str_initial_selection = parts[4];
+		std::vector<std::string> items = split(parts[3], ',');
+		std::string str_initial_selection = parts[4];
+
+		if (parts.size() >= 6 && is_yes(parts[5]))
+			m_dropdown_index_event[name] = true;
 
 		MY_CHECKPOS("dropdown",0);
 
@@ -1397,8 +1398,8 @@ void GUIFormSpecMenu::parseDropDown(parserData* data, const std::string &element
 
 		return;
 	}
-	errorstream << "Invalid dropdown element(" << parts.size() << "): '"
-				<< element << "'"  << std::endl;
+	errorstream << "Invalid dropdown element(" << parts.size() << "): '" << element
+		<< "'" << std::endl;
 }
 
 void GUIFormSpecMenu::parseFieldCloseOnEnter(parserData *data, const std::string &element)
@@ -1414,8 +1415,8 @@ void GUIFormSpecMenu::parsePwdField(parserData* data, const std::string &element
 {
 	std::vector<std::string> parts = split(element,';');
 
-	if ((parts.size() == 4) ||
-		((parts.size() > 4) && (m_formspec_version > FORMSPEC_API_VERSION)))
+	if (parts.size() == 4 ||
+		(parts.size() > 4 && m_formspec_version > FORMSPEC_API_VERSION))
 	{
 		std::vector<std::string> v_pos = split(parts[0],',');
 		std::vector<std::string> v_geom = split(parts[1],',');
@@ -2940,6 +2941,8 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
 	theme_by_name.clear();
 	theme_by_type.clear();
 	m_clickthrough_elements.clear();
+	field_close_on_enter.clear();
+	m_dropdown_index_event.clear();
 
 	m_bgnonfullscreen = true;
 	m_bgfullscreen = false;
@@ -3727,10 +3730,14 @@ void GUIFormSpecMenu::acceptInput(FormspecQuitMode quitmode=quit_mode_no)
 					}
 					s32 selected = e->getSelected();
 					if (selected >= 0) {
-						std::vector<std::string> *dropdown_values =
-							getDropDownValues(s.fname);
-						if (dropdown_values && selected < (s32)dropdown_values->size()) {
-							fields[name] = (*dropdown_values)[selected];
+						if (m_dropdown_index_event.find(s.fname) !=
+								m_dropdown_index_event.end()) {
+							fields[name] = std::to_string(selected + 1);
+						} else {
+							std::vector<std::string> *dropdown_values =
+								getDropDownValues(s.fname);
+							if (dropdown_values && selected < (s32)dropdown_values->size())
+								fields[name] = (*dropdown_values)[selected];
 						}
 					}
 				} else if (s.ftype == f_TabHeader) {

+ 1 - 0
src/gui/guiFormSpecMenu.h

@@ -303,6 +303,7 @@ protected:
 	std::vector<ListRingSpec> m_inventory_rings;
 	std::vector<gui::IGUIElement *> m_backgrounds;
 	std::unordered_map<std::string, bool> field_close_on_enter;
+	std::unordered_map<std::string, bool> m_dropdown_index_event;
 	std::vector<FieldSpec> m_fields;
 	std::vector<std::pair<FieldSpec, GUITable *>> m_tables;
 	std::vector<std::pair<FieldSpec, gui::IGUICheckBox *>> m_checkboxes;

+ 3 - 1
src/network/networkprotocol.h

@@ -238,8 +238,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 		bgcolor[]: use 3 parameters (bgcolor, formspec (now an enum), fbgcolor)
 		box[] and image[] elements enable clipping by default
 		new element: scroll_container[]
+	FORMSPEC VERSION 4:
+		Allow dropdown indexing events
 */
-#define FORMSPEC_API_VERSION 3
+#define FORMSPEC_API_VERSION 4
 
 #define TEXTURENAME_ALLOWED_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_.-"