summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
authorJoshua Bell <josh@lindenlab.com>2011-02-18 17:01:48 -0800
committerJoshua Bell <josh@lindenlab.com>2011-02-18 17:01:48 -0800
commit96cac7c82fcb189a61d514a244b62970e943e4ad (patch)
tree51081d9070bad1b8f0b57fb7bd8766c92830a912 /indra/newview
parentf6970e6ad1f0576ec194fdc8d369030f1e31aeab (diff)
Fix up path resolution.
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/lluilistener.cpp80
1 files changed, 63 insertions, 17 deletions
diff --git a/indra/newview/lluilistener.cpp b/indra/newview/lluilistener.cpp
index 22d3b8b219..d02d126cb5 100644
--- a/indra/newview/lluilistener.cpp
+++ b/indra/newview/lluilistener.cpp
@@ -32,6 +32,7 @@
#include "lluilistener.h"
// STL headers
// std headers
+#include <sstream>
// external library headers
// other Linden headers
#include "llviewerwindow.h" // to get root view
@@ -80,45 +81,90 @@ void LLUIListener::call(const LLSD& event) const
}
}
+// Split string given a single character delimiter.
+// Note that this returns empty strings for leading, trailing, and adjacent
+// delimiters, such as "/foo/bar//baz/" -> ["", "foo", "bar", "", "baz", "" ]
+std::vector<std::string> split(const std::string& s, char delim)
+{
+ std::stringstream ss(s);
+ std::string item;
+ std::vector<std::string> items;
+ while (std::getline(ss, item, delim))
+ {
+ items.push_back(item);
+ }
+ return items;
+}
+
+// Walk the LLView tree to resolve a path
+// Paths can be discovered using Develop > XUI > Show XUI Paths
+//
+// A leading "/" indicates the root of the tree is the starting
+// position of the search, (otherwise the context node is used)
+//
+// Adjacent "//" mean that the next level of the search is done
+// recursively ("descendant" rather than "child").
+//
+// Return values: If no match is found, NULL is returned,
+// otherwise the matching LLView* is returned.
+//
+// Examples:
+//
+// "/" -> return the root view
+// "/foo" -> find "foo" as a direct child of the root
+// "foo" -> find "foo" as a direct child of the context node
+// "//foo" -> find the first "foo" child anywhere in the tree
+// "/foo/bar" -> find "foo" as direct child of the root, and
+// "bar" as a direct child of "foo"
+// "//foo//bar/baz" -> find the first "foo" anywhere in the
+// tree, the first "bar" anywhere under it, and "baz"
+// as a direct child of that
+//
const LLView* resolve_path(const LLView* context, const std::string path)
{
- std::vector<std::string> parts;
- const std::string delims("/");
- LLStringUtilBase<char>::getTokens(path, parts, delims);
+ std::vector<std::string> parts = split(path, '/');
+
+ if (parts.size() == 0)
+ {
+ return context;
+ }
+
+ std::vector<std::string>::iterator it = parts.begin();
+
+ // leading / means "start at root"
+ if ((*it).length() == 0)
+ {
+ context = (LLView*)(gViewerWindow->getRootView());
+ it++;
+ }
bool recurse = false;
- for (std::vector<std::string>::iterator it = parts.begin();
- it != parts.end() && context; it++)
+ for (; it != parts.end() && context; it++)
{
std::string part = *it;
-
+
if (part.length() == 0)
{
- // Allow "foo//bar" meaning "descendant named bar"
recurse = true;
}
else
{
const LLView* found = context->findChildView(part, recurse);
if (!found)
- {
return NULL;
- }
- else
- {
- context = found;
- }
+
+ context = found;
recurse = false;
}
}
- return NULL;
+ return context;
}
void LLUIListener::getValue(const LLSD&event) const
{
- LLSD reply;
-
+ LLSD reply = LLSD::emptyMap();
+
const LLView* root = (LLView*)(gViewerWindow->getRootView());
const LLView* view = resolve_path(root, event["path"].asString());
const LLUICtrl* ctrl(dynamic_cast<const LLUICtrl*>(view));
@@ -132,5 +178,5 @@ void LLUIListener::getValue(const LLSD&event) const
// *TODO: ??? return something indicating failure to resolve
}
- sendReply(reply, event, "reply");
+ sendReply(reply, event);
}