Maelstrom: Use a breadth first recursive search to find elements by name.

https://github.com/libsdl-org/Maelstrom/commit/87557a6b9ad3974a203319f99a574164605c7002

From 87557a6b9ad3974a203319f99a574164605c7002 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Sun, 6 Nov 2011 01:52:01 -0500
Subject: [PATCH] Use a breadth first recursive search to find elements by
 name. This gives more flexibility in XMl layout and definitions.

---
 screenlib/UIBaseElement.cpp | 13 +------------
 screenlib/UIBaseElement.h   | 34 ++++++++++++++++++++++++++++++----
 2 files changed, 31 insertions(+), 16 deletions(-)

diff --git a/screenlib/UIBaseElement.cpp b/screenlib/UIBaseElement.cpp
index d3f51159..8a967286 100644
--- a/screenlib/UIBaseElement.cpp
+++ b/screenlib/UIBaseElement.cpp
@@ -117,7 +117,7 @@ UIBaseElement::GetAnchorElement(const char *name)
 {
 	if (name) {
 		if (m_parent) {
-			UIArea *element = m_parent->GetElement(name);
+			UIArea *element = m_parent->GetElement<UIBaseElement>(name);
 			if (!element) {
 				element = m_parent->GetAnchorElement(name);
 			}
@@ -197,17 +197,6 @@ UIBaseElement::HandleEvent(const SDL_Event &event)
 	return false;
 }
 
-UIBaseElement *
-UIBaseElement::GetElement(const char *name)
-{
-	for (int i = 0; i < m_elements.length(); ++i) {
-		if (strcmp(name, m_elements[i]->GetName()) == 0) {
-			return m_elements[i];
-		}
-	}
-	return NULL;
-}
-
 UIBaseElement *
 UIBaseElement::CreateElement(const char *name)
 {
diff --git a/screenlib/UIBaseElement.h b/screenlib/UIBaseElement.h
index 329d28b9..9f7ccf5c 100644
--- a/screenlib/UIBaseElement.h
+++ b/screenlib/UIBaseElement.h
@@ -74,11 +74,38 @@ class UIBaseElement : public UIArea
 	void AddElement(UIBaseElement *element) {
 		m_elements.add(element);
 	}
+	void GetElements(array<UIBaseElement*> &elements) {
+		for (int i = 0; i < m_elements.length(); ++i) {
+			elements.add(m_elements[i]);
+		}
+	}
 	template <typename T>
 	T *GetElement(const char *name) {
-		UIBaseElement *element = GetElement(name);
-		if (element && element->IsA(T::GetType())) {
-			return (T*)element;
+		// Do a breadth first search
+		array<UIBaseElement*> lists[2];
+		int i, current = 0;
+
+		GetElements(lists[current]);
+		while (lists[current].length() > 0) {
+			array<UIBaseElement*> &list = lists[current];
+			
+			for (i = 0; i < list.length(); ++i) {
+				UIBaseElement *element = list[i];
+				if (strcmp(name, element->GetName()) == 0) {
+					if (element->IsA(T::GetType())) {
+						return (T*)element;
+					}
+				}
+			}
+
+			// Didn't find it, grab the children
+			array<UIBaseElement*> &children = lists[!current];
+			for (i = 0; i < list.length(); ++i) {
+				list[i]->GetElements(children);
+			}
+			list.clear();
+
+			current = !current;
 		}
 		return NULL;
 	}
@@ -156,7 +183,6 @@ class UIBaseElement : public UIArea
 	array<UIBaseElement *> m_elements;
 
 protected:
-	UIBaseElement *GetElement(const char *name);
 	UIBaseElement *CreateElement(const char *type);
 
 	bool LoadElements(rapidxml::xml_node<> *node, const UITemplates *templates);