From 3ddf3aef9b2f2bb85932bd33b9daac5e59d3018a Mon Sep 17 00:00:00 2001
From: Nat Goodspeed <nat@lindenlab.com>
Date: Thu, 1 Sep 2011 13:12:23 -0400
Subject: CHOP-763: Promote Response class from llwindowlistener.cpp to
 LLEventAPI. This is a generally-useful idiom, extending the sendReply()
 convenience function -- it shouldn't remain buried in a single .cpp file.

---
 indra/llcommon/lleventapi.cpp      | 30 +++++++++++++++
 indra/llcommon/lleventapi.h        | 78 ++++++++++++++++++++++++++++++++++++++
 indra/newview/llwindowlistener.cpp | 43 +--------------------
 3 files changed, 110 insertions(+), 41 deletions(-)

diff --git a/indra/llcommon/lleventapi.cpp b/indra/llcommon/lleventapi.cpp
index 4270c8b511..ff5459c1eb 100644
--- a/indra/llcommon/lleventapi.cpp
+++ b/indra/llcommon/lleventapi.cpp
@@ -34,6 +34,7 @@
 // std headers
 // external library headers
 // other Linden headers
+#include "llerror.h"
 
 LLEventAPI::LLEventAPI(const std::string& name, const std::string& desc, const std::string& field):
     lbase(name, field),
@@ -45,3 +46,32 @@ LLEventAPI::LLEventAPI(const std::string& name, const std::string& desc, const s
 LLEventAPI::~LLEventAPI()
 {
 }
+
+LLEventAPI::Response::Response(const LLSD& seed, const LLSD& request, const LLSD::String& replyKey):
+    mResp(seed),
+    mReq(request),
+    mKey(replyKey)
+{}
+
+LLEventAPI::Response::~Response()
+{
+    // When you instantiate a stack Response object, if the original
+    // request requested a reply, send it when we leave this block, no
+    // matter how.
+    sendReply(mResp, mReq, mKey);
+}
+
+void LLEventAPI::Response::warn(const std::string& warning)
+{
+    LL_WARNS("LLEventAPI::Response") << warning << LL_ENDL;
+    mResp["warnings"].append(warning);
+}
+
+void LLEventAPI::Response::error(const std::string& error)
+{
+    // Use LL_WARNS rather than LL_ERROR: we don't want the viewer to shut
+    // down altogether.
+    LL_WARNS("LLEventAPI::Response") << error << LL_ENDL;
+
+    mResp["error"] = error;
+}
diff --git a/indra/llcommon/lleventapi.h b/indra/llcommon/lleventapi.h
index d75d521e8e..332dee9550 100644
--- a/indra/llcommon/lleventapi.h
+++ b/indra/llcommon/lleventapi.h
@@ -76,6 +76,84 @@ public:
         LLEventDispatcher::add(name, desc, callable, required);
     }
 
+    /**
+     * Instantiate a Response object in any LLEventAPI subclass method that
+     * wants to guarantee a reply (if requested) will be sent on exit from the
+     * method. The reply will be sent if request.has(@a replyKey), default
+     * "reply". If specified, the value of request[replyKey] is the name of
+     * the LLEventPump on which to send the reply. Conventionally you might
+     * code something like:
+     *
+     * @code
+     * void MyEventAPI::someMethod(const LLSD& request)
+     * {
+     *     // Send a reply event as long as request.has("reply")
+     *     Response response(LLSD(), request);
+     *     // ...
+     *     // will be sent in reply event
+     *     response["somekey"] = some_data;
+     * }
+     * @endcode
+     */
+    class Response
+    {
+    public:
+        /**
+         * Instantiating a Response object in an LLEventAPI subclass method
+         * ensures that, if desired, a reply event will be sent.
+         *
+         * @a seed is the initial reply LLSD that will be further decorated before
+         * being sent as the reply
+         *
+         * @a request is the incoming request LLSD; we particularly care about
+         * [replyKey] and ["reqid"]
+         *
+         * @a replyKey [default "reply"] is the string name of the LLEventPump
+         * on which the caller wants a reply. If <tt>(!
+         * request.has(replyKey))</tt>, no reply will be sent.
+         */
+        Response(const LLSD& seed, const LLSD& request, const LLSD::String& replyKey="reply");
+        ~Response();
+
+        /**
+         * @code
+         * if (some condition)
+         * {
+         *     response.warn("warnings are logged and collected in [\"warnings\"]");
+         * }
+         * @endcode
+         */
+        void warn(const std::string& warning);
+        /**
+         * @code
+         * if (some condition isn't met)
+         * {
+         *     // In a function returning void, you can validly 'return
+         *     // expression' if the expression is itself of type void. But
+         *     // returning is up to you; response.error() has no effect on
+         *     // flow of control.
+         *     return response.error("error message, logged and also sent as [\"error\"]");
+         * }
+         * @endcode
+         */
+        void error(const std::string& error);
+
+        /**
+         * set other keys...
+         *
+         * @code
+         * // set any attributes you want to be sent in the reply
+         * response["info"] = some_value;
+         * // ...
+         * response["ok"] = went_well;
+         * @endcode
+         */
+        LLSD& operator[](const LLSD::String& key) { return mResp[key]; }
+
+        LLSD mResp, mReq;
+        LLSD::String mKey;
+    };
+
 private:
     std::string mDesc;
 };
diff --git a/indra/newview/llwindowlistener.cpp b/indra/newview/llwindowlistener.cpp
index 05cb798732..3e3287032c 100644
--- a/indra/newview/llwindowlistener.cpp
+++ b/indra/newview/llwindowlistener.cpp
@@ -134,46 +134,7 @@ protected:
 
 namespace {
 
-class Response
-{
-public:
-	Response(const LLSD& seed, const LLSD& request, const LLSD::String& replyKey="reply"):
-		mResp(seed),
-		mReq(request),
-		mKey(replyKey)
-	{}
-
-	~Response()
-	{
-		// When you instantiate a stack Response object, if the original
-		// request requested a reply, send it when we leave this block, no
-		// matter how.
-		sendReply(mResp, mReq, mKey);
-	}
-
-	void warn(const std::string& warning)
-	{
-		LL_WARNS("LLWindowListener") << warning << LL_ENDL;
-		mResp["warnings"].append(warning);
-	}
-
-	void error(const std::string& error)
-	{
-		// Use LL_WARNS rather than LL_ERROR: we don't want the viewer to shut
-		// down altogether.
-		LL_WARNS("LLWindowListener") << error << LL_ENDL;
-
-		mResp["error"] = error;
-	}
-
-	// set other keys...
-	LLSD& operator[](const LLSD::String& key) { return mResp[key]; }
-
-	LLSD mResp, mReq;
-	LLSD::String mKey;
-};
-
-void insertViewInformation(Response & response, LLView * target)
+void insertViewInformation(LLEventAPI::Response & response, LLView * target)
 {
 	// Get info about this LLView* for when we send response.
 	response["path"] = target->getPathname();
@@ -346,7 +307,7 @@ typedef boost::function<bool(LLCoordGL, MASK)> MouseFunc;
 static void mouseEvent(const MouseFunc& func, const LLSD& request)
 {
 	// Ensure we send response
-	Response response(LLSD(), request);
+	LLEventAPI::Response response(LLSD(), request);
 	// We haven't yet established whether the incoming request has "x" and "y",
 	// but capture this anyway, with 0 for omitted values.
 	LLCoordGL pos(request["x"].asInteger(), request["y"].asInteger());
-- 
cgit v1.2.3