diff --git a/Source/Core/DataModel.cpp b/Source/Core/DataModel.cpp index 273801fa1..1a6f33b92 100644 --- a/Source/Core/DataModel.cpp +++ b/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); diff --git a/Source/Core/DataModel.h b/Source/Core/DataModel.h index c1a3ced4b..332f1f509 100644 --- a/Source/Core/DataModel.h +++ b/Source/Core/DataModel.h @@ -58,6 +58,7 @@ class DataModel : NonCopyMoveable { 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); diff --git a/Source/Core/Elements/WidgetDropDown.cpp b/Source/Core/Elements/WidgetDropDown.cpp index bf2f36d7b..e13673c1d 100644 --- a/Source/Core/Elements/WidgetDropDown.cpp +++ b/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); diff --git a/Tests/Source/UnitTests/ElementFormControlSelect.cpp b/Tests/Source/UnitTests/ElementFormControlSelect.cpp index 883ff9bc8..27c211893 100644 --- a/Tests/Source/UnitTests/ElementFormControlSelect.cpp +++ b/Tests/Source/UnitTests/ElementFormControlSelect.cpp @@ -296,6 +296,14 @@ TEST_CASE("form.select.databinding") )", "2", "C"}, + + { + R"( + + )", + "2", "
C
"}, }; DataModelConstructor constructor = context->CreateDataModel("select-test");