Переглянути джерело

Fix usage of data variables in selected `option`s (#510)

Maximilian Stark 2 роки тому
батько
коміт
a9bb4ac615

+ 15 - 0
Source/Core/DataModel.cpp

@@ -234,6 +234,21 @@ bool DataModel::EraseAliases(Element* element)
 	return aliases.erase(element) == 1;
 }
 
+void DataModel::CopyAliases(Element* from_element, Element* to_element)
+{
+	if (from_element == to_element)
+		return;
+	auto existing_map = aliases.find(from_element);
+
+	if (existing_map != aliases.end())
+	{
+		// Need to create a copy to prevent errors during concurrent modification for 3rd party containers
+		auto copy = existing_map->second;
+		for (auto const& it : copy)
+			aliases[to_element][it.first] = std::move(it.second);
+	}
+}
+
 DataAddress DataModel::ResolveAddress(const String& address_str, Element* element) const
 {
 	DataAddress address = ParseAddress(address_str);

+ 1 - 0
Source/Core/DataModel.h

@@ -58,6 +58,7 @@ public:
 
 	bool InsertAlias(Element* element, const String& alias_name, DataAddress replace_with_address);
 	bool EraseAliases(Element* element);
+	void CopyAliases(Element* source_element, Element* target_element);
 
 	DataAddress ResolveAddress(const String& address_str, Element* element) const;
 	const DataEventFunc* GetEventCallback(const String& name);

+ 9 - 0
Source/Core/Elements/WidgetDropDown.cpp

@@ -38,6 +38,7 @@
 #include "../../../Include/RmlUi/Core/Math.h"
 #include "../../../Include/RmlUi/Core/Profiling.h"
 #include "../../../Include/RmlUi/Core/Property.h"
+#include "../DataModel.h"
 
 namespace Rml {
 
@@ -129,9 +130,17 @@ void WidgetDropDown::OnUpdate()
 		const int selection = GetSelection();
 
 		if (Element* option = selection_element->GetChild(selection))
+		{
 			option->GetInnerRML(value_rml);
+			if (auto model = value_element->GetDataModel())
+				model->CopyAliases(option, value_element);
+		}
 		else
+		{
+			if (auto model = value_element->GetDataModel())
+				model->EraseAliases(value_element);
 			value_rml = parent_element->GetValue();
+		}
 
 		value_element->SetInnerRML(value_rml);
 

+ 8 - 0
Tests/Source/UnitTests/ElementFormControlSelect.cpp

@@ -296,6 +296,14 @@ TEST_CASE("form.select.databinding")
 			</select>
 			)",
 			"2", "C"},
+
+		{
+			R"(
+			<select data-value="selected_index">
+				 <option data-for="s : subjects" data-attr-value="it_index"><p data-rml="s | to_upper"></p></option>
+			</select>
+			)",
+			"2", "<p data-rml=\"s | to_upper\">C</p>"},
 	};
 
 	DataModelConstructor constructor = context->CreateDataModel("select-test");