summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNat Goodspeed <nat@lindenlab.com>2011-02-22 20:13:07 -0500
committerNat Goodspeed <nat@lindenlab.com>2011-02-22 20:13:07 -0500
commit1362a3e117dadbc5b1de18487314d4af57ce850f (patch)
tree84dd5e85d7d727e6e1f4fb9760c70050853c8ea4
parentdbaef6ef1fa6461373cd7117f20f5b8fd4e8db6c (diff)
Move Josh's resolvePath() function to LLUI.
Use boost::split_iterator to split LLView pathname on slashes.
-rw-r--r--indra/llui/llui.cpp49
-rw-r--r--indra/llui/llui.h27
-rw-r--r--indra/newview/lluilistener.cpp89
3 files changed, 80 insertions, 85 deletions
diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp
index c300fe55d9..87669574c2 100644
--- a/indra/llui/llui.cpp
+++ b/indra/llui/llui.cpp
@@ -61,6 +61,8 @@
// for XUIParse
#include "llquaternion.h"
#include <boost/tokenizer.hpp>
+#include <boost/algorithm/string/find_iterator.hpp>
+#include <boost/algorithm/string/finder.hpp>
//
// Globals
@@ -2020,6 +2022,53 @@ void LLUI::positionViewNearMouse(LLView* view, S32 spawn_x, S32 spawn_y)
view->translateIntoRectWithExclusion( virtual_window_rect, mouse_rect, FALSE );
}
+LLView* LLUI::resolvePath(LLView* context, const std::string& path)
+{
+ // Nothing about resolvePath() should require non-const LLView*. If caller
+ // wants non-const, call the const flavor and then cast away const-ness.
+ return const_cast<LLView*>(resolvePath(const_cast<const LLView*>(context), path));
+}
+
+const LLView* LLUI::resolvePath(const LLView* context, const std::string& path)
+{
+ // Create an iterator over slash-separated parts of 'path'. Dereferencing
+ // this iterator returns an iterator_range over the substring. Unlike
+ // LLStringUtil::getTokens(), this split_iterator doesn't combine adjacent
+ // delimiters: leading/trailing slash produces an empty substring, double
+ // slash produces an empty substring. That's what we need.
+ boost::split_iterator<std::string::const_iterator> ti(path, boost::first_finder("/")), tend;
+
+ if (ti == tend)
+ {
+ // 'path' is completely empty, no navigation
+ return context;
+ }
+
+ // leading / means "start at root"
+ if (ti->empty())
+ {
+ context = getRootView();
+ ++ti;
+ }
+
+ bool recurse = false;
+ for (; ti != tend && context; ++ti)
+ {
+ if (ti->empty())
+ {
+ recurse = true;
+ }
+ else
+ {
+ std::string part(ti->begin(), ti->end());
+ context = context->findChildView(part, recurse);
+ recurse = false;
+ }
+ }
+
+ return context;
+}
+
// LLLocalClipRect and LLScreenClipRect moved to lllocalcliprect.h/cpp
diff --git a/indra/llui/llui.h b/indra/llui/llui.h
index 62d10df8b2..50cb9e6632 100644
--- a/indra/llui/llui.h
+++ b/indra/llui/llui.h
@@ -185,6 +185,33 @@ public:
//helper functions (should probably move free standing rendering helper functions here)
static LLView* getRootView() { return sRootView; }
static void setRootView(LLView* view) { sRootView = view; }
+ /**
+ * 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
+ */
+ static const LLView* resolvePath(const LLView* context, const std::string& path);
+ static LLView* resolvePath(LLView* context, const std::string& path);
static std::string locateSkin(const std::string& filename);
static void setMousePositionScreen(S32 x, S32 y);
static void getMousePositionScreen(S32 *x, S32 *y);
diff --git a/indra/newview/lluilistener.cpp b/indra/newview/lluilistener.cpp
index d02d126cb5..6b2cd71d40 100644
--- a/indra/newview/lluilistener.cpp
+++ b/indra/newview/lluilistener.cpp
@@ -32,10 +32,9 @@
#include "lluilistener.h"
// STL headers
// std headers
-#include <sstream>
// external library headers
// other Linden headers
-#include "llviewerwindow.h" // to get root view
+#include "llui.h" // getRootView(), resolvePath()
#include "lluictrl.h"
#include "llerror.h"
@@ -55,7 +54,7 @@ LLUIListener::LLUIListener():
"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()));
+ LLSDMap("path", LLSD())("reply", LLSD()));
}
void LLUIListener::call(const LLSD& event) const
@@ -81,92 +80,12 @@ 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 = 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 LLView* root = LLUI::getRootView();
+ const LLView* view = LLUI::resolvePath(root, event["path"].asString());
const LLUICtrl* ctrl(dynamic_cast<const LLUICtrl*>(view));
if (ctrl)