Browse Source

Don't convert to/from rml when generating select dropdown options, add to benchmark.

Michael Ragazzon 6 years ago
parent
commit
55239271e0

+ 3 - 0
Samples/basic/benchmark/src/main.cpp

@@ -114,6 +114,9 @@ public:
 				<div class="col col1"><button class="expand" index="%d">+</button>&nbsp;<a>Route %d</a></div>
 				<div class="col col23"><input type="range" class="assign_range" min="0" max="%d" value="%d"/></div>
 				<div class="col col4">Assigned</div>
+				<select>
+					<option>Red</option><option>Blue</option><option selected>Green</option><option style="background-color: yellow;">Yellow</option>
+				</select>
 				<div class="inrow unmark_collapse">
 					<div class="col col123 assign_text">Assign to route</div>
 					<div class="col col4">

+ 9 - 9
Source/Controls/ElementFormControlSelect.cpp

@@ -129,19 +129,19 @@ void ElementFormControlSelect::OnUpdate()
 	ElementFormControl::OnUpdate();
 
 	// Move any child elements into the widget (except for the three functional elements).
-	while (HasChildNodes())
+	while (Core::Element * raw_child = GetFirstChild())
 	{
-		Core::Element* child = GetFirstChild();
+		Core::ElementPtr child = RemoveChild(raw_child);
 
-		// Check for a value attribute.
-		Rml::Core::String attribute_value = child->GetAttribute<Rml::Core::String>("value", "");
+		bool select = child->GetAttribute("selected");
+		bool selectable = !child->GetAttribute("disabled");
+		Core::String option_value = child->GetAttribute("value", Core::String());
 
-		// Pull the inner RML and add the option.
-		Rml::Core::String rml;
-		child->GetInnerRML(rml);
-		widget->AddOption(rml, attribute_value, -1, child->GetAttribute("selected"), !child->GetAttribute("unselectable"));
+		child->RemoveAttribute("selected");
+		child->RemoveAttribute("disabled");
+		child->RemoveAttribute("value");
 
-		RemoveChild(child);
+		widget->AddOption(std::move(child), option_value, -1, select, selectable);
 	}
 }
 

+ 23 - 10
Source/Controls/WidgetDropDown.cpp

@@ -50,7 +50,7 @@ WidgetDropDown::WidgetDropDown(ElementFormControl* element)
 
 	// Create the button and selection elements.
 	button_element = parent_element->AppendChild(Core::Factory::InstanceElement(parent_element, "*", "selectarrow", Rml::Core::XMLAttributes()), false);
-	value_element = parent_element->AppendChild(Core::Factory::InstanceElement(element, "*", "selectvalue", Rml::Core::XMLAttributes()), false);
+	value_element = parent_element->AppendChild(Core::Factory::InstanceElement(parent_element, "*", "selectvalue", Rml::Core::XMLAttributes()), false);
 	selection_element = parent_element->AppendChild(Core::Factory::InstanceElement(parent_element, "*", "selectbox", Rml::Core::XMLAttributes()), false);
 
 	value_element->SetProperty(Core::PropertyId::OverflowX, Core::Property(Core::Style::Overflow::Hidden));
@@ -208,29 +208,42 @@ int WidgetDropDown::GetSelection() const
 }
 
 // Adds a new option to the select control.
-int WidgetDropDown::AddOption(const Rml::Core::String& rml, const Rml::Core::String& value, int before, bool select, bool selectable)
+int WidgetDropDown::AddOption(const Rml::Core::String& rml, const Rml::Core::String& new_value, int before, bool select, bool selectable)
 {
-	// Instance a new element for the option.
 	Core::ElementPtr element = Core::Factory::InstanceElement(selection_element, "*", "option", Rml::Core::XMLAttributes());
+	element->SetInnerRML(rml);
+
+	bool result = AddOption(std::move(element), new_value, before, select, selectable);
+
+	return result;
+}
+
+int WidgetDropDown::AddOption(Rml::Core::ElementPtr element, const Rml::Core::String& new_value, int before, bool select, bool selectable)
+{
+	static const Core::String str_option = "option";
 
-	// Force to block display and inject the RML. Register a click handler so we can be notified of selection.
+	if (element->GetTagName() != str_option)
+	{
+		Core::Log::Message(Core::Log::LT_WARNING, "A child of '%s' must be of type 'option' but '%s' was given. See element '%s'.", parent_element->GetTagName().c_str(), element->GetTagName().c_str(), parent_element->GetAddress().c_str());
+		return -1;
+	}
+
+	// Force to block display. Register a click handler so we can be notified of selection.
 	element->SetProperty(Core::PropertyId::Display, Core::Property(Core::Style::Display::Block));
 	element->SetProperty(Core::PropertyId::Clip, Core::Property(Core::Style::Clip::Auto));
-	element->SetInnerRML(rml);
 	element->AddEventListener(Core::EventId::Click, this);
 
 	int option_index;
-	if (before < 0 ||
-		before >= (int) options.size())
+	if (before < 0 || before >= (int)options.size())
 	{
 		Core::Element* ptr = selection_element->AppendChild(std::move(element));
-		options.push_back(SelectOption(ptr, value, selectable));
-		option_index = (int) options.size() - 1;
+		options.push_back(SelectOption(ptr, new_value, selectable));
+		option_index = (int)options.size() - 1;
 	}
 	else
 	{
 		Core::Element* ptr = selection_element->InsertBefore(std::move(element), selection_element->GetChild(before));
-		options.insert(options.begin() + before, SelectOption(ptr, value, selectable));
+		options.insert(options.begin() + before, SelectOption(ptr, new_value, selectable));
 		option_index = before;
 	}
 

+ 8 - 0
Source/Controls/WidgetDropDown.h

@@ -78,6 +78,14 @@ public:
 	/// @param[in] selectable If true this option can be selected. If false, this option is not selectable.
 	/// @return The index of the new option.
 	int AddOption(const Rml::Core::String& rml, const Rml::Core::String& value, int before, bool select, bool selectable = true);
+	/// Moves an option element to the select control.
+	/// @param[in] element Element to move.
+	/// @param[in] value The value of the option.
+	/// @param[in] before The index of the element to insert the new option before.
+	/// @param[in] select True to select the new option.
+	/// @param[in] selectable If true this option can be selected. If false, this option is not selectable.
+	/// @return The index of the new option, or -1 if invalid.
+	int AddOption(Rml::Core::ElementPtr element, const Rml::Core::String& value, int before, bool select, bool selectable);
 	/// Removes an option from the select control.
 	/// @param[in] index The index of the option to remove.
 	void RemoveOption(int index);