summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/newview/lluilistener.cpp109
-rw-r--r--indra/newview/lluilistener.h1
2 files changed, 110 insertions, 0 deletions
diff --git a/indra/newview/lluilistener.cpp b/indra/newview/lluilistener.cpp
index 4d6eac4958..d02d126cb5 100644
--- a/indra/newview/lluilistener.cpp
+++ b/indra/newview/lluilistener.cpp
@@ -32,11 +32,14 @@
#include "lluilistener.h"
// STL headers
// std headers
+#include <sstream>
// external library headers
// other Linden headers
+#include "llviewerwindow.h" // to get root view
#include "lluictrl.h"
#include "llerror.h"
+
LLUIListener::LLUIListener():
LLEventAPI("UI",
"LLUICtrl::CommitCallbackRegistry listener.\n"
@@ -47,6 +50,12 @@ LLUIListener::LLUIListener():
"as if from a user gesture on a menu -- or a button click.",
&LLUIListener::call,
LLSD().with("function", LLSD()));
+
+ add("getValue",
+ "For the UI control identified by the path in [\"path\"], return the control's\n"
+ "current value as [\"value\"] reply.",
+ &LLUIListener::getValue,
+ LLSD().with("path", LLSD()));
}
void LLUIListener::call(const LLSD& event) const
@@ -71,3 +80,103 @@ void LLUIListener::call(const LLSD& event) const
(*func)(NULL, event["parameter"]);
}
}
+
+// 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 = 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 (; it != parts.end() && context; it++)
+ {
+ std::string part = *it;
+
+ if (part.length() == 0)
+ {
+ recurse = true;
+ }
+ else
+ {
+ const LLView* found = context->findChildView(part, recurse);
+ if (!found)
+ return NULL;
+
+ context = found;
+ recurse = false;
+ }
+ }
+
+ return context;
+}
+
+void LLUIListener::getValue(const LLSD&event) const
+{
+ 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));
+
+ if (ctrl)
+ {
+ reply["value"] = ctrl->getValue();
+ }
+ else
+ {
+ // *TODO: ??? return something indicating failure to resolve
+ }
+
+ sendReply(reply, event);
+}
diff --git a/indra/newview/lluilistener.h b/indra/newview/lluilistener.h
index e7847f01e8..08724024dc 100644
--- a/indra/newview/lluilistener.h
+++ b/indra/newview/lluilistener.h
@@ -41,6 +41,7 @@ public:
private:
void call(const LLSD& event) const;
+ void getValue(const LLSD&event) const;
};
#endif /* ! defined(LL_LLUILISTENER_H) */