summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llcommon/lldate.cpp17
-rw-r--r--indra/llcommon/lldate.h29
-rw-r--r--indra/llcommon/llmemory.h59
-rw-r--r--indra/llcommon/llsd.cpp40
-rw-r--r--indra/llcommon/llsd.h4
-rw-r--r--indra/llcommon/lltimer.cpp8
-rw-r--r--indra/llcommon/lltimer.h2
-rw-r--r--indra/llcommon/lluuid.cpp15
-rw-r--r--indra/llcommon/lluuid.h5
-rw-r--r--indra/llinventory/lleconomy.h2
-rw-r--r--indra/llmath/llmath.h24
-rw-r--r--indra/llmath/llrect.h5
-rw-r--r--indra/llrender/llgl.cpp5
-rw-r--r--indra/llui/CMakeLists.txt4
-rw-r--r--indra/llui/llcombobox.cpp32
-rw-r--r--indra/llui/llcombobox.h1
-rw-r--r--indra/llui/llfloater.cpp5
-rw-r--r--indra/llui/llfloater.h24
-rw-r--r--indra/llui/llfunctorregistry.cpp37
-rw-r--r--indra/llui/llfunctorregistry.h145
-rw-r--r--indra/llui/llnotifications.cpp1471
-rw-r--r--indra/llui/llnotifications.h892
-rw-r--r--indra/llui/llpanel.cpp129
-rw-r--r--indra/llui/llpanel.h26
-rw-r--r--indra/llui/llscrollbar.cpp76
-rw-r--r--indra/llui/llscrollbar.h2
-rw-r--r--indra/llui/llscrolllistctrl.cpp342
-rw-r--r--indra/llui/llscrolllistctrl.h115
-rw-r--r--indra/llui/llui.cpp16
-rw-r--r--indra/llui/llui.h237
-rw-r--r--indra/llui/lluictrl.cpp11
-rw-r--r--indra/llui/lluictrl.h2
-rw-r--r--indra/llui/lluictrlfactory.h1
-rw-r--r--indra/llui/lluistring.cpp13
-rw-r--r--indra/llui/lluistring.h6
-rw-r--r--indra/llui/llview.cpp5
-rw-r--r--indra/llui/llview.h7
-rw-r--r--indra/llxml/llxmlnode.cpp185
-rw-r--r--indra/llxml/llxmlnode.h26
-rw-r--r--indra/newview/CMakeLists.txt6
-rw-r--r--indra/newview/app_settings/settings.xml11
-rw-r--r--indra/newview/llagent.cpp104
-rw-r--r--indra/newview/llagent.h6
-rw-r--r--indra/newview/llappviewer.cpp167
-rw-r--r--indra/newview/llappviewer.h3
-rw-r--r--indra/newview/llassetuploadresponders.cpp28
-rw-r--r--indra/newview/llcallingcard.cpp20
-rw-r--r--indra/newview/llcompilequeue.cpp12
-rw-r--r--indra/newview/llconfirmationmanager.cpp28
-rw-r--r--indra/newview/lldelayedgestureerror.cpp8
-rw-r--r--indra/newview/lleventnotifier.cpp53
-rw-r--r--indra/newview/lleventnotifier.h2
-rw-r--r--indra/newview/llfirstuse.cpp46
-rw-r--r--indra/newview/llfloateranimpreview.cpp2
-rw-r--r--indra/newview/llfloaterauction.cpp18
-rw-r--r--indra/newview/llfloaterbuy.cpp4
-rw-r--r--indra/newview/llfloaterbuycontents.cpp4
-rw-r--r--indra/newview/llfloaterbuyland.cpp4
-rw-r--r--indra/newview/llfloaterdaycycle.cpp12
-rw-r--r--indra/newview/llfloaterenvsettings.cpp14
-rw-r--r--indra/newview/llfloaterfriends.cpp156
-rw-r--r--indra/newview/llfloaterfriends.h8
-rw-r--r--indra/newview/llfloatergodtools.cpp90
-rw-r--r--indra/newview/llfloatergodtools.h8
-rw-r--r--indra/newview/llfloatergroups.cpp20
-rw-r--r--indra/newview/llfloatergroups.h2
-rw-r--r--indra/newview/llfloaterhardwaresettings.cpp2
-rw-r--r--indra/newview/llfloaterhud.cpp2
-rw-r--r--indra/newview/llfloaterland.cpp150
-rw-r--r--indra/newview/llfloaterland.h11
-rw-r--r--indra/newview/llfloaternotificationsconsole.cpp292
-rw-r--r--indra/newview/llfloaternotificationsconsole.h78
-rw-r--r--indra/newview/llfloateropenobject.cpp6
-rw-r--r--indra/newview/llfloaterperms.cpp2
-rw-r--r--indra/newview/llfloaterpostcard.cpp48
-rw-r--r--indra/newview/llfloaterpostcard.h2
-rw-r--r--indra/newview/llfloaterpostprocess.cpp16
-rw-r--r--indra/newview/llfloaterpostprocess.h2
-rw-r--r--indra/newview/llfloaterregioninfo.cpp478
-rw-r--r--indra/newview/llfloaterregioninfo.h28
-rw-r--r--indra/newview/llfloaterreporter.cpp35
-rw-r--r--indra/newview/llfloatersellland.cpp104
-rw-r--r--indra/newview/llfloatersnapshot.cpp2
-rw-r--r--indra/newview/llfloatertopobjects.cpp12
-rw-r--r--indra/newview/llfloatertopobjects.h4
-rw-r--r--indra/newview/llfloatertos.cpp2
-rw-r--r--indra/newview/llfloaterurlentry.cpp34
-rw-r--r--indra/newview/llfloaterurlentry.h2
-rw-r--r--indra/newview/llfloaterwater.cpp46
-rw-r--r--indra/newview/llfloaterwater.h6
-rw-r--r--indra/newview/llfloaterwindlight.cpp52
-rw-r--r--indra/newview/llfloaterwindlight.h6
-rw-r--r--indra/newview/llfloaterworldmap.cpp6
-rw-r--r--indra/newview/llgesturemgr.cpp6
-rw-r--r--indra/newview/llgroupmgr.cpp6
-rw-r--r--indra/newview/llimpanel.cpp99
-rw-r--r--indra/newview/llimpanel.h6
-rw-r--r--indra/newview/llimview.cpp471
-rw-r--r--indra/newview/llimview.h7
-rw-r--r--indra/newview/llinventorybridge.cpp105
-rw-r--r--indra/newview/llinventorymodel.h1
-rw-r--r--indra/newview/lllandmarklist.cpp4
-rw-r--r--indra/newview/llmutelist.cpp23
-rw-r--r--indra/newview/llnamelistctrl.cpp5
-rw-r--r--indra/newview/llpanelavatar.cpp117
-rw-r--r--indra/newview/llpanelavatar.h14
-rw-r--r--indra/newview/llpanelclassified.cpp88
-rw-r--r--indra/newview/llpanelclassified.h8
-rw-r--r--indra/newview/llpanelgroup.cpp50
-rw-r--r--indra/newview/llpanelgroup.h3
-rw-r--r--indra/newview/llpanelgroupgeneral.cpp82
-rw-r--r--indra/newview/llpanelgroupgeneral.h7
-rw-r--r--indra/newview/llpanelgroupinvite.cpp29
-rw-r--r--indra/newview/llpanelgroupnotices.cpp12
-rw-r--r--indra/newview/llpanelgrouproles.cpp95
-rw-r--r--indra/newview/llpanelgrouproles.h9
-rw-r--r--indra/newview/llpanelland.cpp2
-rw-r--r--indra/newview/llpanellogin.cpp10
-rw-r--r--indra/newview/llpanellogin.h2
-rw-r--r--indra/newview/llpanelpermissions.cpp11
-rw-r--r--indra/newview/llpanelpick.cpp2
-rw-r--r--indra/newview/llpanelplace.cpp14
-rw-r--r--indra/newview/llpanelplace.h2
-rw-r--r--indra/newview/llpreviewgesture.cpp35
-rw-r--r--indra/newview/llpreviewgesture.h2
-rw-r--r--indra/newview/llpreviewnotecard.cpp32
-rw-r--r--indra/newview/llpreviewnotecard.h2
-rw-r--r--indra/newview/llpreviewscript.cpp87
-rw-r--r--indra/newview/llpreviewscript.h6
-rw-r--r--indra/newview/llpreviewtexture.cpp14
-rw-r--r--indra/newview/llselectmgr.cpp45
-rw-r--r--indra/newview/llselectmgr.h2
-rw-r--r--indra/newview/llstartup.cpp183
-rw-r--r--indra/newview/llstartup.h2
-rw-r--r--indra/newview/llstatusbar.cpp16
-rw-r--r--indra/newview/lltoolbar.cpp7
-rw-r--r--indra/newview/lltoolbrush.cpp6
-rw-r--r--indra/newview/lltooldraganddrop.cpp78
-rw-r--r--indra/newview/lltooldraganddrop.h4
-rw-r--r--indra/newview/llurldispatcher.cpp5
-rw-r--r--indra/newview/llviewerinventory.cpp4
-rw-r--r--indra/newview/llviewermenu.cpp334
-rw-r--r--indra/newview/llviewermenufile.cpp73
-rw-r--r--indra/newview/llviewermessage.cpp1058
-rw-r--r--indra/newview/llviewermessage.h10
-rw-r--r--indra/newview/llviewerparcelmedia.cpp14
-rw-r--r--indra/newview/llviewerparcelmgr.cpp179
-rw-r--r--indra/newview/llviewerparcelmgr.h12
-rw-r--r--indra/newview/llviewertexteditor.cpp48
-rw-r--r--indra/newview/llviewertexteditor.h4
-rw-r--r--indra/newview/llviewerwindow.cpp121
-rw-r--r--indra/newview/llviewerwindow.h15
-rw-r--r--indra/newview/llvograss.cpp12
-rw-r--r--indra/newview/llvoiceclient.cpp2
-rw-r--r--indra/newview/llvotree.cpp6
-rw-r--r--indra/newview/llwearable.cpp12
-rw-r--r--indra/newview/llwearablelist.cpp30
-rw-r--r--indra/newview/llwldaycycle.cpp6
-rw-r--r--indra/newview/llxmlrpctransaction.cpp20
159 files changed, 6812 insertions, 3253 deletions
diff --git a/indra/llcommon/lldate.cpp b/indra/llcommon/lldate.cpp
index 6b4bd0d7ef..ff1b6c5334 100644
--- a/indra/llcommon/lldate.cpp
+++ b/indra/llcommon/lldate.cpp
@@ -36,9 +36,12 @@
#include "apr_time.h"
+#include <time.h>
#include <iomanip>
#include <sstream>
+#include "lltimer.h"
+
static const F64 DATE_EPOCH = 0.0;
static const F64 LL_APR_USEC_PER_SEC = 1000000.0;
@@ -122,7 +125,7 @@ void LLDate::toHTTPDateStream(std::ostream& s) const
<< " GMT";
// RFC 1123 date does not use microseconds
- llinfos << "Date in RFC 1123 format is " << s << llendl;
+ //llinfos << "Date in RFC 1123 format is " << s << llendl;
}
void LLDate::toStream(std::ostream& s) const
@@ -239,6 +242,17 @@ bool operator!=(const LLDate& first, const LLDate& second)
return (first.secondsSinceEpoch() != second.secondsSinceEpoch());
}
+/* static */ LLDate LLDate::now()
+{
+ // time() returns seconds, we want fractions of a second, which LLTimer provides --RN
+ return LLDate(LLTimer::getTotalSeconds());
+}
+
+bool LLDate::operator<(const LLDate& rhs) const
+{
+ return mSecondsSinceEpoch < rhs.mSecondsSinceEpoch;
+}
+
std::ostream& operator<<(std::ostream& s, const LLDate& date)
{
date.toStream(s);
@@ -250,3 +264,4 @@ std::istream& operator>>(std::istream& s, LLDate& date)
date.fromStream(s);
return s;
}
+
diff --git a/indra/llcommon/lldate.h b/indra/llcommon/lldate.h
index 2b53c8cc9a..b660f9fcdd 100644
--- a/indra/llcommon/lldate.h
+++ b/indra/llcommon/lldate.h
@@ -35,6 +35,7 @@
#define LL_LLDATE_H
#include <iosfwd>
+#include <string>
#include "stdtypes.h"
@@ -53,7 +54,7 @@ public:
LLDate();
/**
- * @brief Construct a date equal to epoch.
+ * @brief Construct a date equal the source date.
*/
LLDate(const LLDate& date);
@@ -111,6 +112,32 @@ public:
* @param seconds The number of seconds since epoch UTC.
*/
void secondsSinceEpoch(F64 seconds);
+
+ /**
+ * @brief Create an LLDate object set to the current time.
+ *
+ * @return The number of seconds since epoch UTC.
+ */
+ static LLDate now();
+
+ /**
+ * @brief Compare dates using operator< so we can order them using STL.
+ *
+ * @param rhs -- the right hand side of the comparison operator
+ */
+ bool operator<(const LLDate& rhs) const;
+
+ /**
+ * @brief Remaining comparison operators in terms of operator<
+ * This conforms to the expectation of STL.
+ *
+ * @param rhs -- the right hand side of the comparison operator
+ */
+ bool operator>(const LLDate& rhs) const { return rhs < *this; }
+ bool operator<=(const LLDate& rhs) const { return !(rhs < *this); }
+ bool operator>=(const LLDate& rhs) const { return !(*this < rhs); }
+ bool operator!=(const LLDate& rhs) const { return (*this < rhs) || (rhs < *this); }
+ bool operator==(const LLDate& rhs) const { return !(*this != rhs); }
private:
F64 mSecondsSinceEpoch;
diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h
index cc57e658fb..3f3dd33ee3 100644
--- a/indra/llcommon/llmemory.h
+++ b/indra/llcommon/llmemory.h
@@ -409,53 +409,58 @@ protected:
//
// class Foo: public LLSingleton<Foo>{};
//
-// Foo* instance = Foo::getInstance();
+// Foo& instance = Foo::instance();
//
-// The second way is to define a seperate class that exposes the singleton
-// interface:
+// The second way is to use the singleton class directly, without inheritance:
//
-// class FooSingleton: public LLSingleton<Foo>{};
+// typedef LLSingleton<Foo> FooSingleton;
//
-// Foo* instance = FooSingleton::getInstance();
+// Foo& instance = FooSingleton::instance();
+//
+// In this case, the class being managed as a singleton needs to provide an
+// initSingleton() method since the LLSingleton virtual method won't be
+// available
//
// As currently written, it is not thread-safe.
-#if LL_WINDOWS && _MSC_VER < 1400 // this is Visual C++ 2003 or earlier
-// workaround for VC7 compiler bug
-// adapted from http://www.codeproject.com/KB/tips/VC2003MeyersSingletonBug.aspx
-// our version doesn't introduce a nested struct so that you can still declare LLSingleton<MyClass>
-// a friend and hide your constructor
-
template <typename T>
class LLSingleton
{
public:
- static T* getInstance()
+ virtual ~LLSingleton() {}
+#ifdef LL_MSVC7
+// workaround for VC7 compiler bug
+// adapted from http://www.codeproject.com/KB/tips/VC2003MeyersSingletonBug.aspx
+// our version doesn't introduce a nested struct so that you can still declare LLSingleton<MyClass>
+// a friend and hide your constructor
+ static T* getInstance()
{
LLSingleton<T> singleton;
- return singleton.get();
- }
-private:
- T* get()
- {
- static T instance;
- return &instance;
+ return singleton.vsHack();
}
-};
+ T* vsHack()
#else
-
-template <typename T>
-class LLSingleton
-{
-public:
static T* getInstance()
+#endif
{
static T instance;
+ static bool needs_init = true;
+ if (needs_init)
+ {
+ needs_init = false;
+ instance.initSingleton();
+ }
return &instance;
}
-};
-#endif
+ static T& instance()
+ {
+ return *getInstance();
+ }
+
+private:
+ virtual void initSingleton() {}
+};
//----------------------------------------------------------------------------
diff --git a/indra/llcommon/llsd.cpp b/indra/llcommon/llsd.cpp
index 099f233f56..4bf4e442fd 100644
--- a/indra/llcommon/llsd.cpp
+++ b/indra/llcommon/llsd.cpp
@@ -349,7 +349,7 @@ namespace
virtual bool has(const LLSD::String&) const;
virtual LLSD get(const LLSD::String&) const;
- void insert(const LLSD::String& k, const LLSD& v);
+ LLSD& insert(const LLSD::String& k, const LLSD& v);
virtual void erase(const LLSD::String&);
LLSD& ref(const LLSD::String&);
virtual const LLSD& ref(const LLSD::String&) const;
@@ -388,9 +388,14 @@ namespace
return (i != mData.end()) ? i->second : LLSD();
}
- void ImplMap::insert(const LLSD::String& k, const LLSD& v)
+ LLSD& ImplMap::insert(const LLSD::String& k, const LLSD& v)
{
mData.insert(DataMap::value_type(k, v));
+ #ifdef LL_MSVC7
+ return *((LLSD*)this);
+ #else
+ return *dynamic_cast<LLSD*>(this);
+ #endif
}
void ImplMap::erase(const LLSD::String& k)
@@ -436,7 +441,7 @@ namespace
virtual int size() const;
virtual LLSD get(LLSD::Integer) const;
void set(LLSD::Integer, const LLSD&);
- void insert(LLSD::Integer, const LLSD&);
+ LLSD& insert(LLSD::Integer, const LLSD&);
void append(const LLSD&);
virtual void erase(LLSD::Integer);
LLSD& ref(LLSD::Integer);
@@ -485,9 +490,15 @@ namespace
mData[index] = v;
}
- void ImplArray::insert(LLSD::Integer i, const LLSD& v)
+ LLSD& ImplArray::insert(LLSD::Integer i, const LLSD& v)
{
- if (i < 0) { return; }
+ if (i < 0) {
+ #ifdef LL_MSVC7
+ return *((LLSD*)this);
+ #else
+ return *dynamic_cast<LLSD*>(this);
+ #endif
+ }
DataVector::size_type index = i;
if (index >= mData.size())
@@ -496,6 +507,11 @@ namespace
}
mData.insert(mData.begin() + index, v);
+ #ifdef LL_MSVC7
+ return *((LLSD*)this);
+ #else
+ return *dynamic_cast<LLSD*>(this);
+ #endif
}
void ImplArray::append(const LLSD& v)
@@ -739,8 +755,11 @@ LLSD LLSD::emptyMap()
bool LLSD::has(const String& k) const { return safe(impl).has(k); }
LLSD LLSD::get(const String& k) const { return safe(impl).get(k); }
-void LLSD::insert(const String& k, const LLSD& v)
- { makeMap(impl).insert(k, v); }
+LLSD& LLSD::insert(const String& k, const LLSD& v)
+ {
+ makeMap(impl).insert(k, v);
+ return *dynamic_cast<LLSD*>(this);
+ }
void LLSD::erase(const String& k) { makeMap(impl).erase(k); }
LLSD& LLSD::operator[](const String& k)
@@ -761,8 +780,11 @@ int LLSD::size() const { return safe(impl).size(); }
LLSD LLSD::get(Integer i) const { return safe(impl).get(i); }
void LLSD::set(Integer i, const LLSD& v){ makeArray(impl).set(i, v); }
-void LLSD::insert(Integer i, const LLSD& v)
- { makeArray(impl).insert(i, v); }
+LLSD& LLSD::insert(Integer i, const LLSD& v)
+ {
+ makeArray(impl).insert(i, v);
+ return *this;
+ }
void LLSD::append(const LLSD& v) { makeArray(impl).append(v); }
void LLSD::erase(Integer i) { makeArray(impl).erase(i); }
diff --git a/indra/llcommon/llsd.h b/indra/llcommon/llsd.h
index 0382fb1360..87874009dd 100644
--- a/indra/llcommon/llsd.h
+++ b/indra/llcommon/llsd.h
@@ -222,7 +222,7 @@ public:
bool has(const String&) const;
LLSD get(const String&) const;
- void insert(const String&, const LLSD&);
+ LLSD& insert(const String&, const LLSD&);
void erase(const String&);
LLSD& operator[](const String&);
@@ -237,7 +237,7 @@ public:
LLSD get(Integer) const;
void set(Integer, const LLSD&);
- void insert(Integer, const LLSD&);
+ LLSD& insert(Integer, const LLSD&);
void append(const LLSD&);
void erase(Integer);
diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp
index 2c34608064..2525e24989 100644
--- a/indra/llcommon/lltimer.cpp
+++ b/indra/llcommon/lltimer.cpp
@@ -569,6 +569,14 @@ LLEventTimer::LLEventTimer(F32 period)
sActiveList.push_back(this);
}
+LLEventTimer::LLEventTimer(const LLDate& time)
+: mEventTimer()
+{
+ mPeriod = (F32)(time.secondsSinceEpoch() - LLDate::now().secondsSinceEpoch());
+ sActiveList.push_back(this);
+}
+
+
LLEventTimer::~LLEventTimer()
{
sActiveList.remove(this);
diff --git a/indra/llcommon/lltimer.h b/indra/llcommon/lltimer.h
index 1916d67fda..6d6f1f44cd 100644
--- a/indra/llcommon/lltimer.h
+++ b/indra/llcommon/lltimer.h
@@ -38,6 +38,7 @@
#include <limits.h>
#include "stdtypes.h"
+#include "lldate.h"
#include <string>
#include <list>
@@ -173,6 +174,7 @@ class LLEventTimer
{
public:
LLEventTimer(F32 period); // period is the amount of time between each call to tick() in seconds
+ LLEventTimer(const LLDate& time);
virtual ~LLEventTimer();
//function to be called at the supplied frequency
diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp
index 1098d1bd3c..019c5045d4 100644
--- a/indra/llcommon/lluuid.cpp
+++ b/indra/llcommon/lluuid.cpp
@@ -908,6 +908,21 @@ BOOL LLUUID::parseUUID(const std::string& buf, LLUUID* value)
return FALSE;
}
+//static
+LLUUID LLUUID::generateNewID(std::string hash_string)
+{
+ LLUUID new_id;
+ if (hash_string.empty())
+ {
+ new_id.generate();
+ }
+ else
+ {
+ new_id.generate(hash_string);
+ }
+ return new_id;
+}
+
LLAssetID LLTransactionID::makeAssetID(const LLUUID& session) const
{
LLAssetID result;
diff --git a/indra/llcommon/lluuid.h b/indra/llcommon/lluuid.h
index b2fcce5161..e5c204b589 100644
--- a/indra/llcommon/lluuid.h
+++ b/indra/llcommon/lluuid.h
@@ -65,6 +65,9 @@ public:
//
void generate(); // Generate a new UUID
void generate(const std::string& stream); //Generate a new UUID based on hash of input stream
+
+ static LLUUID generateNewID(std::string stream = ""); //static version of above for use in initializer expressions such as constructor params, etc.
+
BOOL set(const char *in_string, BOOL emit = TRUE); // Convert from string, if emit is FALSE, do not emit warnings
BOOL set(const std::string& in_string, BOOL emit = TRUE); // Convert from string, if emit is FALSE, do not emit warnings
void setNull(); // Faster than setting to LLUUID::null.
@@ -124,7 +127,7 @@ public:
static S32 getNodeID(unsigned char * node_id);
static BOOL parseUUID(const std::string& buf, LLUUID* value);
-
+
U8 mData[UUID_BYTES];
};
diff --git a/indra/llinventory/lleconomy.h b/indra/llinventory/lleconomy.h
index 4ac7cb4605..707f4451d1 100644
--- a/indra/llinventory/lleconomy.h
+++ b/indra/llinventory/lleconomy.h
@@ -47,6 +47,8 @@ public:
// become a singleton and this pattern will more easily disambiguate them.
typedef LLSingleton<LLGlobalEconomy> Singleton;
+ void initSingleton() { }
+
virtual void print();
static void processEconomyData(LLMessageSystem *msg, LLGlobalEconomy* econ_data);
diff --git a/indra/llmath/llmath.h b/indra/llmath/llmath.h
index 0372bae106..916f4aa6c7 100644
--- a/indra/llmath/llmath.h
+++ b/indra/llmath/llmath.h
@@ -103,6 +103,30 @@ const F32 FP_MAG_THRESHOLD = 0.0000001f;
// TODO: Replace with logic like is_approx_equal
inline BOOL is_approx_zero( F32 f ) { return (-F_APPROXIMATELY_ZERO < f) && (f < F_APPROXIMATELY_ZERO); }
+// These functions work by interpreting sign+exp+mantissa as an unsigned
+// integer.
+// For example:
+// x = <sign>1 <exponent>00000010 <mantissa>00000000000000000000000
+// y = <sign>1 <exponent>00000001 <mantissa>11111111111111111111111
+//
+// interpreted as ints =
+// x = 10000001000000000000000000000000
+// y = 10000000111111111111111111111111
+// which is clearly a different of 1 in the least significant bit
+// Values with the same exponent can be trivially shown to work.
+//
+// WARNING: Denormals of opposite sign do not work
+// x = <sign>1 <exponent>00000000 <mantissa>00000000000000000000001
+// y = <sign>0 <exponent>00000000 <mantissa>00000000000000000000001
+// Although these values differ by 2 in the LSB, the sign bit makes
+// the int comparison fail.
+//
+// WARNING: NaNs can compare equal
+// There is no special treatment of exceptional values like NaNs
+//
+// WARNING: Infinity is comparable with F32_MAX and negative
+// infinity is comparable with F32_MIN
+
inline BOOL is_approx_equal(F32 x, F32 y)
{
const S32 COMPARE_MANTISSA_UP_TO_BIT = 0x02;
diff --git a/indra/llmath/llrect.h b/indra/llmath/llrect.h
index 21ca4189ff..93b69714de 100644
--- a/indra/llmath/llrect.h
+++ b/indra/llmath/llrect.h
@@ -223,6 +223,11 @@ public:
return *this;
}
+ bool isValid() const
+ {
+ return mLeft <= mRight && mBottom <= mTop;
+ }
+
bool isNull() const
{
return mLeft == mRight || mBottom == mTop;
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index aced88f1a2..89c5115cfd 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -980,13 +980,10 @@ void LLGLState::initClass()
{
sStateMap[GL_DITHER] = GL_TRUE;
// sStateMap[GL_TEXTURE_2D] = GL_TRUE;
-
+
//make sure multisample defaults to disabled
sStateMap[GL_MULTISAMPLE_ARB] = GL_FALSE;
glDisable(GL_MULTISAMPLE_ARB);
-
- //default vertex arrays to enabled.
- glEnableClientState(GL_VERTEX_ARRAY);
}
//static
diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt
index 897cc4275d..1b4d4e7d54 100644
--- a/indra/llui/CMakeLists.txt
+++ b/indra/llui/CMakeLists.txt
@@ -36,6 +36,7 @@ set(llui_SOURCE_FILES
lleditmenuhandler.cpp
llfloater.cpp
llfocusmgr.cpp
+ llfunctorregistry.cpp
lliconctrl.cpp
llkeywords.cpp
lllineeditor.cpp
@@ -43,6 +44,7 @@ set(llui_SOURCE_FILES
llmodaldialog.cpp
llmultislider.cpp
llmultisliderctrl.cpp
+ llnotifications.cpp
llpanel.cpp
llprogressbar.cpp
llradiogroup.cpp
@@ -86,6 +88,7 @@ set(llui_HEADER_FILES
lleditmenuhandler.h
llfloater.h
llfocusmgr.h
+ llfunctorregistry.h
llhtmlhelp.h
lliconctrl.h
llkeywords.h
@@ -95,6 +98,7 @@ set(llui_HEADER_FILES
llmodaldialog.h
llmultisliderctrl.h
llmultislider.h
+ llnotifications.h
llpanel.h
llprogressbar.h
llradiogroup.h
diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp
index df5bcbe752..6edd5a7fe5 100644
--- a/indra/llui/llcombobox.cpp
+++ b/indra/llui/llcombobox.cpp
@@ -72,11 +72,12 @@ LLComboBox::LLComboBox( const std::string& name, const LLRect &rect, const std::
mTextEntryTentative(TRUE),
mListPosition(BELOW),
mPrearrangeCallback( NULL ),
- mTextEntryCallback( NULL )
+ mTextEntryCallback( NULL ),
+ mLabel(label)
{
// Always use text box
// Text label button
- mButton = new LLButton(label,
+ mButton = new LLButton(mLabel,
LLRect(),
LLStringUtil::null,
NULL, this);
@@ -197,7 +198,12 @@ LLView* LLComboBox::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *
}
}
- combo_box->selectFirstItem();
+ // if providing user text entry or descriptive label
+ // don't select an item under the hood
+ if (!combo_box->acceptsTextInput() && combo_box->mLabel.empty())
+ {
+ combo_box->selectFirstItem();
+ }
return combo_box;
}
@@ -259,7 +265,10 @@ LLScrollListItem* LLComboBox::add(const std::string& name, EAddPosition pos, BOO
{
LLScrollListItem* item = mList->addSimpleElement(name, pos);
item->setEnabled(enabled);
- mList->selectFirstItem();
+ if (!mAllowTextEntry && mLabel.empty())
+ {
+ selectFirstItem();
+ }
return item;
}
@@ -268,7 +277,10 @@ LLScrollListItem* LLComboBox::add(const std::string& name, const LLUUID& id, EAd
{
LLScrollListItem* item = mList->addSimpleElement(name, pos, id);
item->setEnabled(enabled);
- mList->selectFirstItem();
+ if (!mAllowTextEntry && mLabel.empty())
+ {
+ selectFirstItem();
+ }
return item;
}
@@ -278,7 +290,10 @@ LLScrollListItem* LLComboBox::add(const std::string& name, void* userdata, EAddP
LLScrollListItem* item = mList->addSimpleElement(name, pos);
item->setEnabled(enabled);
item->setUserdata( userdata );
- mList->selectFirstItem();
+ if (!mAllowTextEntry && mLabel.empty())
+ {
+ selectFirstItem();
+ }
return item;
}
@@ -287,7 +302,10 @@ LLScrollListItem* LLComboBox::add(const std::string& name, LLSD value, EAddPosit
{
LLScrollListItem* item = mList->addSimpleElement(name, pos, value);
item->setEnabled(enabled);
- mList->selectFirstItem();
+ if (!mAllowTextEntry && mLabel.empty())
+ {
+ selectFirstItem();
+ }
return item;
}
diff --git a/indra/llui/llcombobox.h b/indra/llui/llcombobox.h
index 7427a33129..0317ebdae9 100644
--- a/indra/llui/llcombobox.h
+++ b/indra/llui/llcombobox.h
@@ -188,6 +188,7 @@ protected:
LLScrollListCtrl* mList;
EPreferredPosition mListPosition;
LLPointer<LLUIImage> mArrowImage;
+ std::string mLabel;
private:
S32 mButtonPadding;
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 22260b52cf..dd93684a69 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -147,6 +147,7 @@ LLFloater::LLFloater() :
}
mDragHandle = NULL;
mHandle.bind(this);
+ mNotificationContext = new LLFloaterNotificationContext(getHandle());
}
LLFloater::LLFloater(const std::string& name)
@@ -220,6 +221,7 @@ void LLFloater::initFloater(const std::string& title,
BOOL drag_on_left, BOOL minimizable, BOOL close_btn)
{
mHandle.bind(this);
+ mNotificationContext = new LLFloaterNotificationContext(getHandle());
// Init function can be called more than once, so clear out old data.
for (S32 i = 0; i < BUTTON_COUNT; i++)
@@ -429,6 +431,9 @@ void LLFloater::initFloater(const std::string& title,
// virtual
LLFloater::~LLFloater()
{
+ delete mNotificationContext;
+ mNotificationContext = NULL;
+
control_map_t::iterator itor;
for (itor = mFloaterControls.begin(); itor != mFloaterControls.end(); ++itor)
{
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index b66eba8810..ebf2676960 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -39,6 +39,7 @@
#include "llpanel.h"
#include "lluuid.h"
#include "lltabcontainer.h"
+#include "llnotifications.h"
#include <set>
class LLDragHandle;
@@ -46,6 +47,7 @@ class LLResizeHandle;
class LLResizeBar;
class LLButton;
class LLMultiFloater;
+class LLFloater;
const S32 LLFLOATER_VPAD = 6;
const S32 LLFLOATER_HPAD = 6;
@@ -70,6 +72,20 @@ const BOOL CLOSE_NO = FALSE;
const BOOL ADJUST_VERTICAL_YES = TRUE;
const BOOL ADJUST_VERTICAL_NO = FALSE;
+// associates a given notification instance with a particular floater
+class LLFloaterNotificationContext :
+ public LLNotificationContext
+{
+public:
+ LLFloaterNotificationContext(LLHandle<LLFloater> floater_handle) :
+ mFloaterHandle(floater_handle)
+ {}
+
+ LLFloater* getFloater() { return mFloaterHandle.get(); }
+private:
+ LLHandle<LLFloater> mFloaterHandle;
+};
+
class LLFloater : public LLPanel
{
@@ -213,6 +229,11 @@ public:
// handle refocusing.
static void closeFocusedFloater();
+ LLNotification::Params contextualNotification(const std::string& name)
+ {
+ return LLNotification::Params(name).context(mNotificationContext);
+ }
+
static void onClickClose(void *userdata);
static void onClickMinimize(void *userdata);
static void onClickTearOff(void *userdata);
@@ -299,7 +320,7 @@ private:
S32 mPreviousMinimizedBottom;
S32 mPreviousMinimizedLeft;
-private:
+ LLFloaterNotificationContext* mNotificationContext;
LLRootHandle<LLFloater> mHandle;
};
@@ -467,7 +488,6 @@ template <class T> class LLFloaterSingleton : public LLUISingleton<T, Visibility
{
};
-
extern LLFloaterView* gFloaterView;
#endif // LL_FLOATER_H
diff --git a/indra/llui/llfunctorregistry.cpp b/indra/llui/llfunctorregistry.cpp
new file mode 100644
index 0000000000..a6ecc6aa18
--- /dev/null
+++ b/indra/llui/llfunctorregistry.cpp
@@ -0,0 +1,37 @@
+/**
+ * @file llfunctorregistry.cpp
+ * @author Kent Quirk
+ * @brief Maintains a registry of named callback functors taking a single LLSD parameter
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2008, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ **/
+
+#include "llfunctorregistry.h"
+
+// This is a default functor always resident in the system.
+// It's used whenever a functor isn't found in the registry, so that
+// we at least log the data relating to the user response.
diff --git a/indra/llui/llfunctorregistry.h b/indra/llui/llfunctorregistry.h
new file mode 100644
index 0000000000..02bf74a28a
--- /dev/null
+++ b/indra/llui/llfunctorregistry.h
@@ -0,0 +1,145 @@
+/**
+ * @file llfunctorregistry.h
+ * @author Kent Quirk
+ * @brief Maintains a registry of named callback functors taking a single LLSD parameter
+ *
+ * $LicenseInfo:firstyear=2008&license=viewergpl$
+ *
+ * Copyright (c) 2003-2007, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLFUNCTORREGISTRY_H
+#define LL_LLFUNCTORREGISTRY_H
+
+#include <string>
+#include <map>
+
+#include <boost/function.hpp>
+
+#include "llsd.h"
+#include "llmemory.h"
+
+/**
+ * @class LLFunctorRegistry
+ * @brief Maintains a collection of named functors for remote binding
+ * (mainly for use in callbacks from notifications and other signals)
+ * @see LLNotifications
+ *
+ * This class maintains a collection of named functors in a singleton.
+ * We wanted to be able to persist notifications with their callbacks
+ * across restarts of the viewer; we couldn't store functors that way.
+ * Using this registry, systems that require a functor to be maintained
+ * long term can register it at system startup, and then pass in the
+ * functor by name.
+ */
+
+template <typename FUNCTOR_TYPE>
+class LLFunctorRegistry : public LLSingleton<LLFunctorRegistry<FUNCTOR_TYPE> >
+{
+ friend class LLSingleton<LLFunctorRegistry>;
+ LOG_CLASS(LLFunctorRegistry);
+private:
+ LLFunctorRegistry() : LOGFUNCTOR("LogFunctor"), DONOTHING("DoNothing")
+ {
+ mMap[LOGFUNCTOR] = log_functor;
+ mMap[DONOTHING] = do_nothing;
+ }
+
+public:
+ typedef FUNCTOR_TYPE ResponseFunctor;
+ typedef typename std::map<std::string, FUNCTOR_TYPE> FunctorMap;
+
+ bool registerFunctor(const std::string& name, ResponseFunctor f)
+ {
+ bool retval = true;
+ typename FunctorMap::iterator it = mMap.find(name);
+ if (mMap.count(name) == 0)
+ {
+ mMap[name] = f;
+ }
+ else
+ {
+ llerrs << "attempt to store duplicate name '" << name << "' in LLFunctorRegistry. NOT ADDED." << llendl;
+ retval = false;
+ }
+
+ return retval;
+ }
+
+ bool unregisterFunctor(const std::string& name)
+ {
+ if (mMap.count(name) == 0)
+ {
+ llwarns << "trying to remove '" << name << "' from LLFunctorRegistry but it's not there." << llendl;
+ return false;
+ }
+ mMap.erase(name);
+ return true;
+ }
+
+ FUNCTOR_TYPE getFunctor(const std::string& name)
+ {
+ typename FunctorMap::iterator it = mMap.find(name);
+ if (mMap.count(name) != 0)
+ {
+ return mMap[name];
+ }
+ else
+ {
+ llwarns << "tried to find '" << name << "' in LLFunctorRegistry, but it wasn't there." << llendl;
+ return mMap[LOGFUNCTOR];
+ }
+ }
+
+ const std::string LOGFUNCTOR;
+ const std::string DONOTHING;
+
+private:
+
+ static void log_functor(const LLSD& notification, const LLSD& payload)
+ {
+ llwarns << "log_functor called with payload: " << payload << llendl;
+ }
+
+ static void do_nothing(const LLSD& notification, const LLSD& payload)
+ {
+ // what the sign sez
+ }
+
+ FunctorMap mMap;
+};
+
+template <typename FUNCTOR_TYPE>
+class LLFunctorRegistration
+{
+public:
+ LLFunctorRegistration(const std::string& name, FUNCTOR_TYPE functor)
+ {
+ LLFunctorRegistry<FUNCTOR_TYPE>::instance().registerFunctor(name, functor);
+ }
+};
+
+#endif//LL_LLFUNCTORREGISTRY_H
+
diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
new file mode 100644
index 0000000000..c2da50b98b
--- /dev/null
+++ b/indra/llui/llnotifications.cpp
@@ -0,0 +1,1471 @@
+/**
+* @file llnotifications.cpp
+* @brief Non-UI queue manager for keeping a prioritized list of notifications
+*
+* $LicenseInfo:firstyear=2008&license=viewergpl$
+*
+* Copyright (c) 2008, Linden Research, Inc.
+*
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab. Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+*
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
+*
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+
+#include "linden_common.h"
+#include "lluictrlfactory.h"
+#include "lldir.h"
+#include "llsdserialize.h"
+
+#include "llnotifications.h"
+
+#include <algorithm>
+#include <boost/regex.hpp>
+
+
+const std::string NOTIFICATION_PERSIST_VERSION = "0.93";
+
+// local channel for notification history
+class LLNotificationHistoryChannel : public LLNotificationChannel
+{
+ LOG_CLASS(LLNotificationHistoryChannel);
+public:
+ LLNotificationHistoryChannel(const std::string& filename) :
+ LLNotificationChannel("History", "Visible", &historyFilter),
+ mFileName(filename)
+ {
+ connectChanged(boost::bind(&LLNotificationHistoryChannel::historyHandler, this, _1));
+ loadPersistentNotifications();
+ }
+
+private:
+ bool historyHandler(const LLSD& payload)
+ {
+ // we ignore "load" messages, but rewrite the persistence file on any other
+ std::string sigtype = payload["sigtype"];
+ if (sigtype != "load")
+ {
+ savePersistentNotifications();
+ }
+ return false;
+ }
+
+ // The history channel gets all notifications except those that have been cancelled
+ static bool historyFilter(LLNotificationPtr pNotification)
+ {
+ return !pNotification->isCancelled();
+ }
+
+ void savePersistentNotifications()
+ {
+ llinfos << "Saving open notifications to " << mFileName << llendl;
+
+ llofstream notify_file(mFileName.c_str());
+ if (!notify_file.is_open())
+ {
+ llwarns << "Failed to open " << mFileName << llendl;
+ return;
+ }
+
+ LLSD output;
+ output["version"] = NOTIFICATION_PERSIST_VERSION;
+ LLSD& data = output["data"];
+
+ for (LLNotificationSet::iterator it = mItems.begin(); it != mItems.end(); ++it)
+ {
+ if (!LLNotifications::instance().templateExists((*it)->getName())) continue;
+
+ // only store notifications flagged as persisting
+ LLNotificationTemplatePtr templatep = LLNotifications::instance().getTemplate((*it)->getName());
+ if (!templatep->mPersist) continue;
+
+ data.append((*it)->asLLSD());
+ }
+
+ LLPointer<LLSDFormatter> formatter = new LLSDXMLFormatter();
+ formatter->format(output, notify_file, LLSDFormatter::OPTIONS_PRETTY);
+ }
+
+ void loadPersistentNotifications()
+ {
+ llinfos << "Loading open notifications from " << mFileName << llendl;
+
+ llifstream notify_file(mFileName.c_str());
+ if (!notify_file.is_open())
+ {
+ llwarns << "Failed to open " << mFileName << llendl;
+ return;
+ }
+
+ LLSD input;
+ LLPointer<LLSDParser> parser = new LLSDXMLParser();
+ if (parser->parse(notify_file, input, LLSDSerialize::SIZE_UNLIMITED) < 0)
+ {
+ llwarns << "Failed to parse open notifications" << llendl;
+ return;
+ }
+
+ if (input.isUndefined()) return;
+ std::string version = input["version"];
+ if (version != NOTIFICATION_PERSIST_VERSION)
+ {
+ llwarns << "Bad open notifications version: " << version << llendl;
+ return;
+ }
+ LLSD& data = input["data"];
+ if (data.isUndefined()) return;
+
+ LLNotifications& instance = LLNotifications::instance();
+ for (LLSD::array_const_iterator notification_it = data.beginArray();
+ notification_it != data.endArray();
+ ++notification_it)
+ {
+ instance.add(LLNotificationPtr(new LLNotification(*notification_it)));
+ }
+ }
+
+ //virtual
+ void onDelete(LLNotificationPtr pNotification)
+ {
+ // we want to keep deleted notifications in our log
+ mItems.insert(pNotification);
+
+ return;
+ }
+
+private:
+ std::string mFileName;
+};
+
+bool filterIgnoredNotifications(LLNotificationPtr notification)
+{
+ LLNotificationFormPtr form = notification->getForm();
+ // Check to see if the user wants to ignore this alert
+ if (form->getIgnoreType() != LLNotificationForm::IGNORE_NO)
+ {
+ return LLUI::sConfigGroup->getWarning(notification->getName());
+ }
+
+ return true;
+}
+
+bool handleIgnoredNotification(const LLSD& payload)
+{
+ if (payload["sigtype"].asString() == "add")
+ {
+ LLNotificationPtr pNotif = LLNotifications::instance().find(payload["id"].asUUID());
+ if (!pNotif) return false;
+
+ LLNotificationFormPtr form = pNotif->getForm();
+ LLSD response;
+ switch(form->getIgnoreType())
+ {
+ case LLNotificationForm::IGNORE_WITH_DEFAULT_RESPONSE:
+ response = pNotif->getResponseTemplate(LLNotification::WITH_DEFAULT_BUTTON);
+ break;
+ case LLNotificationForm::IGNORE_WITH_LAST_RESPONSE:
+ response = LLUI::sIgnoresGroup->getLLSD("Default" + pNotif->getName());
+ break;
+ case LLNotificationForm::IGNORE_SHOW_AGAIN:
+ break;
+ default:
+ return false;
+ }
+ pNotif->setIgnored(true);
+ pNotif->respond(response);
+ return true; // don't process this item any further
+ }
+ return false;
+}
+
+namespace LLNotificationFilters
+{
+ // a sample filter
+ bool includeEverything(LLNotificationPtr p)
+ {
+ return true;
+ }
+};
+
+LLNotificationForm::LLNotificationForm()
+: mFormData(LLSD::emptyArray()),
+ mIgnore(IGNORE_NO)
+{
+}
+
+
+LLNotificationForm::LLNotificationForm(const std::string& name, const LLXMLNodePtr xml_node)
+: mFormData(LLSD::emptyArray()),
+ mIgnore(IGNORE_NO)
+{
+ if (!xml_node->hasName("form"))
+ {
+ llwarns << "Bad xml node for form: " << xml_node->getName() << llendl;
+ }
+ LLXMLNodePtr child = xml_node->getFirstChild();
+ while(child)
+ {
+ child = LLNotifications::instance().checkForXMLTemplate(child);
+
+ LLSD item_entry;
+ std::string element_name = child->getName()->mString;
+
+ if (element_name == "ignore")
+ {
+ bool save_option = false;
+ child->getAttribute_bool("save_option", save_option);
+ if (!save_option)
+ {
+ mIgnore = IGNORE_WITH_DEFAULT_RESPONSE;
+ }
+ else
+ {
+ // remember last option chosen by user and automatically respond with that in the future
+ mIgnore = IGNORE_WITH_LAST_RESPONSE;
+ LLUI::sIgnoresGroup->declareLLSD(std::string("Default") + name, "", std::string("Default response for notification " + name));
+ }
+ child->getAttributeString("text", mIgnoreMsg);
+ LLUI::sIgnoresGroup->addWarning(name);
+ }
+ else
+ {
+ // flatten xml form entry into single LLSD map with type==name
+ item_entry["type"] = element_name;
+ const LLXMLAttribList::iterator attrib_end = child->mAttributes.end();
+ for(LLXMLAttribList::iterator attrib_it = child->mAttributes.begin();
+ attrib_it != attrib_end;
+ ++attrib_it)
+ {
+ item_entry[std::string(attrib_it->second->getName()->mString)] = attrib_it->second->getValue();
+ }
+ item_entry["value"] = child->getTextContents();
+ mFormData.append(item_entry);
+ }
+
+ child = child->getNextSibling();
+ }
+}
+
+LLNotificationForm::LLNotificationForm(const LLSD& sd)
+{
+ if (sd.isArray())
+ {
+ mFormData = sd;
+ }
+ else
+ {
+ llwarns << "Invalid form data " << sd << llendl;
+ mFormData = LLSD::emptyArray();
+ }
+}
+
+LLSD LLNotificationForm::asLLSD() const
+{
+ return mFormData;
+}
+
+LLSD LLNotificationForm::getElement(const std::string& element_name)
+{
+ for (LLSD::array_const_iterator it = mFormData.beginArray();
+ it != mFormData.endArray();
+ ++it)
+ {
+ if ((*it)["name"].asString() == element_name) return (*it);
+ }
+ return LLSD();
+}
+
+
+bool LLNotificationForm::hasElement(const std::string& element_name)
+{
+ for (LLSD::array_const_iterator it = mFormData.beginArray();
+ it != mFormData.endArray();
+ ++it)
+ {
+ if ((*it)["name"].asString() == element_name) return true;
+ }
+ return false;
+}
+
+void LLNotificationForm::addElement(const std::string& type, const std::string& name, const LLSD& value)
+{
+ LLSD element;
+ element["type"] = type;
+ element["name"] = name;
+ element["label"] = name;
+ element["value"] = value;
+ element["index"] = mFormData.size();
+ mFormData.append(element);
+}
+
+void LLNotificationForm::append(const LLSD& sub_form)
+{
+ if (sub_form.isArray())
+ {
+ for (LLSD::array_const_iterator it = sub_form.beginArray();
+ it != sub_form.endArray();
+ ++it)
+ {
+ mFormData.append(*it);
+ }
+ }
+}
+
+void LLNotificationForm::formatElements(const LLSD& substitutions)
+{
+ for (LLSD::array_iterator it = mFormData.beginArray();
+ it != mFormData.endArray();
+ ++it)
+ {
+ // format "text" component of each form element
+ if ((*it).has("text"))
+ {
+ std::string text = (*it)["text"].asString();
+ text = LLNotification::format(text, substitutions);
+ (*it)["text"] = text;
+ }
+ if ((*it)["type"].asString() == "text" && (*it).has("value"))
+ {
+ std::string value = (*it)["value"].asString();
+ value = LLNotification::format(value, substitutions);
+ (*it)["value"] = value;
+ }
+ }
+}
+
+std::string LLNotificationForm::getDefaultOption()
+{
+ for (LLSD::array_const_iterator it = mFormData.beginArray();
+ it != mFormData.endArray();
+ ++it)
+ {
+ if ((*it)["default"]) return (*it)["name"].asString();
+ }
+ return "";
+}
+
+LLNotificationTemplate::LLNotificationTemplate() :
+ mExpireSeconds(0),
+ mExpireOption(-1),
+ mURLOption(-1),
+ mUnique(false),
+ mPriority(NOTIFICATION_PRIORITY_NORMAL)
+{
+ mForm = LLNotificationFormPtr(new LLNotificationForm());
+}
+
+LLNotification::LLNotification(const LLNotification::Params& p) :
+ mTimestamp(p.timestamp),
+ mSubstitutions(p.substitutions),
+ mPayload(p.payload),
+ mExpiresAt(0),
+ mResponseFunctorName(p.functor_name),
+ mTemporaryResponder(p.mTemporaryResponder),
+ mRespondedTo(false),
+ mPriority(p.priority),
+ mCancelled(false),
+ mIgnored(false)
+{
+ mId.generate();
+ init(p.name, p.form_elements);
+}
+
+
+LLNotification::LLNotification(const LLSD& sd) :
+ mTemporaryResponder(false),
+ mRespondedTo(false),
+ mCancelled(false),
+ mIgnored(false)
+{
+ mId.generate();
+ mSubstitutions = sd["substitutions"];
+ mPayload = sd["payload"];
+ mTimestamp = sd["time"];
+ mExpiresAt = sd["expiry"];
+ mPriority = (ENotificationPriority)sd["priority"].asInteger();
+ mResponseFunctorName = sd["responseFunctor"].asString();
+ std::string templatename = sd["name"].asString();
+ init(templatename, LLSD());
+ // replace form with serialized version
+ mForm = LLNotificationFormPtr(new LLNotificationForm(sd["form"]));
+}
+
+
+LLSD LLNotification::asLLSD()
+{
+ LLSD output;
+ output["name"] = mTemplatep->mName;
+ output["form"] = getForm()->asLLSD();
+ output["substitutions"] = mSubstitutions;
+ output["payload"] = mPayload;
+ output["time"] = mTimestamp;
+ output["expiry"] = mExpiresAt;
+ output["priority"] = (S32)mPriority;
+ output["responseFunctor"] = mResponseFunctorName;
+ return output;
+}
+
+void LLNotification::update()
+{
+ LLNotifications::instance().update(shared_from_this());
+}
+
+void LLNotification::updateFrom(LLNotificationPtr other)
+{
+ // can only update from the same notification type
+ if (mTemplatep != other->mTemplatep) return;
+
+ // NOTE: do NOT change the ID, since it is the key to
+ // this given instance, just update all the metadata
+ //mId = other->mId;
+
+ mPayload = other->mPayload;
+ mSubstitutions = other->mSubstitutions;
+ mTimestamp = other->mTimestamp;
+ mExpiresAt = other->mExpiresAt;
+ mCancelled = other->mCancelled;
+ mIgnored = other->mIgnored;
+ mPriority = other->mPriority;
+ mForm = other->mForm;
+ mResponseFunctorName = other->mResponseFunctorName;
+ mRespondedTo = other->mRespondedTo;
+ mTemporaryResponder = other->mTemporaryResponder;
+
+ update();
+}
+
+const LLNotificationFormPtr LLNotification::getForm()
+{
+ return mForm;
+}
+
+void LLNotification::cancel()
+{
+ mCancelled = true;
+}
+
+LLSD LLNotification::getResponseTemplate(EResponseTemplateType type)
+{
+ LLSD response = LLSD::emptyMap();
+ for (S32 element_idx = 0;
+ element_idx < mForm->getNumElements();
+ ++element_idx)
+ {
+ LLSD element = mForm->getElement(element_idx);
+ if (element.has("name"))
+ {
+ response[element["name"].asString()] = element["value"];
+ }
+
+ if ((type == WITH_DEFAULT_BUTTON)
+ && element["default"].asBoolean())
+ {
+ response[element["name"].asString()] = true;
+ }
+ }
+ return response;
+}
+
+//static
+S32 LLNotification::getSelectedOption(const LLSD& notification, const LLSD& response)
+{
+ LLNotificationForm form(notification["form"]);
+
+ for (S32 element_idx = 0;
+ element_idx < form.getNumElements();
+ ++element_idx)
+ {
+ LLSD element = form.getElement(element_idx);
+
+ // only look at buttons
+ if (element["type"].asString() == "button"
+ && response[element["name"].asString()].asBoolean())
+ {
+ return element["index"].asInteger();
+ }
+ }
+
+ return -1;
+}
+
+//static
+std::string LLNotification::getSelectedOptionName(const LLSD& response)
+{
+ for (LLSD::map_const_iterator response_it = response.beginMap();
+ response_it != response.endMap();
+ ++response_it)
+ {
+ if (response_it->second.isBoolean() && response_it->second.asBoolean())
+ {
+ return response_it->first;
+ }
+ }
+ return "";
+}
+
+
+void LLNotification::respond(const LLSD& response)
+{
+ mRespondedTo = true;
+ LLNotificationFunctorRegistry::instance().getFunctor(mResponseFunctorName)(asLLSD(), response);
+ if (mTemporaryResponder)
+ {
+ LLNotificationFunctorRegistry::instance().unregisterFunctor(mResponseFunctorName);
+ mResponseFunctorName = "";
+ mTemporaryResponder = false;
+ }
+
+ if (mForm->getIgnoreType() != LLNotificationForm::IGNORE_NO)
+ {
+ LLUI::sIgnoresGroup->setWarning(getName(), !mIgnored);
+ if (mIgnored && mForm->getIgnoreType() == LLNotificationForm::IGNORE_WITH_LAST_RESPONSE)
+ {
+ LLUI::sIgnoresGroup->setLLSD("Default" + getName(), response);
+ }
+ }
+
+ update();
+}
+
+void LLNotification::setIgnored(bool ignore)
+{
+ mIgnored = ignore;
+}
+
+void LLNotification::setResponseFunctor(std::string const &responseFunctorName)
+{
+ if (mTemporaryResponder)
+ // get rid of the old one
+ LLNotificationFunctorRegistry::instance().unregisterFunctor(mResponseFunctorName);
+ mResponseFunctorName = responseFunctorName;
+ mTemporaryResponder = false;
+}
+
+bool LLNotification::payloadContainsAll(const std::vector<std::string>& required_fields) const
+{
+ for(std::vector<std::string>::const_iterator required_fields_it = required_fields.begin();
+ required_fields_it != required_fields.end();
+ required_fields_it++)
+ {
+ std::string required_field_name = *required_fields_it;
+ if( ! getPayload().has(required_field_name))
+ {
+ return false; // a required field was not found
+ }
+ }
+ return true; // all required fields were found
+}
+
+bool LLNotification::isEquivalentTo(LLNotificationPtr that) const
+{
+ if (this->mTemplatep->mName != that->mTemplatep->mName)
+ {
+ return false; // must have the same template name or forget it
+ }
+ if (this->mTemplatep->mUnique)
+ {
+ // highlander bit sez there can only be one of these
+ return
+ this->payloadContainsAll(that->mTemplatep->mUniqueContext) &&
+ that->payloadContainsAll(this->mTemplatep->mUniqueContext);
+ }
+ return false;
+}
+
+void LLNotification::init(const std::string& template_name, const LLSD& form_elements)
+{
+ mTemplatep = LLNotifications::instance().getTemplate(template_name);
+ if (!mTemplatep) return;
+
+ // add default substitutions
+ // TODO: change this to read from the translatable strings file!
+ mSubstitutions["SECOND_LIFE"] = "Second Life";
+ mSubstitutions["_URL"] = getURL();
+ mSubstitutions["_NAME"] = template_name;
+ // TODO: something like this so that a missing alert is sensible:
+ //mSubstitutions["_ARGS"] = get_all_arguments_as_text(mSubstitutions);
+
+ mForm = LLNotificationFormPtr(new LLNotificationForm(*mTemplatep->mForm));
+ mForm->append(form_elements);
+
+ // apply substitution to form labels
+ mForm->formatElements(mSubstitutions);
+
+ LLDate rightnow = LLDate::now();
+ if (mTemplatep->mExpireSeconds)
+ {
+ mExpiresAt = LLDate(rightnow.secondsSinceEpoch() + mTemplatep->mExpireSeconds);
+ }
+
+ if (mPriority == NOTIFICATION_PRIORITY_UNSPECIFIED)
+ {
+ mPriority = mTemplatep->mPriority;
+ }
+}
+
+std::string LLNotification::summarize() const
+{
+ std::string s = "Notification(";
+ s += getName();
+ s += ") : ";
+ s += mTemplatep ? mTemplatep->mMessage : "";
+ // should also include timestamp and expiration time (but probably not payload)
+ return s;
+}
+
+//static
+std::string LLNotification::format(const std::string& s, const LLSD& substitutions)
+{
+ if (!substitutions.isMap())
+ {
+ return s;
+ }
+
+ std::ostringstream output;
+ // match strings like [NAME]
+ const boost::regex key("\\[([0-9_A-Z]+)]");
+
+ std::string::const_iterator start = s.begin();
+ std::string::const_iterator end = s.end();
+ boost::smatch match;
+
+ while (boost::regex_search(start, end, match, key, boost::match_default))
+ {
+ bool found_replacement = false;
+ std::string replacement;
+
+ // see if we have a replacement for the bracketed string (without the brackets)
+ // test first using has() because if we just look up with operator[] we get back an
+ // empty string even if the value is missing. We want to distinguish between
+ // missing replacements and deliberately empty replacement strings.
+ if (substitutions.has(std::string(match[1].first, match[1].second)))
+ {
+ replacement = substitutions[std::string(match[1].first, match[1].second)].asString();
+ found_replacement = true;
+ }
+ // if not, see if there's one WITH brackets
+ else if (substitutions.has(std::string(match[0].first, match[0].second)))
+ {
+ replacement = substitutions[std::string(match[0].first, match[0].second)].asString();
+ found_replacement = true;
+ }
+
+ if (found_replacement)
+ {
+ // found a replacement
+ // "hello world" is output
+ output << std::string(start, match[0].first) << replacement;
+ }
+ else
+ {
+ // we had no replacement, so leave the string we searched for so that it gets noticed by QA
+ // "hello [NAME_NOT_FOUND]" is output
+ output << std::string(start, match[0].second);
+ }
+
+ // update search position
+ start = match[0].second;
+ }
+ // send the remainder of the string (with no further matches for bracketed names)
+ output << std::string(start, end);
+ return output.str();
+}
+
+std::string LLNotification::getMessage() const
+{
+ // all our callers cache this result, so it gives us more flexibility
+ // to do the substitution at call time rather than attempting to
+ // cache it in the notification
+ if (!mTemplatep)
+ return std::string();
+ return format(mTemplatep->mMessage, mSubstitutions);
+}
+
+std::string LLNotification::getLabel() const
+{
+ return (mTemplatep ? format(mTemplatep->mLabel, mSubstitutions) : "");
+}
+
+
+
+// =========================================================
+// LLNotificationChannel implementation
+// ---
+void LLNotificationChannelBase::connectChanged(const LLStandardSignal::slot_type& slot)
+{
+ // when someone wants to connect to a channel, we first throw them
+ // all of the notifications that are already in the channel
+ // we use a special signal called "load" in case the channel wants to care
+ // only about new notifications
+ for (LLNotificationSet::iterator it = mItems.begin(); it != mItems.end(); ++it)
+ {
+ slot.get_slot_function()(LLSD().insert("sigtype", "load").insert("id", (*it)->id()));
+ }
+ // and then connect the signal so that all future notifications will also be
+ // forwarded.
+ mChanged.connect(slot);
+}
+
+void LLNotificationChannelBase::connectPassedFilter(const LLStandardSignal::slot_type& slot)
+{
+ // these two filters only fire for notifications added after the current one, because
+ // they don't participate in the hierarchy.
+ mPassedFilter.connect(slot);
+}
+
+void LLNotificationChannelBase::connectFailedFilter(const LLStandardSignal::slot_type& slot)
+{
+ mFailedFilter.connect(slot);
+}
+
+// external call, conforms to our standard signature
+bool LLNotificationChannelBase::updateItem(const LLSD& payload)
+{
+ // first check to see if it's in the master list
+ LLNotificationPtr pNotification = LLNotifications::instance().find(payload["id"]);
+ if (!pNotification)
+ return false; // not found
+
+ return updateItem(payload, pNotification);
+}
+
+
+//FIX QUIT NOT WORKING
+
+
+// internal call, for use in avoiding lookup
+bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPtr pNotification)
+{
+ std::string cmd = payload["sigtype"];
+ LLNotificationSet::iterator foundItem = mItems.find(pNotification);
+ bool wasFound = (foundItem != mItems.end());
+ bool passesFilter = mFilter(pNotification);
+
+ // first, we offer the result of the filter test to the simple
+ // signals for pass/fail. One of these is guaranteed to be called.
+ // If either signal returns true, the change processing is NOT performed
+ // (so don't return true unless you know what you're doing!)
+ bool abortProcessing = false;
+ if (passesFilter)
+ {
+ abortProcessing = mPassedFilter(payload);
+ }
+ else
+ {
+ abortProcessing = mFailedFilter(payload);
+ }
+
+ if (abortProcessing)
+ {
+ return true;
+ }
+
+ if (cmd == "load")
+ {
+ // should be no reason we'd ever get a load if we already have it
+ // if passes filter send a load message, else do nothing
+ assert(!wasFound);
+ if (passesFilter)
+ {
+ // not in our list, add it and say so
+ mItems.insert(pNotification);
+ abortProcessing = mChanged(payload);
+ onLoad(pNotification);
+ }
+ }
+ else if (cmd == "change")
+ {
+ // if it passes filter now and was found, we just send a change message
+ // if it passes filter now and wasn't found, we have to add it
+ // if it doesn't pass filter and wasn't found, we do nothing
+ // if it doesn't pass filter and was found, we need to delete it
+ if (passesFilter)
+ {
+ if (wasFound)
+ {
+ // it already existed, so this is a change
+ // since it changed in place, all we have to do is resend the signal
+ abortProcessing = mChanged(payload);
+ onChange(pNotification);
+ }
+ else
+ {
+ // not in our list, add it and say so
+ mItems.insert(pNotification);
+ // our payload is const, so make a copy before changing it
+ LLSD newpayload = payload;
+ newpayload["sigtype"] = "add";
+ abortProcessing = mChanged(newpayload);
+ onChange(pNotification);
+ }
+ }
+ else
+ {
+ if (wasFound)
+ {
+ // it already existed, so this is a delete
+ mItems.erase(pNotification);
+ // our payload is const, so make a copy before changing it
+ LLSD newpayload = payload;
+ newpayload["sigtype"] = "delete";
+ abortProcessing = mChanged(newpayload);
+ onChange(pNotification);
+ }
+ // didn't pass, not on our list, do nothing
+ }
+ }
+ else if (cmd == "add")
+ {
+ // should be no reason we'd ever get an add if we already have it
+ // if passes filter send an add message, else do nothing
+ assert(!wasFound);
+ if (passesFilter)
+ {
+ // not in our list, add it and say so
+ mItems.insert(pNotification);
+ abortProcessing = mChanged(payload);
+ onAdd(pNotification);
+ }
+ }
+ else if (cmd == "delete")
+ {
+ // if we have it in our list, pass on the delete, then delete it, else do nothing
+ if (wasFound)
+ {
+ abortProcessing = mChanged(payload);
+ mItems.erase(pNotification);
+ onDelete(pNotification);
+ }
+ }
+ return abortProcessing;
+}
+
+LLNotificationChannel::LLNotificationChannel(const std::string& name,
+ const std::string& parent,
+ LLNotificationFilter filter,
+ LLNotificationComparator comparator) :
+LLNotificationChannelBase(filter, comparator),
+mName(name),
+mParent(parent)
+{
+ // store myself in the channel map
+ LLNotifications::instance().addChannel(LLNotificationChannelPtr(this));
+ // bind to notification broadcast
+ if (parent.empty())
+ {
+ LLNotifications::instance().connectChanged(
+ boost::bind(&LLNotificationChannelBase::updateItem, this, _1));
+ }
+ else
+ {
+ LLNotificationChannelPtr p = LLNotifications::instance().getChannel(parent);
+ LLStandardSignal::slot_type f = boost::bind(&LLNotificationChannelBase::updateItem, this, _1);
+ p->connectChanged(f);
+ }
+}
+
+
+void LLNotificationChannel::setComparator(LLNotificationComparator comparator)
+{
+ mComparator = comparator;
+ LLNotificationSet s2(mComparator);
+ s2.insert(mItems.begin(), mItems.end());
+ mItems.swap(s2);
+
+ // notify clients that we've been resorted
+ mChanged(LLSD().insert("sigtype", "sort"));
+}
+
+bool LLNotificationChannel::isEmpty() const
+{
+ return mItems.empty();
+}
+
+LLNotificationChannel::Iterator LLNotificationChannel::begin()
+{
+ return mItems.begin();
+}
+
+LLNotificationChannel::Iterator LLNotificationChannel::end()
+{
+ return mItems.end();
+}
+
+std::string LLNotificationChannel::summarize()
+{
+ std::string s("Channel '");
+ s += mName;
+ s += "'\n ";
+ for (LLNotificationChannel::Iterator it = begin(); it != end(); ++it)
+ {
+ s += (*it)->summarize();
+ s += "\n ";
+ }
+ return s;
+}
+
+
+// ---
+// END OF LLNotificationChannel implementation
+// =========================================================
+
+
+// =========================================================
+// LLNotifications implementation
+// ---
+LLNotifications::LLNotifications() : LLNotificationChannelBase(LLNotificationFilters::includeEverything,
+ LLNotificationComparators::orderByUUID())
+{
+}
+
+
+// The expiration channel gets all notifications that are cancelled
+bool LLNotifications::expirationFilter(LLNotificationPtr pNotification)
+{
+ return pNotification->isCancelled() || pNotification->isRespondedTo();
+}
+
+bool LLNotifications::expirationHandler(const LLSD& payload)
+{
+ if (payload["sigtype"].asString() != "delete")
+ {
+ // anything added to this channel actually should be deleted from the master
+ cancel(find(payload["id"]));
+ return true; // don't process this item any further
+ }
+ return false;
+}
+
+bool LLNotifications::uniqueFilter(LLNotificationPtr pNotif)
+{
+ if (!pNotif->hasUniquenessConstraints())
+ {
+ return true;
+ }
+
+ // checks against existing unique notifications
+ for (LLNotificationMap::iterator existing_it = mUniqueNotifications.find(pNotif->getName());
+ existing_it != mUniqueNotifications.end();
+ ++existing_it)
+ {
+ LLNotificationPtr existing_notification = existing_it->second;
+ if (pNotif != existing_notification
+ && pNotif->isEquivalentTo(existing_notification))
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool LLNotifications::uniqueHandler(const LLSD& payload)
+{
+ LLNotificationPtr pNotif = LLNotifications::instance().find(payload["id"].asUUID());
+ if (pNotif && pNotif->hasUniquenessConstraints())
+ {
+ if (payload["sigtype"].asString() == "add")
+ {
+ // not a duplicate according to uniqueness criteria, so we keep it
+ // and store it for future uniqueness checks
+ mUniqueNotifications.insert(std::make_pair(pNotif->getName(), pNotif));
+ }
+ else if (payload["sigtype"].asString() == "delete")
+ {
+ mUniqueNotifications.erase(pNotif->getName());
+ }
+ }
+
+ return false;
+}
+
+bool LLNotifications::failedUniquenessTest(const LLSD& payload)
+{
+ LLNotificationPtr pNotif = LLNotifications::instance().find(payload["id"].asUUID());
+
+ if (!pNotif || !pNotif->hasUniquenessConstraints())
+ {
+ return false;
+ }
+
+ // checks against existing unique notifications
+ for (LLNotificationMap::iterator existing_it = mUniqueNotifications.find(pNotif->getName());
+ existing_it != mUniqueNotifications.end();
+ ++existing_it)
+ {
+ LLNotificationPtr existing_notification = existing_it->second;
+ if (pNotif != existing_notification
+ && pNotif->isEquivalentTo(existing_notification))
+ {
+ // copy notification instance data over to oldest instance
+ // of this unique notification and update it
+ existing_notification->updateFrom(pNotif);
+ // then delete the new one
+ pNotif->cancel();
+ }
+ }
+
+ return false;
+}
+
+
+void LLNotifications::addChannel(LLNotificationChannelPtr pChan)
+{
+ mChannels[pChan->getName()] = pChan;
+}
+
+LLNotificationChannelPtr LLNotifications::getChannel(const std::string& channelName)
+{
+ ChannelMap::iterator p = mChannels.find(channelName);
+ if(p == mChannels.end())
+ {
+ llerrs << "Did not find channel named " << channelName << llendl;
+ }
+ return p->second;
+}
+
+
+// this function is called once at construction time, after the object is constructed.
+void LLNotifications::initSingleton()
+{
+ loadTemplates();
+ createDefaultChannels();
+}
+
+void LLNotifications::createDefaultChannels()
+{
+ // now construct the various channels AFTER loading the notifications,
+ // because the history channel is going to rewrite the stored notifications file
+ new LLNotificationChannel("Expiration", "",
+ boost::bind(&LLNotifications::expirationFilter, this, _1));
+ new LLNotificationChannel("Unexpired", "",
+ !boost::bind(&LLNotifications::expirationFilter, this, _1)); // use negated bind
+ new LLNotificationChannel("Unique", "Unexpired",
+ boost::bind(&LLNotifications::uniqueFilter, this, _1));
+ new LLNotificationChannel("Ignore", "Unique",
+ filterIgnoredNotifications);
+ new LLNotificationChannel("Visible", "Ignore",
+ &LLNotificationFilters::includeEverything);
+
+ // create special history channel
+ //std::string notifications_log_file = gDirUtilp->getExpandedFilename ( LL_PATH_PER_SL_ACCOUNT, "open_notifications.xml" );
+ // use ^^^ when done debugging notifications serialization
+ std::string notifications_log_file = gDirUtilp->getExpandedFilename ( LL_PATH_USER_SETTINGS, "open_notifications.xml" );
+ new LLNotificationHistoryChannel(notifications_log_file);
+
+ // connect action methods to these channels
+ LLNotifications::instance().getChannel("Expiration")->
+ connectChanged(boost::bind(&LLNotifications::expirationHandler, this, _1));
+ LLNotifications::instance().getChannel("Unique")->
+ connectChanged(boost::bind(&LLNotifications::uniqueHandler, this, _1));
+ LLNotifications::instance().getChannel("Unique")->
+ connectFailedFilter(boost::bind(&LLNotifications::failedUniquenessTest, this, _1));
+ LLNotifications::instance().getChannel("Ignore")->
+ connectFailedFilter(&handleIgnoredNotification);
+}
+
+static std::string sStringSkipNextTime("Skip this dialog next time");
+static std::string sStringAlwaysChoose("Always choose this option");
+
+bool LLNotifications::addTemplate(const std::string &name,
+ LLNotificationTemplatePtr theTemplate)
+{
+ if (mTemplates.count(name))
+ {
+ llwarns << "LLNotifications -- attempted to add template '" << name << "' twice." << llendl;
+ return false;
+ }
+ mTemplates[name] = theTemplate;
+ return true;
+}
+
+LLNotificationTemplatePtr LLNotifications::getTemplate(const std::string& name)
+{
+ if (mTemplates.count(name))
+ {
+ return mTemplates[name];
+ }
+ else
+ {
+ return mTemplates["MissingAlert"];
+ }
+}
+
+bool LLNotifications::templateExists(const std::string& name)
+{
+ return (mTemplates.count(name) != 0);
+}
+
+void LLNotifications::clearTemplates()
+{
+ mTemplates.clear();
+}
+
+void LLNotifications::forceResponse(const LLNotification::Params& params, S32 option)
+{
+ LLNotificationPtr temp_notify(new LLNotification(params));
+ LLSD response = temp_notify->getResponseTemplate();
+ LLSD selected_item = temp_notify->getForm()->getElement(option);
+
+ if (selected_item.isUndefined())
+ {
+ llwarns << "Invalid option" << option << " for notification " << (std::string)params.name << llendl;
+ return;
+ }
+ response[selected_item["name"].asString()] = true;
+
+ temp_notify->respond(response);
+}
+
+LLNotifications::TemplateNames LLNotifications::getTemplateNames() const
+{
+ TemplateNames names;
+ for (TemplateMap::const_iterator it = mTemplates.begin(); it != mTemplates.end(); ++it)
+ {
+ names.push_back(it->first);
+ }
+ return names;
+}
+
+typedef std::map<std::string, std::string> StringMap;
+void replaceSubstitutionStrings(LLXMLNodePtr node, StringMap& replacements)
+{
+ //llwarns << "replaceSubstitutionStrings" << llendl;
+ // walk the list of attributes looking for replacements
+ for (LLXMLAttribList::iterator it=node->mAttributes.begin();
+ it != node->mAttributes.end(); ++it)
+ {
+ std::string value = it->second->getValue();
+ if (value[0] == '$')
+ {
+ value.erase(0, 1); // trim off the $
+ std::string replacement;
+ StringMap::const_iterator found = replacements.find(value);
+ if (found != replacements.end())
+ {
+ replacement = found->second;
+ //llwarns << "replaceSubstituionStrings: value: " << value << " repl: " << replacement << llendl;
+
+ it->second->setValue(replacement);
+ }
+ else
+ {
+ llwarns << "replaceSubstituionStrings FAILURE: value: " << value << " repl: " << replacement << llendl;
+ }
+ }
+ }
+
+ // now walk the list of children and call this recursively.
+ for (LLXMLNodePtr child = node->getFirstChild();
+ child.notNull(); child = child->getNextSibling())
+ {
+ replaceSubstitutionStrings(child, replacements);
+ }
+}
+
+// private to this file
+// returns true if the template request was invalid and there's nothing else we
+// can do with this node, false if you should keep processing (it may have
+// replaced the contents of the node referred to)
+LLXMLNodePtr LLNotifications::checkForXMLTemplate(LLXMLNodePtr item)
+{
+ if (item->hasName("usetemplate"))
+ {
+ std::string replacementName;
+ if (item->getAttributeString("name", replacementName))
+ {
+ StringMap replacements;
+ for (LLXMLAttribList::const_iterator it=item->mAttributes.begin();
+ it != item->mAttributes.end(); ++it)
+ {
+ replacements[it->second->getName()->mString] = it->second->getValue();
+ }
+ if (mXmlTemplates.count(replacementName))
+ {
+ item=LLXMLNode::replaceNode(item, mXmlTemplates[replacementName]);
+
+ // walk the nodes looking for $(substitution) here and replace
+ replaceSubstitutionStrings(item, replacements);
+ }
+ else
+ {
+ llwarns << "XML template lookup failure on '" << replacementName << "' " << llendl;
+ }
+ }
+ }
+ return item;
+}
+
+bool LLNotifications::loadTemplates()
+{
+ const std::string xml_filename = "notifications.xml";
+ LLXMLNodePtr root;
+
+ BOOL success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root);
+
+ if (!success || root.isNull() || !root->hasName( "notifications" ))
+ {
+ llerrs << "Problem reading UI Notifications file: " << xml_filename << llendl;
+ return false;
+ }
+
+ clearTemplates();
+
+ for (LLXMLNodePtr item = root->getFirstChild();
+ item.notNull(); item = item->getNextSibling())
+ {
+ // we do this FIRST so that item can be changed if we
+ // encounter a usetemplate -- we just replace the
+ // current xml node and keep processing
+ item = checkForXMLTemplate(item);
+
+ if (item->hasName("global"))
+ {
+ std::string global_name;
+ if (item->getAttributeString("name", global_name))
+ {
+ mGlobalStrings[global_name] = item->getTextContents();
+ }
+ continue;
+ }
+
+ if (item->hasName("template"))
+ {
+ // store an xml template; templates must have a single node (can contain
+ // other nodes)
+ std::string name;
+ item->getAttributeString("name", name);
+ LLXMLNodePtr ptr = item->getFirstChild();
+ mXmlTemplates[name] = ptr;
+ continue;
+ }
+
+ if (!item->hasName("notification"))
+ {
+ llwarns << "Unexpected entity " << item->getName()->mString <<
+ " found in " << xml_filename << llendl;
+ continue;
+ }
+
+ // now we know we have a notification entry, so let's build it
+ LLNotificationTemplatePtr pTemplate(new LLNotificationTemplate());
+
+ if (!item->getAttributeString("name", pTemplate->mName))
+ {
+ llwarns << "Unable to parse notification with no name" << llendl;
+ continue;
+ }
+
+ //llinfos << "Parsing " << pTemplate->mName << llendl;
+
+ pTemplate->mMessage = item->getTextContents();
+ pTemplate->mDefaultFunctor = pTemplate->mName;
+ item->getAttributeString("type", pTemplate->mType);
+ item->getAttributeString("icon", pTemplate->mIcon);
+ item->getAttributeString("label", pTemplate->mLabel);
+ item->getAttributeU32("duration", pTemplate->mExpireSeconds);
+ item->getAttributeU32("expireOption", pTemplate->mExpireOption);
+
+ std::string priority;
+ item->getAttributeString("priority", priority);
+ pTemplate->mPriority = NOTIFICATION_PRIORITY_NORMAL;
+ if (!priority.empty())
+ {
+ if (priority == "low") pTemplate->mPriority = NOTIFICATION_PRIORITY_LOW;
+ if (priority == "normal") pTemplate->mPriority = NOTIFICATION_PRIORITY_NORMAL;
+ if (priority == "high") pTemplate->mPriority = NOTIFICATION_PRIORITY_HIGH;
+ if (priority == "critical") pTemplate->mPriority = NOTIFICATION_PRIORITY_CRITICAL;
+ }
+
+ item->getAttributeString("functor", pTemplate->mDefaultFunctor);
+
+ BOOL persist = false;
+ item->getAttributeBOOL("persist", persist);
+ pTemplate->mPersist = persist;
+
+ std::string sound;
+ item->getAttributeString("sound", sound);
+ if (!sound.empty())
+ {
+ // TODO: test for bad sound effect name / missing effect
+ pTemplate->mSoundEffect = LLUUID(LLUI::sConfigGroup->getString(sound.c_str()));
+ }
+
+ for (LLXMLNodePtr child = item->getFirstChild();
+ !child.isNull(); child = child->getNextSibling())
+ {
+ child = checkForXMLTemplate(child);
+
+ // <url>
+ if (child->hasName("url"))
+ {
+ pTemplate->mURL = child->getTextContents();
+ child->getAttributeU32("option", pTemplate->mURLOption);
+ }
+
+ if (child->hasName("unique"))
+ {
+ pTemplate->mUnique = true;
+ for (LLXMLNodePtr formitem = child->getFirstChild();
+ !formitem.isNull(); formitem = formitem->getNextSibling())
+ {
+ if (formitem->hasName("context"))
+ {
+ std::string key;
+ formitem->getAttributeString("key", key);
+ pTemplate->mUniqueContext.push_back(key);
+ //llwarns << "adding " << key << " to unique context" << llendl;
+ }
+ else
+ {
+ llwarns << "'unique' has unrecognized subelement "
+ << formitem->getName()->mString << llendl;
+ }
+ }
+ }
+
+ // <form>
+ if (child->hasName("form"))
+ {
+ pTemplate->mForm = LLNotificationFormPtr(new LLNotificationForm(pTemplate->mName, child));
+ }
+ }
+ addTemplate(pTemplate->mName, pTemplate);
+ }
+
+ //std::ostringstream ostream;
+ //root->writeToOstream(ostream, "\n ");
+ //llwarns << ostream.str() << llendl;
+
+ return true;
+}
+
+// we provide a couple of simple add notification functions so that it's reasonable to create notifications in one line
+LLNotificationPtr LLNotifications::add(const std::string& name,
+ const LLSD& substitutions,
+ const LLSD& payload)
+{
+ return add(LLNotification::Params(name).substitutions(substitutions).payload(payload));
+}
+
+LLNotificationPtr LLNotifications::add(const std::string& name,
+ const LLSD& substitutions,
+ const LLSD& payload,
+ const std::string& functor_name)
+{
+ return add(LLNotification::Params(name).substitutions(substitutions).payload(payload).functor_name(functor_name));
+}
+
+LLNotificationPtr LLNotifications::add(const std::string& name,
+ const LLSD& substitutions,
+ const LLSD& payload,
+ LLNotificationFunctorRegistry::ResponseFunctor functor)
+{
+ return add(LLNotification::Params(name).substitutions(substitutions).payload(payload).functor(functor));
+}
+
+// generalized add function that takes a parameter block object for more complex instantiations
+LLNotificationPtr LLNotifications::add(const LLNotification::Params& p)
+{
+ LLNotificationPtr pNotif(new LLNotification(p));
+ add(pNotif);
+ return pNotif;
+}
+
+
+void LLNotifications::add(const LLNotificationPtr pNotif)
+{
+ // first see if we already have it -- if so, that's a problem
+ LLNotificationSet::iterator it=mItems.find(pNotif);
+ if (it != mItems.end())
+ {
+ llerrs << "Notification added a second time to the master notification channel." << llendl;
+ }
+
+ updateItem(LLSD().insert("sigtype", "add").insert("id", pNotif->id()), pNotif);
+}
+
+void LLNotifications::cancel(LLNotificationPtr pNotif)
+{
+ LLNotificationSet::iterator it=mItems.find(pNotif);
+ if (it == mItems.end())
+ {
+ llerrs << "Attempted to delete nonexistent notification " << pNotif->getName() << llendl;
+ }
+ updateItem(LLSD().insert("sigtype", "delete").insert("id", pNotif->id()), pNotif);
+ pNotif->cancel();
+}
+
+void LLNotifications::update(const LLNotificationPtr pNotif)
+{
+ LLNotificationSet::iterator it=mItems.find(pNotif);
+ if (it != mItems.end())
+ {
+ updateItem(LLSD().insert("sigtype", "change").insert("id", pNotif->id()), pNotif);
+ }
+}
+
+
+LLNotificationPtr LLNotifications::find(LLUUID uuid)
+{
+ LLNotificationPtr target = LLNotificationPtr(new LLNotification(uuid));
+ LLNotificationSet::iterator it=mItems.find(target);
+ if (it == mItems.end())
+ {
+ llwarns << "Tried to dereference uuid '" << uuid << "' as a notification key but didn't find it." << llendl;
+ return LLNotificationPtr((LLNotification*)NULL);
+ }
+ else
+ {
+ return *it;
+ }
+}
+
+void LLNotifications::forEachNotification(NotificationProcess process)
+{
+ std::for_each(mItems.begin(), mItems.end(), process);
+}
+
+std::string LLNotifications::getGlobalString(const std::string& key) const
+{
+ GlobalStringMap::const_iterator it = mGlobalStrings.find(key);
+ if (it != mGlobalStrings.end())
+ {
+ return it->second;
+ }
+ else
+ {
+ // if we don't have the key as a global, return the key itself so that the error
+ // is self-diagnosing.
+ return key;
+ }
+}
+
+
+// ---
+// END OF LLNotifications implementation
+// =========================================================
+
+std::ostream& operator<<(std::ostream& s, const LLNotification& notification)
+{
+ s << notification.summarize();
+ return s;
+}
+
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h
new file mode 100644
index 0000000000..2a2003f499
--- /dev/null
+++ b/indra/llui/llnotifications.h
@@ -0,0 +1,892 @@
+/**
+* @file llnotifications.h
+* @brief Non-UI manager and support for keeping a prioritized list of notifications
+* @author Q (with assistance from Richard and Coco)
+*
+* $LicenseInfo:firstyear=2008&license=viewergpl$
+*
+* Copyright (c) 2008, Linden Research, Inc.
+*
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab. Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+*
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
+*
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+
+#ifndef LL_LLNOTIFICATIONS_H
+#define LL_LLNOTIFICATIONS_H
+
+/**
+ * This system is intended to provide a singleton mechanism for adding
+ * notifications to one of an arbitrary set of event channels.
+ *
+ * Controlling JIRA: DEV-9061
+ *
+ * Every notification has (see code for full list):
+ * - a textual name, which is used to look up its template in the XML files
+ * - a payload, which is a block of LLSD
+ * - a channel, which is normally extracted from the XML files but
+ * can be overridden.
+ * - a timestamp, used to order the notifications
+ * - expiration time -- if nonzero, specifies a time after which the
+ * notification will no longer be valid.
+ * - a callback name and a couple of status bits related to callbacks (see below)
+ *
+ * There is a management class called LLNotifications, which is an LLSingleton.
+ * The class maintains a collection of all of the notifications received
+ * or processed during this session, and also manages the persistence
+ * of those notifications that must be persisted.
+ *
+ * We also have Channels. A channel is a view on a collection of notifications;
+ * The collection is defined by a filter function that controls which
+ * notifications are in the channel, and its ordering is controlled by
+ * a comparator.
+ *
+ * There is a hierarchy of channels; notifications flow down from
+ * the management class (LLNotifications, which itself inherits from
+ * The channel base class) to the individual channels.
+ * Any change to notifications (add, delete, modify) is
+ * automatically propagated through the channel hierarchy.
+ *
+ * We provide methods for adding a new notification, for removing
+ * one, and for managing channels. Channels are relatively cheap to construct
+ * and maintain, so in general, human interfaces should use channels to
+ * select and manage their lists of notifications.
+ *
+ * We also maintain a collection of templates that are loaded from the
+ * XML file of template translations. The system supports substitution
+ * of named variables from the payload into the XML file.
+ *
+ * By default, only the "unknown message" template is built into the system.
+ * It is not an error to add a notification that's not found in the
+ * template system, but it is logged.
+ *
+ */
+
+#include <string>
+#include <list>
+#include <vector>
+#include <map>
+#include <set>
+#include <iomanip>
+#include <sstream>
+
+#include <boost/utility.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/signal.hpp>
+#include <boost/type_traits.hpp>
+
+// we want to minimize external dependencies, but this one is important
+#include "llsd.h"
+
+// and we need this to manage the notification callbacks
+#include "llfunctorregistry.h"
+#include "llui.h"
+
+class LLNotification;
+typedef boost::shared_ptr<LLNotification> LLNotificationPtr;
+
+/*****************************************************************************
+* Signal and handler declarations
+* Using a single handler signature means that we can have a common handler
+* type, rather than needing a distinct one for each different handler.
+*****************************************************************************/
+
+/**
+ * A boost::signals Combiner that stops the first time a handler returns true
+ * We need this because we want to have our handlers return bool, so that
+ * we have the option to cause a handler to stop further processing. The
+ * default handler fails when the signal returns a value but has no slots.
+ */
+struct LLStopWhenHandled
+{
+ typedef bool result_type;
+
+ template<typename InputIterator>
+ result_type operator()(InputIterator first, InputIterator last) const
+ {
+ for (InputIterator si = first; si != last; ++si)
+ {
+ if (*si)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+};
+
+
+typedef enum e_notification_priority
+{
+ NOTIFICATION_PRIORITY_UNSPECIFIED,
+ NOTIFICATION_PRIORITY_LOW,
+ NOTIFICATION_PRIORITY_NORMAL,
+ NOTIFICATION_PRIORITY_HIGH,
+ NOTIFICATION_PRIORITY_CRITICAL
+} ENotificationPriority;
+
+/**
+ * We want to have a standard signature for all signals; this way,
+ * we can easily document a protocol for communicating across
+ * dlls and into scripting languages someday.
+ * we want to return a bool to indicate whether the signal has been
+ * handled and should NOT be passed on to other listeners.
+ * Return true to stop further handling of the signal, and false
+ * to continue.
+ * We take an LLSD because this way the contents of the signal
+ * are independent of the API used to communicate it.
+ * It is const ref because then there's low cost to pass it;
+ * if you only need to inspect it, it's very cheap.
+ */
+
+typedef boost::function<void (const LLSD&, const LLSD&)> LLNotificationResponder;
+
+typedef LLFunctorRegistry<LLNotificationResponder> LLNotificationFunctorRegistry;
+typedef LLFunctorRegistration<LLNotificationResponder> LLNotificationFunctorRegistration;
+
+typedef boost::signal<bool(const LLSD&), LLStopWhenHandled> LLStandardSignal;
+
+// context data that can be looked up via a notification's payload by the display logic
+// derive from this class to implement specific contexts
+class LLNotificationContext : public LLInstanceTracker<LLNotificationContext, LLUUID>
+{
+public:
+ LLNotificationContext() : LLInstanceTracker<LLNotificationContext, LLUUID>(LLUUID::generateNewID())
+ {
+ }
+
+ virtual ~LLNotificationContext() {}
+
+ LLSD asLLSD() const
+ {
+ return getKey();
+ }
+
+private:
+
+};
+
+// Contains notification form data, such as buttons and text fields along with
+// manipulator functions
+class LLNotificationForm
+{
+ LOG_CLASS(LLNotificationForm);
+
+public:
+ typedef enum e_ignore_type
+ {
+ IGNORE_NO,
+ IGNORE_WITH_DEFAULT_RESPONSE,
+ IGNORE_WITH_LAST_RESPONSE,
+ IGNORE_SHOW_AGAIN
+ } EIgnoreType;
+
+ LLNotificationForm();
+ LLNotificationForm(const LLSD& sd);
+ LLNotificationForm(const std::string& name, const LLXMLNodePtr xml_node);
+
+ LLSD asLLSD() const;
+
+ S32 getNumElements() { return mFormData.size(); }
+ LLSD getElement(S32 index) { return mFormData.get(index); }
+ LLSD getElement(const std::string& element_name);
+ bool hasElement(const std::string& element_name);
+ void addElement(const std::string& type, const std::string& name, const LLSD& value = LLSD());
+ void formatElements(const LLSD& substitutions);
+ // appends form elements from another form serialized as LLSD
+ void append(const LLSD& sub_form);
+ std::string getDefaultOption();
+
+ EIgnoreType getIgnoreType() { return mIgnore; }
+ std::string getIgnoreMessage() { return mIgnoreMsg; }
+
+private:
+ LLSD mFormData;
+ EIgnoreType mIgnore;
+ std::string mIgnoreMsg;
+};
+
+typedef boost::shared_ptr<LLNotificationForm> LLNotificationFormPtr;
+
+// This is the class of object read from the XML file (notifications.xml,
+// from the appropriate local language directory).
+struct LLNotificationTemplate
+{
+ LLNotificationTemplate();
+ // the name of the notification -- the key used to identify it
+ // Ideally, the key should follow variable naming rules
+ // (no spaces or punctuation).
+ std::string mName;
+ // The type of the notification
+ // used to control which queue it's stored in
+ std::string mType;
+ // The text used to display the notification. Replaceable parameters
+ // are enclosed in square brackets like this [].
+ std::string mMessage;
+ // The label for the notification; used for
+ // certain classes of notification (those with a window and a window title).
+ // Also used when a notification pops up underneath the current one.
+ // Replaceable parameters can be used in the label.
+ std::string mLabel;
+ // The name of the icon image. This should include an extension.
+ std::string mIcon;
+ // This is the Highlander bit -- "There Can Be Only One"
+ // An outstanding notification with this bit set
+ // is updated by an incoming notification with the same name,
+ // rather than creating a new entry in the queue.
+ // (used for things like progress indications, or repeating warnings
+ // like "the grid is going down in N minutes")
+ bool mUnique;
+ // if we want to be unique only if a certain part of the payload is constant
+ // specify the field names for the payload. The notification will only be
+ // combined if all of the fields named in the context are identical in the
+ // new and the old notification; otherwise, the notification will be
+ // duplicated. This is to support suppressing duplicate offers from the same
+ // sender but still differentiating different offers. Example: Invitation to
+ // conference chat.
+ std::vector<std::string> mUniqueContext;
+ // If this notification expires automatically, this value will be
+ // nonzero, and indicates the number of seconds for which the notification
+ // will be valid (a teleport offer, for example, might be valid for
+ // 300 seconds).
+ U32 mExpireSeconds;
+ // if the offer expires, one of the options is chosen automatically
+ // based on its "value" parameter. This controls which one.
+ // If expireSeconds is specified, expireOption should also be specified.
+ U32 mExpireOption;
+ // if the notification contains a url, it's stored here (and replaced
+ // into the message where [_URL] is found)
+ std::string mURL;
+ // if there's a URL in the message, this controls which option visits
+ // that URL. Obsolete this and eliminate the buttons for affected
+ // messages when we allow clickable URLs in the UI
+ U32 mURLOption;
+ // does this notification persist across sessions? if so, it will be
+ // serialized to disk on first receipt and read on startup
+ bool mPersist;
+ // This is the name of the default functor, if present, to be
+ // used for the notification's callback. It is optional, and used only if
+ // the notification is constructed without an identified functor.
+ std::string mDefaultFunctor;
+ // The form data associated with a given notification (buttons, text boxes, etc)
+ LLNotificationFormPtr mForm;
+ // default priority for notifications of this type
+ ENotificationPriority mPriority;
+ // UUID of the audio file to be played when this notification arrives
+ // this is loaded as a name, but looked up to get the UUID upon template load.
+ // If null, it wasn't specified.
+ LLUUID mSoundEffect;
+};
+
+// we want to keep a map of these by name, and it's best to manage them
+// with smart pointers
+typedef boost::shared_ptr<LLNotificationTemplate> LLNotificationTemplatePtr;
+
+/**
+ * @class LLNotification
+ * @brief The object that expresses the details of a notification
+ *
+ * We make this noncopyable because
+ * we want to manage these through LLNotificationPtr, and only
+ * ever create one instance of any given notification.
+ *
+ * The enable_shared_from_this flag ensures that if we construct
+ * a smart pointer from a notification, we'll always get the same
+ * shared pointer.
+ */
+class LLNotification :
+ boost::noncopyable,
+ public boost::enable_shared_from_this<LLNotification>
+{
+LOG_CLASS(LLNotification);
+friend class LLNotifications;
+
+public:
+ // parameter object used to instantiate a new notification
+ class Params : public LLParamBlock<Params>
+ {
+ friend class LLNotification;
+ public:
+ Params(const std::string& _name)
+ : name(_name),
+ mTemporaryResponder(false),
+ functor_name(_name),
+ priority(NOTIFICATION_PRIORITY_UNSPECIFIED),
+ timestamp(LLDate::now())
+ {
+ }
+
+ // pseudo-param
+ Params& functor(LLNotificationFunctorRegistry::ResponseFunctor f)
+ {
+ functor_name = LLUUID::generateNewID().asString();
+ LLNotificationFunctorRegistry::instance().registerFunctor(functor_name, f);
+
+ mTemporaryResponder = true;
+ return *this;
+ }
+
+ LLMandatoryParam<std::string> name;
+
+ // optional
+ LLOptionalParam<LLSD> substitutions;
+ LLOptionalParam<LLSD> payload;
+ LLOptionalParam<ENotificationPriority> priority;
+ LLOptionalParam<LLSD> form_elements;
+ LLOptionalParam<LLDate> timestamp;
+ LLOptionalParam<LLNotificationContext*> context;
+ LLOptionalParam<std::string> functor_name;
+
+ private:
+ bool mTemporaryResponder;
+ };
+
+private:
+
+ LLUUID mId;
+ LLSD mPayload;
+ LLSD mSubstitutions;
+ LLDate mTimestamp;
+ LLDate mExpiresAt;
+ bool mCancelled;
+ bool mRespondedTo; // once the notification has been responded to, this becomes true
+ bool mIgnored;
+ ENotificationPriority mPriority;
+ LLNotificationFormPtr mForm;
+
+ // a reference to the template
+ LLNotificationTemplatePtr mTemplatep;
+
+ /*
+ We want to be able to store and reload notifications so that they can survive
+ a shutdown/restart of the client. So we can't simply pass in callbacks;
+ we have to specify a callback mechanism that can be used by name rather than
+ by some arbitrary pointer -- and then people have to initialize callbacks
+ in some useful location. So we use LLNotificationFunctorRegistry to manage them.
+ */
+ std::string mResponseFunctorName;
+
+ /*
+ In cases where we want to specify an explict, non-persisted callback,
+ we store that in the callback registry under a dynamically generated
+ key, and store the key in the notification, so we can still look it up
+ using the same mechanism.
+ */
+ bool mTemporaryResponder;
+
+ void init(const std::string& template_name, const LLSD& form_elements);
+
+ LLNotification(const Params& p);
+
+ // this is just for making it easy to look things up in a set organized by UUID -- DON'T USE IT
+ // for anything real!
+ LLNotification(LLUUID uuid) : mId(uuid) {}
+
+ void cancel();
+
+ bool payloadContainsAll(const std::vector<std::string>& required_fields) const;
+
+public:
+
+ // constructor from a saved notification
+ LLNotification(const LLSD& sd);
+
+ // This is a string formatter for substituting into the message directly
+ // from LLSD without going through the hopefully-to-be-obsoleted LLString
+ static std::string format(const std::string& text, const LLSD& substitutions);
+
+ void setResponseFunctor(std::string const &responseFunctorName);
+
+ typedef enum e_response_template_type
+ {
+ WITHOUT_DEFAULT_BUTTON,
+ WITH_DEFAULT_BUTTON
+ } EResponseTemplateType;
+
+ // return response LLSD filled in with default form contents and (optionally) the default button selected
+ LLSD getResponseTemplate(EResponseTemplateType type = WITHOUT_DEFAULT_BUTTON);
+
+ // returns index of first button with value==TRUE
+ // usually this the button the user clicked on
+ // returns -1 if no button clicked (e.g. form has not been displayed)
+ static S32 getSelectedOption(const LLSD& notification, const LLSD& response);
+ // returns name of first button with value==TRUE
+ static std::string getSelectedOptionName(const LLSD& notification);
+
+ // after someone responds to a notification (usually by clicking a button,
+ // but sometimes by filling out a little form and THEN clicking a button),
+ // the result of the response (the name and value of the button clicked,
+ // plus any other data) should be packaged up as LLSD, then passed as a
+ // parameter to the notification's respond() method here. This will look up
+ // and call the appropriate responder.
+ //
+ // response is notification serialized as LLSD:
+ // ["name"] = notification name
+ // ["form"] = LLSD tree that includes form description and any prefilled form data
+ // ["response"] = form data filled in by user
+ // (including, but not limited to which button they clicked on)
+ // ["payload"] = transaction specific data, such as ["source_id"] (originator of notification),
+ // ["item_id"] (attached inventory item), etc.
+ // ["substitutions"] = string substitutions used to generate notification message
+ // from the template
+ // ["time"] = time at which notification was generated;
+ // ["expiry"] = time at which notification expires;
+ // ["responseFunctor"] = name of registered functor that handles responses to notification;
+ LLSD asLLSD();
+
+ void respond(const LLSD& sd);
+
+ void setIgnored(bool ignore);
+
+ bool isCancelled() const
+ {
+ return mCancelled;
+ }
+
+ bool isRespondedTo() const
+ {
+ return mRespondedTo;
+ }
+
+ bool isIgnored() const
+ {
+ return mIgnored;
+ }
+
+ const std::string& getName() const
+ {
+ return mTemplatep->mName;
+ }
+
+ const LLUUID& id() const
+ {
+ return mId;
+ }
+
+ const LLSD& getPayload() const
+ {
+ return mPayload;
+ }
+
+ const LLSD& getSubstitutions() const
+ {
+ return mSubstitutions;
+ }
+
+ const LLDate& getDate() const
+ {
+ return mTimestamp;
+ }
+
+ std::string getType() const
+ {
+ return (mTemplatep ? mTemplatep->mType : "");
+ }
+
+ std::string getMessage() const;
+ std::string getLabel() const;
+
+ std::string getURL() const
+ {
+ return (mTemplatep ? mTemplatep->mURL : "");
+ }
+
+ S32 getURLOption() const
+ {
+ return (mTemplatep ? mTemplatep->mURLOption : -1);
+ }
+
+ const LLNotificationFormPtr getForm();
+
+ const LLDate getExpiration() const
+ {
+ return mExpiresAt;
+ }
+
+ ENotificationPriority getPriority() const
+ {
+ return mPriority;
+ }
+
+ const LLUUID getID() const
+ {
+ return mId;
+ }
+
+ // comparing two notifications normally means comparing them by UUID (so we can look them
+ // up quickly this way)
+ bool operator<(const LLNotification& rhs) const
+ {
+ return mId < rhs.mId;
+ }
+
+ bool operator==(const LLNotification& rhs) const
+ {
+ return mId == rhs.mId;
+ }
+
+ bool operator!=(const LLNotification& rhs) const
+ {
+ return !operator==(rhs);
+ }
+
+ bool isSameObjectAs(const LLNotification* rhs) const
+ {
+ return this == rhs;
+ }
+
+ // this object has been updated, so tell all our clients
+ void update();
+
+ void updateFrom(LLNotificationPtr other);
+
+ // A fuzzy equals comparator.
+ // true only if both notifications have the same template and
+ // 1) flagged as unique (there can be only one of these) OR
+ // 2) all required payload fields of each also exist in the other.
+ bool isEquivalentTo(LLNotificationPtr that) const;
+
+ // if the current time is greater than the expiration, the notification is expired
+ bool isExpired() const
+ {
+ if (mExpiresAt.secondsSinceEpoch() == 0)
+ {
+ return false;
+ }
+
+ LLDate rightnow = LLDate::now();
+ return rightnow > mExpiresAt;
+ }
+
+ std::string summarize() const;
+
+ bool hasUniquenessConstraints() const { return (mTemplatep ? mTemplatep->mUnique : false);}
+
+ virtual ~LLNotification() {}
+};
+
+std::ostream& operator<<(std::ostream& s, const LLNotification& notification);
+
+namespace LLNotificationFilters
+{
+ // a sample filter
+ bool includeEverything(LLNotificationPtr p);
+
+ typedef enum e_comparison
+ {
+ EQUAL,
+ LESS,
+ GREATER,
+ LESS_EQUAL,
+ GREATER_EQUAL
+ } EComparison;
+
+ // generic filter functor that takes method or member variable reference
+ template<typename T>
+ struct filterBy
+ {
+ typedef boost::function<T (LLNotificationPtr)> field_t;
+ typedef typename boost::remove_reference<T>::type value_t;
+
+ filterBy(field_t field, value_t value, EComparison comparison = EQUAL)
+ : mField(field),
+ mFilterValue(value),
+ mComparison(comparison)
+ {
+ }
+
+ bool operator()(LLNotificationPtr p)
+ {
+ switch(mComparison)
+ {
+ case EQUAL:
+ return mField(p) == mFilterValue;
+ case LESS:
+ return mField(p) < mFilterValue;
+ case GREATER:
+ return mField(p) > mFilterValue;
+ case LESS_EQUAL:
+ return mField(p) <= mFilterValue;
+ case GREATER_EQUAL:
+ return mField(p) >= mFilterValue;
+ default:
+ return false;
+ }
+ }
+
+ field_t mField;
+ value_t mFilterValue;
+ EComparison mComparison;
+ };
+};
+
+namespace LLNotificationComparators
+{
+ typedef enum e_direction { ORDER_DECREASING, ORDER_INCREASING } EDirection;
+
+ // generic order functor that takes method or member variable reference
+ template<typename T>
+ struct orderBy
+ {
+ typedef boost::function<T (LLNotificationPtr)> field_t;
+ orderBy(field_t field, EDirection = ORDER_INCREASING) : mField(field) {}
+ bool operator()(LLNotificationPtr lhs, LLNotificationPtr rhs)
+ {
+ if (mDirection == ORDER_DECREASING)
+ {
+ return mField(lhs) > mField(rhs);
+ }
+ else
+ {
+ return mField(lhs) < mField(rhs);
+ }
+ }
+
+ field_t mField;
+ EDirection mDirection;
+ };
+
+ struct orderByUUID : public orderBy<const LLUUID&>
+ {
+ orderByUUID(EDirection direction = ORDER_INCREASING) : orderBy<const LLUUID&>(&LLNotification::id, direction) {}
+ };
+
+ struct orderByDate : public orderBy<const LLDate&>
+ {
+ orderByDate(EDirection direction = ORDER_INCREASING) : orderBy<const LLDate&>(&LLNotification::getDate, direction) {}
+ };
+};
+
+typedef boost::function<bool (LLNotificationPtr)> LLNotificationFilter;
+typedef boost::function<bool (LLNotificationPtr, LLNotificationPtr)> LLNotificationComparator;
+typedef std::set<LLNotificationPtr, LLNotificationComparator> LLNotificationSet;
+typedef std::multimap<std::string, LLNotificationPtr> LLNotificationMap;
+
+// ========================================================
+// Abstract base class (interface) for a channel; also used for the master container.
+// This lets us arrange channels into a call hierarchy.
+
+// We maintain a heirarchy of notification channels; events are always started at the top
+// and propagated through the hierarchy only if they pass a filter.
+// Any channel can be created with a parent. A null parent (empty string) means it's
+// tied to the root of the tree (the LLNotifications class itself).
+// The default hierarchy looks like this:
+//
+// LLNotifications --+-- Expiration --+-- Mute --+-- Ignore --+-- Visible --+-- History
+// +-- Alerts
+// +-- Notifications
+//
+// In general, new channels that want to only see notifications that pass through
+// all of the built-in tests should attach to the "Visible" channel
+//
+class LLNotificationChannelBase :
+ public boost::signals::trackable
+{
+ LOG_CLASS(LLNotificationChannelBase);
+public:
+ LLNotificationChannelBase(LLNotificationFilter filter, LLNotificationComparator comp) :
+ mFilter(filter), mItems(comp)
+ {}
+ virtual ~LLNotificationChannelBase() {}
+ // you can also connect to a Channel, so you can be notified of
+ // changes to this channel
+ virtual void connectChanged(const LLStandardSignal::slot_type& slot);
+ virtual void connectPassedFilter(const LLStandardSignal::slot_type& slot);
+ virtual void connectFailedFilter(const LLStandardSignal::slot_type& slot);
+
+ // use this when items change or to add a new one
+ bool updateItem(const LLSD& payload);
+ const LLNotificationFilter& getFilter() { return mFilter; }
+
+protected:
+ LLNotificationSet mItems;
+ LLStandardSignal mChanged;
+ LLStandardSignal mPassedFilter;
+ LLStandardSignal mFailedFilter;
+
+ // these are action methods that subclasses can override to take action
+ // on specific types of changes; the management of the mItems list is
+ // still handled by the generic handler.
+ virtual void onLoad(LLNotificationPtr p) {}
+ virtual void onAdd(LLNotificationPtr p) {}
+ virtual void onDelete(LLNotificationPtr p) {}
+ virtual void onChange(LLNotificationPtr p) {}
+
+ bool updateItem(const LLSD& payload, LLNotificationPtr pNotification);
+ LLNotificationFilter mFilter;
+};
+
+// manages a list of notifications
+// Note that if this is ever copied around, we might find ourselves with multiple copies
+// of a queue with notifications being added to different nonequivalent copies. So we
+// make it inherit from boost::noncopyable, and then create a map of shared_ptr to manage it.
+//
+// NOTE: LLNotificationChannel is self-registering. The *correct* way to create one is to
+// do something like:
+// new LLNotificationChannel("name", "parent"...);
+// You can then retrieve the channel by using the registry:
+// LLNotifications::instance().getChannel("name")...
+//
+class LLNotificationChannel :
+ boost::noncopyable,
+ public LLNotificationChannelBase
+{
+ LOG_CLASS(LLNotificationChannel);
+
+public:
+ virtual ~LLNotificationChannel() {}
+ // Notification Channels have a filter, which determines which notifications
+ // will be added to this channel.
+ // Channel filters cannot change.
+ LLNotificationChannel(const std::string& name, const std::string& parent,
+ LLNotificationFilter filter=LLNotificationFilters::includeEverything,
+ LLNotificationComparator comparator=LLNotificationComparators::orderByUUID());
+
+ typedef LLNotificationSet::iterator Iterator;
+
+ std::string getName() const { return mName; }
+ std::string getParentChannelName() { return mParent; }
+
+ bool isEmpty() const;
+
+ Iterator begin();
+ Iterator end();
+
+ // Channels have a comparator to control sort order;
+ // the default sorts by arrival date
+ void setComparator(LLNotificationComparator comparator);
+
+ std::string summarize();
+
+private:
+ std::string mName;
+ std::string mParent;
+ LLNotificationComparator mComparator;
+};
+
+
+
+// The type of the pointers that we're going to manage in the NotificationQueue system
+// Because LLNotifications is a singleton, we don't actually expect to ever
+// destroy it, but if it becomes necessary to do so, the shared_ptr model
+// will ensure that we don't leak resources.
+typedef boost::shared_ptr<LLNotificationChannel> LLNotificationChannelPtr;
+
+class LLNotifications :
+ public LLSingleton<LLNotifications>,
+ public LLNotificationChannelBase
+{
+ LOG_CLASS(LLNotifications);
+
+ friend class LLSingleton<LLNotifications>;
+public:
+ // load notification descriptions from file;
+ // OK to call more than once because it will reload
+ bool loadTemplates();
+ LLXMLNodePtr checkForXMLTemplate(LLXMLNodePtr item);
+
+ // we provide a collection of simple add notification functions so that it's reasonable to create notifications in one line
+ LLNotificationPtr add(const std::string& name,
+ const LLSD& substitutions = LLSD(),
+ const LLSD& payload = LLSD());
+ LLNotificationPtr add(const std::string& name,
+ const LLSD& substitutions,
+ const LLSD& payload,
+ const std::string& functor_name);
+ LLNotificationPtr add(const std::string& name,
+ const LLSD& substitutions,
+ const LLSD& payload,
+ LLNotificationFunctorRegistry::ResponseFunctor functor);
+ LLNotificationPtr add(const LLNotification::Params& p);
+
+ void add(const LLNotificationPtr pNotif);
+ void cancel(LLNotificationPtr pNotif);
+ void update(const LLNotificationPtr pNotif);
+
+ LLNotificationPtr find(LLUUID uuid);
+
+ typedef boost::function<void (LLNotificationPtr)> NotificationProcess;
+
+ void forEachNotification(NotificationProcess process);
+
+ // This is all stuff for managing the templates
+ // take your template out
+ LLNotificationTemplatePtr getTemplate(const std::string& name);
+
+ // get the whole collection
+ typedef std::vector<std::string> TemplateNames;
+ TemplateNames getTemplateNames() const; // returns a list of notification names
+
+ typedef std::map<std::string, LLNotificationTemplatePtr> TemplateMap;
+
+ TemplateMap::const_iterator templatesBegin() { return mTemplates.begin(); }
+ TemplateMap::const_iterator templatesEnd() { return mTemplates.end(); }
+
+ // test for existence
+ bool templateExists(const std::string& name);
+ // useful if you're reloading the file
+ void clearTemplates(); // erase all templates
+
+ void forceResponse(const LLNotification::Params& params, S32 option);
+
+ void createDefaultChannels();
+
+ typedef std::map<std::string, LLNotificationChannelPtr> ChannelMap;
+ ChannelMap mChannels;
+
+ void addChannel(LLNotificationChannelPtr pChan);
+ LLNotificationChannelPtr getChannel(const std::string& channelName);
+
+ std::string getGlobalString(const std::string& key) const;
+
+private:
+ // we're a singleton, so we don't have a public constructor
+ LLNotifications();
+ /*virtual*/ void initSingleton();
+
+ void loadPersistentNotifications();
+
+ bool expirationFilter(LLNotificationPtr pNotification);
+ bool expirationHandler(const LLSD& payload);
+ bool uniqueFilter(LLNotificationPtr pNotification);
+ bool uniqueHandler(const LLSD& payload);
+ bool failedUniquenessTest(const LLSD& payload);
+ LLNotificationChannelPtr pHistoryChannel;
+ LLNotificationChannelPtr pExpirationChannel;
+
+ // put your template in
+ bool addTemplate(const std::string& name, LLNotificationTemplatePtr theTemplate);
+ TemplateMap mTemplates;
+
+ std::string mFileName;
+
+ typedef std::map<std::string, LLXMLNodePtr> XMLTemplateMap;
+ XMLTemplateMap mXmlTemplates;
+
+ LLNotificationMap mUniqueNotifications;
+
+ typedef std::map<std::string, std::string> GlobalStringMap;
+ GlobalStringMap mGlobalStrings;
+};
+
+
+#endif//LL_LLNOTIFICATIONS_H
+
diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp
index 22934450e7..2edbbe6abc 100644
--- a/indra/llui/llpanel.cpp
+++ b/indra/llui/llpanel.cpp
@@ -58,8 +58,6 @@
#include "llresizebar.h"
#include "llcriticaldamp.h"
-LLPanel::alert_queue_t LLPanel::sAlertQueue;
-
const S32 RESIZE_BAR_OVERLAP = 1;
const S32 RESIZE_BAR_HEIGHT = 3;
@@ -344,14 +342,14 @@ BOOL LLPanel::checkRequirements()
{
if (!mRequirementsError.empty())
{
- LLStringUtil::format_map_t args;
- args["[COMPONENTS]"] = mRequirementsError;
- args["[FLOATER]"] = getName();
+ LLSD args;
+ args["COMPONENTS"] = mRequirementsError;
+ args["FLOATER"] = getName();
llwarns << getName() << " failed requirements check on: \n"
<< mRequirementsError << llendl;
-
- alertXml(std::string("FailedRequirementsCheck"), args);
+
+ LLNotifications::instance().add(LLNotification::Params("FailedRequirementsCheck").payload(args));
mRequirementsError.clear();
return FALSE;
}
@@ -359,25 +357,6 @@ BOOL LLPanel::checkRequirements()
return TRUE;
}
-//static
-void LLPanel::alertXml(const std::string& label, LLStringUtil::format_map_t args)
-{
- sAlertQueue.push(LLAlertInfo(label,args));
-}
-
-//static
-BOOL LLPanel::nextAlert(LLAlertInfo &alert)
-{
- if (!sAlertQueue.empty())
- {
- alert = sAlertQueue.front();
- sAlertQueue.pop();
- return TRUE;
- }
-
- return FALSE;
-}
-
void LLPanel::setFocus(BOOL b)
{
if( b )
@@ -1039,9 +1018,9 @@ void LLPanel::childDisplayNotFound()
mExpectedMembers.insert(*itor);
}
mNewExpectedMembers.clear();
- LLStringUtil::format_map_t args;
- args["[CONTROLS]"] = msg;
- LLAlertDialog::showXml("FloaterNotFound", args);
+ LLSD args;
+ args["CONTROLS"] = msg;
+ LLNotifications::instance().add("FloaterNotFound", args);
}
void LLPanel::storeRectControl()
@@ -1065,6 +1044,8 @@ struct LLLayoutStack::LLEmbeddedPanel
mAutoResize(auto_resize),
mUserResize(user_resize),
mOrientation(orientation),
+ mCollapsed(FALSE),
+ mCollapseAmt(0.f),
mVisibleAmt(1.f) // default to fully visible
{
LLResizeBar::Side side = (orientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM;
@@ -1095,14 +1076,28 @@ struct LLLayoutStack::LLEmbeddedPanel
mResizeBar = NULL;
}
+ F32 getCollapseFactor()
+ {
+ if (mOrientation == HORIZONTAL)
+ {
+ return mVisibleAmt * clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, (F32)mMinWidth / (F32)mPanel->getRect().getWidth());
+ }
+ else
+ {
+ return mVisibleAmt * clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, (F32)mMinHeight / (F32)mPanel->getRect().getHeight());
+ }
+ }
+
LLPanel* mPanel;
S32 mMinWidth;
S32 mMinHeight;
BOOL mAutoResize;
BOOL mUserResize;
+ BOOL mCollapsed;
LLResizeBar* mResizeBar;
eLayoutOrientation mOrientation;
F32 mVisibleAmt;
+ F32 mCollapseAmt;
};
static LLRegisterWidget<LLLayoutStack> r2("layout_stack");
@@ -1123,28 +1118,27 @@ LLLayoutStack::~LLLayoutStack()
void LLLayoutStack::draw()
{
updateLayout();
+
+ e_panel_list_t::iterator panel_it;
+ for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
{
- e_panel_list_t::iterator panel_it;
- for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
+ // clip to layout rectangle, not bounding rectangle
+ LLRect clip_rect = (*panel_it)->mPanel->getRect();
+ // scale clipping rectangle by visible amount
+ if (mOrientation == HORIZONTAL)
{
- // clip to layout rectangle, not bounding rectangle
- LLRect clip_rect = (*panel_it)->mPanel->getRect();
- // scale clipping rectangle by visible amount
- if (mOrientation == HORIZONTAL)
- {
- clip_rect.mRight = clip_rect.mLeft + llround((F32)clip_rect.getWidth() * (*panel_it)->mVisibleAmt);
- }
- else
- {
- clip_rect.mBottom = clip_rect.mTop - llround((F32)clip_rect.getHeight() * (*panel_it)->mVisibleAmt);
- }
+ clip_rect.mRight = clip_rect.mLeft + llround((F32)clip_rect.getWidth() * (*panel_it)->getCollapseFactor());
+ }
+ else
+ {
+ clip_rect.mBottom = clip_rect.mTop - llround((F32)clip_rect.getHeight() * (*panel_it)->getCollapseFactor());
+ }
- LLPanel* panelp = (*panel_it)->mPanel;
+ LLPanel* panelp = (*panel_it)->mPanel;
- LLLocalClipRect clip(clip_rect);
- // only force drawing invisible children if visible amount is non-zero
- drawChild(panelp, 0, 0, !clip_rect.isNull());
- }
+ LLLocalClipRect clip(clip_rect);
+ // only force drawing invisible children if visible amount is non-zero
+ drawChild(panelp, 0, 0, !clip_rect.isNull());
}
}
@@ -1276,8 +1270,13 @@ S32 LLLayoutStack::getDefaultWidth(S32 cur_width)
return cur_width;
}
-void LLLayoutStack::addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize, S32 index)
+void LLLayoutStack::addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize, EAnimate animate, S32 index)
{
+ // panel starts off invisible (collapsed)
+ if (animate == ANIMATE)
+ {
+ panel->setVisible(FALSE);
+ }
LLEmbeddedPanel* embedded_panel = new LLEmbeddedPanel(panel, mOrientation, min_width, min_height, auto_resize, user_resize);
mPanels.insert(mPanels.begin() + llclamp(index, 0, (S32)mPanels.size()), embedded_panel);
@@ -1293,6 +1292,11 @@ void LLLayoutStack::addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL
sendChildToFront(resize_barp);
}
+ // start expanding panel animation
+ if (animate == ANIMATE)
+ {
+ panel->setVisible(TRUE);
+ }
}
void LLLayoutStack::removePanel(LLPanel* panel)
@@ -1300,6 +1304,14 @@ void LLLayoutStack::removePanel(LLPanel* panel)
removeChild(panel);
}
+void LLLayoutStack::collapsePanel(LLPanel* panel, BOOL collapsed)
+{
+ LLEmbeddedPanel* panel_container = findEmbeddedPanel(panel);
+ if (!panel_container) return;
+
+ panel_container->mCollapsed = collapsed;
+}
+
void LLLayoutStack::updateLayout(BOOL force_resize)
{
calcMinExtents();
@@ -1332,6 +1344,15 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
}
}
+ if ((*panel_it)->mCollapsed)
+ {
+ (*panel_it)->mCollapseAmt = lerp((*panel_it)->mCollapseAmt, 1.f, LLCriticalDamp::getInterpolant(ANIM_CLOSE_TIME));
+ }
+ else
+ {
+ (*panel_it)->mCollapseAmt = lerp((*panel_it)->mCollapseAmt, 0.f, LLCriticalDamp::getInterpolant(ANIM_CLOSE_TIME));
+ }
+
if (mOrientation == HORIZONTAL)
{
// enforce minimize size constraint by default
@@ -1339,7 +1360,7 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
{
panelp->reshape((*panel_it)->mMinWidth, panelp->getRect().getHeight());
}
- total_width += llround(panelp->getRect().getWidth() * (*panel_it)->mVisibleAmt);
+ total_width += llround(panelp->getRect().getWidth() * (*panel_it)->getCollapseFactor());
// want n-1 panel gaps for n panels
if (panel_it != mPanels.begin())
{
@@ -1353,7 +1374,7 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
{
panelp->reshape(panelp->getRect().getWidth(), (*panel_it)->mMinHeight);
}
- total_height += llround(panelp->getRect().getHeight() * (*panel_it)->mVisibleAmt);
+ total_height += llround(panelp->getRect().getHeight() * (*panel_it)->getCollapseFactor());
if (panel_it != mPanels.begin())
{
total_height += mPanelSpacing;
@@ -1367,7 +1388,7 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it)
{
// panels that are not fully visible do not count towards shrink headroom
- if ((*panel_it)->mVisibleAmt < 1.f)
+ if ((*panel_it)->getCollapseFactor() < 1.f)
{
continue;
}
@@ -1431,7 +1452,7 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
S32 delta_size = 0;
// if panel can automatically resize (not animating, and resize flag set)...
- if ((*panel_it)->mVisibleAmt == 1.f
+ if ((*panel_it)->getCollapseFactor() == 1.f
&& (force_resize || (*panel_it)->mAutoResize)
&& !(*panel_it)->mResizeBar->hasMouseCapture())
{
@@ -1515,11 +1536,11 @@ void LLLayoutStack::updateLayout(BOOL force_resize)
if (mOrientation == HORIZONTAL)
{
- cur_x += llround(new_width * (*panel_it)->mVisibleAmt) + mPanelSpacing;
+ cur_x += llround(new_width * (*panel_it)->getCollapseFactor()) + mPanelSpacing;
}
else //VERTICAL
{
- cur_y -= llround(new_height * (*panel_it)->mVisibleAmt) + mPanelSpacing;
+ cur_y -= llround(new_height * (*panel_it)->getCollapseFactor()) + mPanelSpacing;
}
}
diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h
index c55eb6bba2..da876667e6 100644
--- a/indra/llui/llpanel.h
+++ b/indra/llui/llpanel.h
@@ -49,23 +49,13 @@ const BOOL BORDER_YES = TRUE;
const BOOL BORDER_NO = FALSE;
-struct LLAlertInfo
-{
- std::string mLabel;
- LLStringUtil::format_map_t mArgs;
-
- LLAlertInfo(std::string label, LLStringUtil::format_map_t args) : mLabel(label), mArgs(args) { }
- LLAlertInfo(){}
-};
-
-
/*
* General purpose concrete view base class.
* Transparent or opaque,
* With or without border,
* Can contain LLUICtrls.
*/
-class LLPanel : public LLUICtrl
+class LLPanel : public LLUICtrl, public boost::signals::trackable
{
public:
@@ -227,8 +217,6 @@ public:
void childNotFound(const std::string& id) const;
void childDisplayNotFound();
- static void alertXml(const std::string& label, LLStringUtil::format_map_t args = LLStringUtil::format_map_t());
- static BOOL nextAlert(LLAlertInfo &alert);
static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory);
protected:
@@ -266,8 +254,6 @@ private:
std::string mRequirementsError;
- typedef std::queue<LLAlertInfo> alert_queue_t;
- static alert_queue_t sAlertQueue;
}; // end class LLPanel
@@ -292,8 +278,16 @@ public:
S32 getMinWidth() const { return mMinWidth; }
S32 getMinHeight() const { return mMinHeight; }
- void addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize, S32 index = S32_MAX);
+ typedef enum e_animate
+ {
+ NO_ANIMATE,
+ ANIMATE
+ } EAnimate;
+
+ void addPanel(LLPanel* panel, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize, EAnimate animate = NO_ANIMATE, S32 index = S32_MAX);
void removePanel(LLPanel* panel);
+ void collapsePanel(LLPanel* panel, BOOL collapsed = TRUE);
+ S32 getNumPanels() { return mPanels.size(); }
private:
struct LLEmbeddedPanel;
diff --git a/indra/llui/llscrollbar.cpp b/indra/llui/llscrollbar.cpp
index a7163323bd..734b3ab381 100644
--- a/indra/llui/llscrollbar.cpp
+++ b/indra/llui/llscrollbar.cpp
@@ -127,6 +127,8 @@ LLScrollbar::LLScrollbar(
}
line_up_btn->setHeldDownCallback( &LLScrollbar::onLineUpBtnPressed );
line_up_btn->setTabStop(FALSE);
+ line_up_btn->setScaleImage(TRUE);
+
addChild(line_up_btn);
LLButton* line_down_btn = new LLButton(std::string("Line Down"), line_down_rect,
@@ -136,6 +138,7 @@ LLScrollbar::LLScrollbar(
line_down_btn->setFollowsBottom();
line_down_btn->setHeldDownCallback( &LLScrollbar::onLineDownBtnPressed );
line_down_btn->setTabStop(FALSE);
+ line_down_btn->setScaleImage(TRUE);
addChild(line_down_btn);
}
@@ -148,20 +151,29 @@ LLScrollbar::~LLScrollbar()
void LLScrollbar::setDocParams( S32 size, S32 pos )
{
mDocSize = size;
- mDocPos = llclamp( pos, 0, getDocPosMax() );
+ setDocPos(pos);
mDocChanged = TRUE;
updateThumbRect();
}
-void LLScrollbar::setDocPos(S32 pos)
+void LLScrollbar::setDocPos(S32 pos, BOOL update_thumb)
{
+ pos = llclamp(pos, 0, getDocPosMax());
if (pos != mDocPos)
{
- mDocPos = llclamp( pos, 0, getDocPosMax() );
+ mDocPos = pos;
mDocChanged = TRUE;
- updateThumbRect();
+ if( mChangeCallback )
+ {
+ mChangeCallback( mDocPos, this, mCallbackUserData );
+ }
+
+ if( update_thumb )
+ {
+ updateThumbRect();
+ }
}
}
@@ -170,7 +182,7 @@ void LLScrollbar::setDocSize(S32 size)
if (size != mDocSize)
{
mDocSize = size;
- mDocPos = llclamp( mDocPos, 0, getDocPosMax() );
+ setDocPos(mDocPos);
mDocChanged = TRUE;
updateThumbRect();
@@ -182,7 +194,7 @@ void LLScrollbar::setPageSize( S32 page_size )
if (page_size != mPageSize)
{
mPageSize = page_size;
- mDocPos = llclamp( mDocPos, 0, getDocPosMax() );
+ setDocPos(mDocPos);
mDocChanged = TRUE;
updateThumbRect();
@@ -208,9 +220,9 @@ void LLScrollbar::updateThumbRect()
const S32 THUMB_MIN_LENGTH = 16;
S32 window_length = (mOrientation == LLScrollbar::HORIZONTAL) ? getRect().getWidth() : getRect().getHeight();
- S32 thumb_bg_length = window_length - 2 * SCROLLBAR_SIZE;
+ S32 thumb_bg_length = llmax(0, window_length - 2 * SCROLLBAR_SIZE);
S32 visible_lines = llmin( mDocSize, mPageSize );
- S32 thumb_length = mDocSize ? llmax( visible_lines * thumb_bg_length / mDocSize, THUMB_MIN_LENGTH ) : thumb_bg_length;
+ S32 thumb_length = mDocSize ? llmin(llmax( visible_lines * thumb_bg_length / mDocSize, THUMB_MIN_LENGTH), thumb_bg_length) : thumb_bg_length;
S32 variable_lines = mDocSize - visible_lines;
@@ -218,7 +230,7 @@ void LLScrollbar::updateThumbRect()
{
S32 thumb_start_max = thumb_bg_length + SCROLLBAR_SIZE;
S32 thumb_start_min = SCROLLBAR_SIZE + THUMB_MIN_LENGTH;
- S32 thumb_start = variable_lines ? llclamp( thumb_start_max - (mDocPos * (thumb_bg_length - thumb_length)) / variable_lines, thumb_start_min, thumb_start_max ) : thumb_start_max;
+ S32 thumb_start = variable_lines ? llmin( llmax(thumb_start_max - (mDocPos * (thumb_bg_length - thumb_length)) / variable_lines, thumb_start_min), thumb_start_max ) : thumb_start_max;
mThumbRect.mLeft = 0;
mThumbRect.mTop = thumb_start;
@@ -230,7 +242,7 @@ void LLScrollbar::updateThumbRect()
// Horizontal
S32 thumb_start_max = thumb_bg_length + SCROLLBAR_SIZE - thumb_length;
S32 thumb_start_min = SCROLLBAR_SIZE;
- S32 thumb_start = variable_lines ? llclamp( thumb_start_min + (mDocPos * (thumb_bg_length - thumb_length)) / variable_lines, thumb_start_min, thumb_start_max ) : thumb_start_min;
+ S32 thumb_start = variable_lines ? llmin(llmax( thumb_start_min + (mDocPos * (thumb_bg_length - thumb_length)) / variable_lines, thumb_start_min), thumb_start_max ) : thumb_start_min;
mThumbRect.mLeft = thumb_start;
mThumbRect.mTop = SCROLLBAR_SIZE;
@@ -446,7 +458,7 @@ BOOL LLScrollbar::handleMouseUp(S32 x, S32 y, MASK mask)
}
else
{
- // Opaque, so don't just check children
+ // Opaque, so don't just check children
handled = LLView::handleMouseUp( x, y, mask );
}
@@ -455,13 +467,31 @@ BOOL LLScrollbar::handleMouseUp(S32 x, S32 y, MASK mask)
void LLScrollbar::reshape(S32 width, S32 height, BOOL called_from_parent)
{
+ if (width == getRect().getWidth() && height == getRect().getHeight()) return;
LLView::reshape( width, height, called_from_parent );
+ LLButton* up_button = getChild<LLButton>("Line Up");
+ LLButton* down_button = getChild<LLButton>("Line Down");
+
+ if (mOrientation == VERTICAL)
+ {
+ up_button->reshape(up_button->getRect().getWidth(), llmin(getRect().getHeight() / 2, SCROLLBAR_SIZE));
+ down_button->reshape(down_button->getRect().getWidth(), llmin(getRect().getHeight() / 2, SCROLLBAR_SIZE));
+ up_button->setOrigin(up_button->getRect().mLeft, getRect().getHeight() - up_button->getRect().getHeight());
+ }
+ else
+ {
+ up_button->reshape(llmin(getRect().getWidth() / 2, SCROLLBAR_SIZE), up_button->getRect().getHeight());
+ down_button->reshape(llmin(getRect().getWidth() / 2, SCROLLBAR_SIZE), down_button->getRect().getHeight());
+ down_button->setOrigin(getRect().getWidth() - down_button->getRect().getWidth(), down_button->getRect().mBottom);
+ }
updateThumbRect();
}
void LLScrollbar::draw()
{
+ if (!getRect().isValid()) return;
+
S32 local_mouse_x;
S32 local_mouse_y;
LLUI::getCursorPositionLocal(this, &local_mouse_x, &local_mouse_y);
@@ -531,21 +561,7 @@ void LLScrollbar::draw()
void LLScrollbar::changeLine( S32 delta, BOOL update_thumb )
{
- S32 new_pos = llclamp( mDocPos + delta, 0, getDocPosMax() );
- if( new_pos != mDocPos )
- {
- mDocPos = new_pos;
- }
-
- if( mChangeCallback )
- {
- mChangeCallback( mDocPos, this, mCallbackUserData );
- }
-
- if( update_thumb )
- {
- updateThumbRect();
- }
+ setDocPos(mDocPos + delta, update_thumb);
}
void LLScrollbar::setValue(const LLSD& value)
@@ -561,22 +577,22 @@ BOOL LLScrollbar::handleKeyHere(KEY key, MASK mask)
switch( key )
{
case KEY_HOME:
- changeLine( -mDocPos, TRUE );
+ setDocPos( 0 );
handled = TRUE;
break;
case KEY_END:
- changeLine( getDocPosMax() - mDocPos, TRUE );
+ setDocPos( getDocPosMax() );
handled = TRUE;
break;
case KEY_DOWN:
- changeLine( mStepSize, TRUE );
+ setDocPos( getDocPos() + mStepSize );
handled = TRUE;
break;
case KEY_UP:
- changeLine( - mStepSize, TRUE );
+ setDocPos( getDocPos() - mStepSize );
handled = TRUE;
break;
diff --git a/indra/llui/llscrollbar.h b/indra/llui/llscrollbar.h
index d35dc10bd4..5fdacd43f8 100644
--- a/indra/llui/llscrollbar.h
+++ b/indra/llui/llscrollbar.h
@@ -81,7 +81,7 @@ public:
// How many "lines" the "document" has scrolled.
// 0 <= DocPos <= DocSize - DocVisibile
- void setDocPos( S32 pos );
+ void setDocPos( S32 pos, BOOL update_thumb = TRUE );
S32 getDocPos() const { return mDocPos; }
BOOL isAtBeginning();
diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp
index c0f21ba9e5..ea0c6d4b2f 100644
--- a/indra/llui/llscrolllistctrl.cpp
+++ b/indra/llui/llscrolllistctrl.cpp
@@ -378,6 +378,22 @@ void LLScrollListText::draw(const LLColor4& color, const LLColor4& highlight_col
TRUE);
}
+LLScrollListDate::LLScrollListDate( const LLDate& date, const LLFontGL* font, S32 width, U8 font_style, LLFontGL::HAlign font_alignment, LLColor4& color, BOOL use_color, BOOL visible)
+: LLScrollListText(date.asRFC1123(), font, width, font_style, font_alignment, color, use_color, visible),
+ mDate(date)
+{
+}
+
+void LLScrollListDate::setValue(const LLSD& value)
+{
+ mDate = value.asDate();
+ LLScrollListText::setValue(mDate.asRFC1123());
+}
+
+const LLSD LLScrollListDate::getValue() const
+{
+ return mDate;
+}
LLScrollListItem::~LLScrollListItem()
{
@@ -578,6 +594,7 @@ LLScrollListCtrl::LLScrollListCtrl(const std::string& name, const LLRect& rect,
mSearchColumn(0),
mNumDynamicWidthColumns(0),
mTotalStaticColumnWidth(0),
+ mTotalColumnPadding(0),
mSorted(TRUE),
mDirty(FALSE),
mOriginalSelection(-1),
@@ -627,6 +644,28 @@ LLScrollListCtrl::LLScrollListCtrl(const std::string& name, const LLRect& rect,
mLastSelected = NULL;
}
+S32 LLScrollListCtrl::getSearchColumn()
+{
+ // search for proper search column
+ if (mSearchColumn < 0)
+ {
+ LLScrollListItem* itemp = getFirstData();
+ if (itemp)
+ {
+ for(S32 column = 0; column < getNumColumns(); column++)
+ {
+ LLScrollListCell* cell = itemp->getColumn(column);
+ if (cell && cell->isText())
+ {
+ mSearchColumn = column;
+ break;
+ }
+ }
+ }
+ }
+ return llclamp(mSearchColumn, 0, getNumColumns());
+}
+
LLScrollListCtrl::~LLScrollListCtrl()
{
std::for_each(mItemList.begin(), mItemList.end(), DeletePointer());
@@ -890,8 +929,8 @@ BOOL LLScrollListCtrl::addItem( LLScrollListItem* item, EAddPosition pos, BOOL r
// *TODO: Use bookkeeping to make this an incramental cost with item additions
void LLScrollListCtrl::calcColumnWidths()
{
- const S32 HEADING_TEXT_PADDING = 30;
- const S32 COLUMN_TEXT_PADDING = 20;
+ const S32 HEADING_TEXT_PADDING = 25;
+ const S32 COLUMN_TEXT_PADDING = 10;
mMaxContentWidth = 0;
@@ -904,20 +943,17 @@ void LLScrollListCtrl::calcColumnWidths()
if (!column) continue;
// update column width
- S32 new_width = column->mWidth;
+ S32 new_width = column->getWidth();
if (column->mRelWidth >= 0)
{
new_width = (S32)llround(column->mRelWidth*mItemListRect.getWidth());
}
else if (column->mDynamicWidth)
{
- new_width = (mItemListRect.getWidth() - mTotalStaticColumnWidth) / mNumDynamicWidthColumns;
+ new_width = (mItemListRect.getWidth() - mTotalStaticColumnWidth - mTotalColumnPadding) / mNumDynamicWidthColumns;
}
- if (new_width != column->mWidth)
- {
- column->mWidth = new_width;
- }
+ column->setWidth(new_width);
// update max content width for this column, by looking at all items
column->mMaxContentWidth = column->mHeader ? LLFontGL::sSansSerifSmall->getWidth(column->mLabel) + mColumnPadding + HEADING_TEXT_PADDING : 0;
@@ -971,28 +1007,13 @@ void LLScrollListCtrl::updateColumns()
{
calcColumnWidths();
- // propagate column widths to individual cells
- item_list::iterator iter;
- for (iter = mItemList.begin(); iter != mItemList.end(); iter++)
- {
- LLScrollListItem *itemp = *iter;
- S32 num_cols = itemp->getNumColumns();
- S32 i = 0;
- for (LLScrollListCell* cell = itemp->getColumn(i); i < num_cols; cell = itemp->getColumn(++i))
- {
- if (i >= (S32)mColumnsIndexed.size()) break;
-
- cell->setWidth(mColumnsIndexed[i]->mWidth);
- }
- }
-
// update column headers
std::vector<LLScrollListColumn*>::iterator column_ordered_it;
S32 left = mItemListRect.mLeft;
LLColumnHeader* last_header = NULL;
for (column_ordered_it = mColumnsIndexed.begin(); column_ordered_it != mColumnsIndexed.end(); ++column_ordered_it)
{
- if ((*column_ordered_it)->mWidth < 0)
+ if ((*column_ordered_it)->getWidth() < 0)
{
// skip hidden columns
continue;
@@ -1001,9 +1022,11 @@ void LLScrollListCtrl::updateColumns()
if (column->mHeader)
{
+ column->mHeader->updateResizeBars();
+
last_header = column->mHeader;
S32 top = mItemListRect.mTop;
- S32 right = left + column->mWidth;
+ S32 right = left + column->getWidth();
if (column->mIndex != (S32)mColumnsIndexed.size()-1)
{
@@ -1021,14 +1044,30 @@ void LLScrollListCtrl::updateColumns()
}
}
- //FIXME: stretch the entire last column if it is resizable (gestures windows shows truncated text in last column)
// expand last column header we encountered to full list width
- if (last_header)
+ if (last_header && last_header->canResize())
{
S32 new_width = llmax(0, mItemListRect.mRight - last_header->getRect().mLeft);
last_header->reshape(new_width, last_header->getRect().getHeight());
last_header->setVisible(mDisplayColumnHeaders && new_width > 0);
+ last_header->getColumn()->setWidth(new_width);
+ }
+
+ // propagate column widths to individual cells
+ item_list::iterator iter;
+ for (iter = mItemList.begin(); iter != mItemList.end(); iter++)
+ {
+ LLScrollListItem *itemp = *iter;
+ S32 num_cols = itemp->getNumColumns();
+ S32 i = 0;
+ for (LLScrollListCell* cell = itemp->getColumn(i); i < num_cols; cell = itemp->getColumn(++i))
+ {
+ if (i >= (S32)mColumnsIndexed.size()) break;
+
+ cell->setWidth(mColumnsIndexed[i]->getWidth());
+ }
}
+
}
void LLScrollListCtrl::setDisplayHeading(BOOL display)
@@ -1490,7 +1529,7 @@ BOOL LLScrollListCtrl::selectItemByPrefix(const LLWString& target, BOOL case_sen
{
LLScrollListItem* item = *iter;
// Only select enabled items with matching names
- LLScrollListCell* cellp = item->getColumn(mSearchColumn);
+ LLScrollListCell* cellp = item->getColumn(getSearchColumn());
BOOL select = cellp ? item->getEnabled() && ('\0' == cellp->getValue().asString()[0]) : FALSE;
if (select)
{
@@ -1513,7 +1552,7 @@ BOOL LLScrollListCtrl::selectItemByPrefix(const LLWString& target, BOOL case_sen
LLScrollListItem* item = *iter;
// Only select enabled items with matching names
- LLScrollListCell* cellp = item->getColumn(mSearchColumn);
+ LLScrollListCell* cellp = item->getColumn(getSearchColumn());
if (!cellp)
{
continue;
@@ -1743,6 +1782,8 @@ void LLScrollListCtrl::drawItems()
void LLScrollListCtrl::draw()
{
+ LLLocalClipRect clip(getLocalRect());
+
// if user specifies sort, make sure it is maintained
if (needsSorting() && !isSorted())
{
@@ -1816,7 +1857,7 @@ BOOL LLScrollListCtrl::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sti
S32 rect_left = getColumnOffsetFromIndex(column_index) + mItemListRect.mLeft;
S32 rect_bottom = getRowOffsetFromIndex(getItemIndex(hit_item));
LLRect cell_rect;
- cell_rect.setOriginAndSize(rect_left, rect_bottom, rect_left + columnp->mWidth, mLineHeight);
+ cell_rect.setOriginAndSize(rect_left, rect_bottom, rect_left + columnp->getWidth(), mLineHeight);
// Convert rect local to screen coordinates
localPointToScreen(
cell_rect.mLeft, cell_rect.mBottom,
@@ -2113,7 +2154,7 @@ S32 LLScrollListCtrl::getColumnIndexFromOffset(S32 x)
ordered_columns_t::const_iterator end = mColumnsIndexed.end();
for ( ; iter != end; ++iter)
{
- width = (*iter)->mWidth + mColumnPadding;
+ width = (*iter)->getWidth() + mColumnPadding;
right += width;
if (left <= x && x < right )
{
@@ -2140,7 +2181,7 @@ S32 LLScrollListCtrl::getColumnOffsetFromIndex(S32 index)
{
return column_offset;
}
- column_offset += (*iter)->mWidth + mColumnPadding;
+ column_offset += (*iter)->getWidth() + mColumnPadding;
}
// when running off the end, return the rightmost pixel
@@ -2292,7 +2333,7 @@ BOOL LLScrollListCtrl::handleKeyHere(KEY key,MASK mask )
{
if (getFirstSelected())
{
- LLScrollListCell* cellp = getFirstSelected()->getColumn(mSearchColumn);
+ LLScrollListCell* cellp = getFirstSelected()->getColumn(getSearchColumn());
if (cellp)
{
cellp->highlightText(0, 0);
@@ -2379,7 +2420,7 @@ BOOL LLScrollListCtrl::handleUnicodeCharHere(llwchar uni_char)
{
LLScrollListItem* item = *iter;
- LLScrollListCell* cellp = item->getColumn(mSearchColumn);
+ LLScrollListCell* cellp = item->getColumn(getSearchColumn());
if (cellp)
{
// Only select enabled items with matching first characters
@@ -2446,7 +2487,7 @@ void LLScrollListCtrl::selectItem(LLScrollListItem* itemp, BOOL select_single_it
{
if (mLastSelected)
{
- LLScrollListCell* cellp = mLastSelected->getColumn(mSearchColumn);
+ LLScrollListCell* cellp = mLastSelected->getColumn(getSearchColumn());
if (cellp)
{
cellp->highlightText(0, 0);
@@ -2474,7 +2515,7 @@ void LLScrollListCtrl::deselectItem(LLScrollListItem* itemp)
}
itemp->setSelected(FALSE);
- LLScrollListCell* cellp = itemp->getColumn(mSearchColumn);
+ LLScrollListCell* cellp = itemp->getColumn(getSearchColumn());
if (cellp)
{
cellp->highlightText(0, 0);
@@ -2501,9 +2542,14 @@ struct SameSortColumn
bool operator()(std::pair<S32, BOOL> sort_column) { return sort_column.first == mColumn; }
};
-BOOL LLScrollListCtrl::setSort(S32 column, BOOL ascending)
+BOOL LLScrollListCtrl::setSort(S32 column_idx, BOOL ascending)
{
- sort_column_t new_sort_column(column, ascending);
+ LLScrollListColumn* sort_column = getColumn(column_idx);
+ if (!sort_column) return FALSE;
+
+ sort_column->mSortAscending = ascending;
+
+ sort_column_t new_sort_column(column_idx, ascending);
if (mSortColumns.empty())
{
@@ -2517,7 +2563,7 @@ BOOL LLScrollListCtrl::setSort(S32 column, BOOL ascending)
// remove any existing sort criterion referencing this column
// and add the new one
- mSortColumns.erase(remove_if(mSortColumns.begin(), mSortColumns.end(), SameSortColumn(column)), mSortColumns.end());
+ mSortColumns.erase(remove_if(mSortColumns.begin(), mSortColumns.end(), SameSortColumn(column_idx)), mSortColumns.end());
mSortColumns.push_back(new_sort_column);
// did the sort criteria change?
@@ -2643,6 +2689,12 @@ void LLScrollListCtrl::scrollToShowSelected()
}
}
+void LLScrollListCtrl::updateStaticColumnWidth(LLScrollListColumn* col, S32 new_width)
+{
+ mTotalStaticColumnWidth += llmax(0, new_width) - llmax(0, col->getWidth());
+}
+
+
// virtual
LLXMLNodePtr LLScrollListCtrl::getXML(bool save_children) const
{
@@ -2689,7 +2741,7 @@ LLXMLNodePtr LLScrollListCtrl::getXML(bool save_children) const
child_node->createChild("name", TRUE)->setStringValue(column->mName);
child_node->createChild("label", TRUE)->setStringValue(column->mLabel);
- child_node->createChild("width", TRUE)->setIntValue(column->mWidth);
+ child_node->createChild("width", TRUE)->setIntValue(column->getWidth());
}
return node;
@@ -2813,15 +2865,9 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac
scroll_list->setSearchColumn(search_column);
- if (sort_column >= 0)
- {
- scroll_list->sortByColumnIndex(sort_column, sort_ascending);
- }
-
LLSD columns;
S32 index = 0;
LLXMLNodePtr child;
- S32 total_static = 0;
for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
{
if (child->hasName("column"))
@@ -2850,8 +2896,6 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac
std::string tooltip;
child->getAttributeString("tool_tip", tooltip);
- if(!columndynamicwidth) total_static += llmax(0, columnwidth);
-
F32 columnrelwidth = 0.f;
child->getAttributeF32("relwidth", columnrelwidth);
@@ -2872,9 +2916,13 @@ LLView* LLScrollListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac
index++;
}
}
- scroll_list->setTotalStaticColumnWidth(total_static);
scroll_list->setColumnHeadings(columns);
+ if (sort_column >= 0)
+ {
+ scroll_list->sortByColumnIndex(sort_column, sort_ascending);
+ }
+
for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
{
if (child->hasName("row"))
@@ -3019,22 +3067,26 @@ void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos)
if (mColumns.find(name) == mColumns.end())
{
// Add column
- mColumns[name] = LLScrollListColumn(column);
+ mColumns[name] = LLScrollListColumn(column, this);
LLScrollListColumn* new_column = &mColumns[name];
new_column->mParentCtrl = this;
new_column->mIndex = mColumns.size()-1;
// Add button
- if (new_column->mWidth > 0 || new_column->mRelWidth > 0 || new_column->mDynamicWidth)
+ if (new_column->getWidth() > 0 || new_column->mRelWidth > 0 || new_column->mDynamicWidth)
{
+ if (getNumColumns() > 0)
+ {
+ mTotalColumnPadding += mColumnPadding;
+ }
if (new_column->mRelWidth >= 0)
{
- new_column->mWidth = (S32)llround(new_column->mRelWidth*mItemListRect.getWidth());
+ new_column->setWidth((S32)llround(new_column->mRelWidth*mItemListRect.getWidth()));
}
else if(new_column->mDynamicWidth)
{
mNumDynamicWidthColumns++;
- new_column->mWidth = (mItemListRect.getWidth() - mTotalStaticColumnWidth) / mNumDynamicWidthColumns;
+ new_column->setWidth((mItemListRect.getWidth() - mTotalStaticColumnWidth - mTotalColumnPadding) / mNumDynamicWidthColumns);
}
S32 top = mItemListRect.mTop;
S32 left = mItemListRect.mLeft;
@@ -3043,14 +3095,14 @@ void LLScrollListCtrl::addColumn(const LLSD& column, EAddPosition pos)
for (itor = mColumns.begin(); itor != mColumns.end(); ++itor)
{
if (itor->second.mIndex < new_column->mIndex &&
- itor->second.mWidth > 0)
+ itor->second.getWidth() > 0)
{
- left += itor->second.mWidth + mColumnPadding;
+ left += itor->second.getWidth() + mColumnPadding;
}
}
}
std::string button_name = "btn_" + name;
- S32 right = left+new_column->mWidth;
+ S32 right = left+new_column->getWidth();
if (new_column->mIndex != (S32)mColumns.size()-1)
{
right += mColumnPadding;
@@ -3145,6 +3197,8 @@ void LLScrollListCtrl::clearColumns()
}
mColumns.clear();
mSortColumns.clear();
+ mTotalStaticColumnWidth = 0;
+ mTotalColumnPadding = 0;
}
void LLScrollListCtrl::setColumnLabel(const std::string& column, const std::string& label)
@@ -3244,7 +3298,7 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p
}
S32 index = columnp->mIndex;
- S32 width = columnp->mWidth;
+ S32 width = columnp->getWidth();
LLFontGL::HAlign font_alignment = columnp->mFontAlignment;
LLColor4 fcolor = LLColor4::black;
@@ -3301,6 +3355,19 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p
}
new_item->setColumn(index, cell);
}
+ else if (type == "date")
+ {
+ LLScrollListDate* cell = new LLScrollListDate(value.asDate(), font, width, font_style, font_alignment);
+ if (has_color)
+ {
+ cell->setColor(color);
+ }
+ new_item->setColumn(index, cell);
+ if (columnp->mHeader && !value.asString().empty())
+ {
+ columnp->mHeader->setHasResizableElement(TRUE);
+ }
+ }
else
{
LLScrollListText* cell = new LLScrollListText(value.asString(), font, width, font_style, font_alignment, fcolor, TRUE);
@@ -3325,7 +3392,7 @@ LLScrollListItem* LLScrollListCtrl::addElement(const LLSD& value, EAddPosition p
if (new_item->getColumn(column_idx) == NULL)
{
LLScrollListColumn* column_ptr = &column_it->second;
- new_item->setColumn(column_idx, new LLScrollListText(LLStringUtil::null, LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF_SMALL ), column_ptr->mWidth, LLFontGL::NORMAL));
+ new_item->setColumn(column_idx, new LLScrollListText(LLStringUtil::null, LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF_SMALL ), column_ptr->getWidth(), LLFontGL::NORMAL));
}
}
@@ -3469,6 +3536,7 @@ LLColumnHeader::LLColumnHeader(const std::string& label, const LLRect &rect, LLS
mButton->setMouseDownCallback(onMouseDown);
mButton->setCallbackUserData(this);
+ mButton->setToolTip(label);
mAscendingText = std::string("[LOW]...[HIGH](Ascending)"); // *TODO: Translate
mDescendingText = std::string("[HIGH]...[LOW](Descending)"); // *TODO: Translate
@@ -3556,7 +3624,7 @@ void LLColumnHeader::onClick(void* user_data)
LLScrollListCtrl::onClickColumn(column);
- // propage new sort order to sort order list
+ // propagate new sort order to sort order list
headerp->mList->selectNthItem(column->mParentCtrl->getSortAscending() ? 0 : 1);
}
@@ -3646,7 +3714,7 @@ void LLColumnHeader::showList()
text_width = llmax(text_width, LLFontGL::sSansSerifSmall->getWidth(descending_string)) + 10;
text_width = llmax(text_width, getRect().getWidth() - 30);
- mList->getColumn(0)->mWidth = text_width;
+ mList->getColumn(0)->setWidth(text_width);
((LLScrollListText*)mList->getFirstData()->getColumn(0))->setText(ascending_string);
((LLScrollListText*)mList->getLastData()->getColumn(0))->setText(descending_string);
@@ -3688,7 +3756,7 @@ LLView* LLColumnHeader::findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_d
llassert(snap_edge == SNAP_RIGHT);
// use higher snap threshold for column headers
- threshold = llmin(threshold, 15);
+ threshold = llmin(threshold, 10);
LLRect snap_rect = getSnapRect();
@@ -3727,47 +3795,48 @@ void LLColumnHeader::userSetShape(const LLRect& new_rect)
if (delta_width != 0)
{
- S32 remaining_width = delta_width;
+ S32 remaining_width = -delta_width;
S32 col;
for (col = mColumn->mIndex + 1; col < mColumn->mParentCtrl->getNumColumns(); col++)
{
LLScrollListColumn* columnp = mColumn->mParentCtrl->getColumn(col);
- if (!columnp) break;
+ if (!columnp) continue;
if (columnp->mHeader && columnp->mHeader->canResize())
{
// how many pixels in width can this column afford to give up?
- S32 resize_buffer_amt = llmax(0, columnp->mWidth - MIN_COLUMN_WIDTH);
+ S32 resize_buffer_amt = llmax(0, columnp->getWidth() - MIN_COLUMN_WIDTH);
// user shrinking column, need to add width to other columns
if (delta_width < 0)
{
- if (!columnp->mDynamicWidth && columnp->mWidth > 0)
+ if (/*!columnp->mDynamicWidth && */columnp->getWidth() > 0)
{
// statically sized column, give all remaining width to this column
- columnp->mWidth -= remaining_width;
+ columnp->setWidth(columnp->getWidth() + remaining_width);
if (columnp->mRelWidth > 0.f)
{
- columnp->mRelWidth = (F32)columnp->mWidth / (F32)mColumn->mParentCtrl->getItemListRect().getWidth();
+ columnp->mRelWidth = (F32)columnp->getWidth() / (F32)mColumn->mParentCtrl->getItemListRect().getWidth();
}
+ // all padding went to this widget, we're done
+ break;
}
- break;
}
else
{
// user growing column, need to take width from other columns
- remaining_width -= resize_buffer_amt;
+ remaining_width += resize_buffer_amt;
- if (!columnp->mDynamicWidth && columnp->mWidth > 0)
+ if (/*!columnp->mDynamicWidth && */columnp->getWidth() > 0)
{
- columnp->mWidth -= llmin(columnp->mWidth - MIN_COLUMN_WIDTH, delta_width);
+ columnp->setWidth(columnp->getWidth() - llmin(columnp->getWidth() - MIN_COLUMN_WIDTH, delta_width));
if (columnp->mRelWidth > 0.f)
{
- columnp->mRelWidth = (F32)columnp->mWidth / (F32)mColumn->mParentCtrl->getItemListRect().getWidth();
+ columnp->mRelWidth = (F32)columnp->getWidth() / (F32)mColumn->mParentCtrl->getItemListRect().getWidth();
}
}
- if (remaining_width <= 0)
+ if (remaining_width >= 0)
{
// width sucked up from neighboring columns, done
break;
@@ -3779,14 +3848,14 @@ void LLColumnHeader::userSetShape(const LLRect& new_rect)
// clamp resize amount to maximum that can be absorbed by other columns
if (delta_width > 0)
{
- delta_width -= llmax(remaining_width, 0);
+ delta_width += llmin(remaining_width, 0);
}
// propagate constrained delta_width to new width for this column
new_width = getRect().getWidth() + delta_width - mColumn->mParentCtrl->getColumnPadding();
// use requested width
- mColumn->mWidth = new_width;
+ mColumn->setWidth(new_width);
// update proportional spacing
if (mColumn->mRelWidth > 0.f)
@@ -3804,36 +3873,40 @@ void LLColumnHeader::userSetShape(const LLRect& new_rect)
void LLColumnHeader::setHasResizableElement(BOOL resizable)
{
// for now, dynamically spaced columns can't be resized
- if (mColumn->mDynamicWidth) return;
+// if (mColumn->mDynamicWidth) return;
- if (resizable != mHasResizableElement)
+ if (mHasResizableElement != resizable)
{
+ mColumn->mParentCtrl->dirtyColumns();
mHasResizableElement = resizable;
+ }
+}
- S32 num_resizable_columns = 0;
- S32 col;
- for (col = 0; col < mColumn->mParentCtrl->getNumColumns(); col++)
+void LLColumnHeader::updateResizeBars()
+{
+ S32 num_resizable_columns = 0;
+ S32 col;
+ for (col = 0; col < mColumn->mParentCtrl->getNumColumns(); col++)
+ {
+ LLScrollListColumn* columnp = mColumn->mParentCtrl->getColumn(col);
+ if (columnp->mHeader && columnp->mHeader->canResize())
{
- LLScrollListColumn* columnp = mColumn->mParentCtrl->getColumn(col);
- if (columnp->mHeader && columnp->mHeader->canResize())
- {
- num_resizable_columns++;
- }
+ num_resizable_columns++;
}
+ }
- S32 num_resizers_enabled = 0;
+ S32 num_resizers_enabled = 0;
- // now enable/disable resize handles on resizable columns if we have at least two
- for (col = 0; col < mColumn->mParentCtrl->getNumColumns(); col++)
+ // now enable/disable resize handles on resizable columns if we have at least two
+ for (col = 0; col < mColumn->mParentCtrl->getNumColumns(); col++)
+ {
+ LLScrollListColumn* columnp = mColumn->mParentCtrl->getColumn(col);
+ if (!columnp->mHeader) continue;
+ BOOL enable = num_resizable_columns >= 2 && num_resizers_enabled < (num_resizable_columns - 1) && columnp->mHeader->canResize();
+ columnp->mHeader->enableResizeBar(enable);
+ if (enable)
{
- LLScrollListColumn* columnp = mColumn->mParentCtrl->getColumn(col);
- if (!columnp->mHeader) continue;
- BOOL enable = num_resizable_columns >= 2 && num_resizers_enabled < (num_resizable_columns - 1) && columnp->mHeader->canResize();
- columnp->mHeader->enableResizeBar(enable);
- if (enable)
- {
- num_resizers_enabled++;
- }
+ num_resizers_enabled++;
}
}
}
@@ -3841,7 +3914,7 @@ void LLColumnHeader::setHasResizableElement(BOOL resizable)
void LLColumnHeader::enableResizeBar(BOOL enable)
{
// for now, dynamically spaced columns can't be resized
- if (!mColumn->mDynamicWidth)
+ //if (!mColumn->mDynamicWidth)
{
mResizeBar->setEnabled(enable);
}
@@ -3851,3 +3924,78 @@ BOOL LLColumnHeader::canResize()
{
return getVisible() && (mHasResizableElement || mColumn->mDynamicWidth);
}
+
+void LLScrollListColumn::setWidth(S32 width)
+{
+ if (!mDynamicWidth && mRelWidth <= 0.f)
+ {
+ mParentCtrl->updateStaticColumnWidth(this, width);
+ }
+ mWidth = width;
+}
+
+// Default constructor
+LLScrollListColumn::LLScrollListColumn() :
+ mName(),
+ mSortingColumn(),
+ mSortAscending(TRUE),
+ mLabel(),
+ mWidth(-1),
+ mRelWidth(-1.0),
+ mDynamicWidth(FALSE),
+ mMaxContentWidth(0),
+ mIndex(-1),
+ mParentCtrl(NULL),
+ mHeader(NULL),
+ mFontAlignment(LLFontGL::LEFT)
+{ }
+
+LLScrollListColumn::LLScrollListColumn(const LLSD &sd, LLScrollListCtrl* parent) :
+ mWidth(0),
+ mIndex (-1),
+ mParentCtrl(parent),
+ mHeader(NULL),
+ mMaxContentWidth(0),
+ mDynamicWidth(FALSE),
+ mRelWidth(-1.f)
+{
+ mName = sd.get("name").asString();
+ mSortingColumn = mName;
+ if (sd.has("sort"))
+ {
+ mSortingColumn = sd.get("sort").asString();
+ }
+ mSortAscending = TRUE;
+ if (sd.has("sort_ascending"))
+ {
+ mSortAscending = sd.get("sort_ascending").asBoolean();
+ }
+ mLabel = sd.get("label").asString();
+ if (sd.has("relwidth") && (F32)sd.get("relwidth").asReal() > 0)
+ {
+ mRelWidth = (F32)sd.get("relwidth").asReal();
+ if (mRelWidth < 0) mRelWidth = 0;
+ if (mRelWidth > 1) mRelWidth = 1;
+ mDynamicWidth = FALSE;
+ }
+ else if(sd.has("dynamicwidth") && (BOOL)sd.get("dynamicwidth").asBoolean() == TRUE)
+ {
+ mDynamicWidth = TRUE;
+ mRelWidth = -1;
+ }
+ else
+ {
+
+ setWidth(sd.get("width").asInteger());
+ }
+
+ if (sd.has("halign"))
+ {
+ mFontAlignment = (LLFontGL::HAlign)llclamp(sd.get("halign").asInteger(), (S32)LLFontGL::LEFT, (S32)LLFontGL::HCENTER);
+ }
+ else
+ {
+ mFontAlignment = LLFontGL::LEFT;
+ }
+
+}
diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h
index 0128c01eba..d8ef955042 100644
--- a/indra/llui/llscrolllistctrl.h
+++ b/indra/llui/llscrolllistctrl.h
@@ -47,6 +47,7 @@
#include "llcombobox.h"
#include "llscrollbar.h"
#include "llresizebar.h"
+#include "lldate.h"
/*
* Represents a cell in a scrollable table.
@@ -133,6 +134,18 @@ private:
static U32 sCount;
};
+
+class LLScrollListDate : public LLScrollListText
+{
+public:
+ LLScrollListDate( const LLDate& date, const LLFontGL* font, S32 width=0, U8 font_style = LLFontGL::NORMAL, LLFontGL::HAlign font_alignment = LLFontGL::LEFT, LLColor4& color = LLColor4::black, BOOL use_color = FALSE, BOOL visible = TRUE);
+ virtual void setValue(const LLSD& value);
+ virtual const LLSD getValue() const;
+
+private:
+ LLDate mDate;
+};
+
/*
* Cell displaying an image.
*/
@@ -185,88 +198,11 @@ private:
class LLScrollListColumn
{
public:
- // Default constructor
- LLScrollListColumn() :
- mName(),
- mSortingColumn(),
- mSortAscending(TRUE),
- mLabel(),
- mWidth(-1),
- mRelWidth(-1.0),
- mDynamicWidth(FALSE),
- mMaxContentWidth(0),
- mIndex(-1),
- mParentCtrl(NULL),
- mHeader(NULL),
- mFontAlignment(LLFontGL::LEFT)
- { }
-
- LLScrollListColumn(std::string name, std::string label, S32 width, F32 relwidth) :
- mName(name),
- mSortingColumn(name),
- mSortAscending(TRUE),
- mLabel(label),
- mWidth(width),
- mRelWidth(relwidth),
- mDynamicWidth(FALSE),
- mMaxContentWidth(0),
- mIndex(-1),
- mParentCtrl(NULL),
- mHeader(NULL),
- mFontAlignment(LLFontGL::LEFT)
- { }
-
- LLScrollListColumn(const LLSD &sd)
- {
- mMaxContentWidth = 0;
-
- mName = sd.get("name").asString();
- mSortingColumn = mName;
- if (sd.has("sort"))
- {
- mSortingColumn = sd.get("sort").asString();
- }
- mSortAscending = TRUE;
- if (sd.has("sort_ascending"))
- {
- mSortAscending = sd.get("sort_ascending").asBoolean();
- }
- mLabel = sd.get("label").asString();
- if (sd.has("relwidth") && (F32)sd.get("relwidth").asReal() > 0)
- {
- mRelWidth = (F32)sd.get("relwidth").asReal();
- if (mRelWidth < 0) mRelWidth = 0;
- if (mRelWidth > 1) mRelWidth = 1;
- mDynamicWidth = FALSE;
- mWidth = 0;
- }
- else if(sd.has("dynamicwidth") && (BOOL)sd.get("dynamicwidth").asBoolean() == TRUE)
- {
- mDynamicWidth = TRUE;
- mRelWidth = -1;
- mWidth = 0;
- }
- else
- {
- mWidth = sd.get("width").asInteger();
- mDynamicWidth = FALSE;
- mRelWidth = -1;
- }
-
- if (sd.has("halign"))
- {
- mFontAlignment = (LLFontGL::HAlign)llclamp(sd.get("halign").asInteger(), (S32)LLFontGL::LEFT, (S32)LLFontGL::HCENTER);
- }
- else
- {
- mFontAlignment = LLFontGL::LEFT;
- }
-
- mIndex = -1;
- mParentCtrl = NULL;
- mHeader = NULL;
- mFontAlignment = LLFontGL::LEFT;
- }
+ LLScrollListColumn();
+ LLScrollListColumn(const LLSD &sd, LLScrollListCtrl* parent);
+
+ void setWidth(S32 width);
+ S32 getWidth() const { return mWidth; }
// Public data is fine so long as this remains a simple struct-like data class.
// If it ever gets any smarter than that, these should all become private
@@ -275,7 +211,6 @@ public:
std::string mSortingColumn;
BOOL mSortAscending;
std::string mLabel;
- S32 mWidth;
F32 mRelWidth;
BOOL mDynamicWidth;
S32 mMaxContentWidth;
@@ -283,6 +218,10 @@ public:
LLScrollListCtrl* mParentCtrl;
class LLColumnHeader* mHeader;
LLFontGL::HAlign mFontAlignment;
+
+private:
+ S32 mWidth;
+
};
class LLColumnHeader : public LLComboBox
@@ -301,6 +240,7 @@ public:
void setImage(const std::string &image_name);
LLScrollListColumn* getColumn() { return mColumn; }
void setHasResizableElement(BOOL resizable);
+ void updateResizeBars();
BOOL canResize();
void enableResizeBar(BOOL enable);
std::string getLabel() { return mOrigLabel; }
@@ -551,8 +491,7 @@ public:
virtual S32 getScrollPos() const;
virtual void setScrollPos( S32 pos );
-
- S32 getSearchColumn() { return mSearchColumn; }
+ S32 getSearchColumn();
void setSearchColumn(S32 column) { mSearchColumn = column; }
S32 getColumnIndexFromOffset(S32 x);
S32 getColumnOffsetFromIndex(S32 index);
@@ -613,8 +552,9 @@ public:
virtual void deselect();
virtual BOOL canDeselect() const;
- void setNumDynamicColumns(int num) { mNumDynamicWidthColumns = num; }
- void setTotalStaticColumnWidth(int width) { mTotalStaticColumnWidth = width; }
+ void setNumDynamicColumns(S32 num) { mNumDynamicWidthColumns = num; }
+ void updateStaticColumnWidth(LLScrollListColumn* col, S32 new_width);
+ S32 getTotalStaticColumnWidth() { return mTotalStaticColumnWidth; }
std::string getSortColumnName();
BOOL getSortAscending() { return mSortColumns.empty() ? TRUE : mSortColumns.back().second; }
@@ -719,6 +659,7 @@ private:
S32 mSearchColumn;
S32 mNumDynamicWidthColumns;
S32 mTotalStaticColumnWidth;
+ S32 mTotalColumnPadding;
BOOL mSorted;
diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp
index a4b16dc2de..7b2c97af67 100644
--- a/indra/llui/llui.cpp
+++ b/indra/llui/llui.cpp
@@ -30,6 +30,7 @@
*/
// Utilities functions the user interface needs
+
#include "linden_common.h"
#include <string>
@@ -65,6 +66,7 @@ std::map<std::string, std::string> gTranslation;
std::list<std::string> gUntranslated;
LLControlGroup* LLUI::sConfigGroup = NULL;
+LLControlGroup* LLUI::sIgnoresGroup = NULL;
LLControlGroup* LLUI::sColorsGroup = NULL;
LLImageProviderInterface* LLUI::sImageProvider = NULL;
LLUIAudioCallback LLUI::sAudioCallback = NULL;
@@ -90,7 +92,7 @@ void make_ui_sound(const char* namep)
LLUUID uuid(LLUI::sConfigGroup->getString(name));
if (uuid.isNull())
{
- if ("00000000-0000-0000-0000-000000000000" == LLUI::sConfigGroup->getString(name))
+ if (LLUI::sConfigGroup->getString(name) == LLUUID::null.asString())
{
if (LLUI::sConfigGroup->getBOOL("UISndDebugSpamToggle"))
{
@@ -1552,6 +1554,7 @@ bool handleShowXUINamesChanged(const LLSD& newvalue)
}
void LLUI::initClass(LLControlGroup* config,
+ LLControlGroup* ignores,
LLControlGroup* colors,
LLImageProviderInterface* image_provider,
LLUIAudioCallback audio_callback,
@@ -1559,7 +1562,16 @@ void LLUI::initClass(LLControlGroup* config,
const std::string& language)
{
sConfigGroup = config;
+ sIgnoresGroup = ignores;
sColorsGroup = colors;
+
+ if (sConfigGroup == NULL
+ || sIgnoresGroup == NULL
+ || sColorsGroup == NULL)
+ {
+ llerrs << "Failure to initialize configuration groups" << llendl;
+ }
+
sImageProvider = image_provider;
sAudioCallback = audio_callback;
sGLScaleFactor = (scale_factor == NULL) ? LLVector2(1.f, 1.f) : *scale_factor;
@@ -1567,7 +1579,7 @@ void LLUI::initClass(LLControlGroup* config,
LLFontGL::sShadowColor = colors->getColor("ColorDropShadow");
LLUI::sShowXUINames = LLUI::sConfigGroup->getBOOL("ShowXUINames");
- LLUI::sConfigGroup->getControl("ShowXUINames")->getSignal()->connect(boost::bind(&handleShowXUINamesChanged, _1));
+ LLUI::sConfigGroup->getControl("ShowXUINames")->getSignal()->connect(&handleShowXUINamesChanged);
}
void LLUI::cleanupClass()
diff --git a/indra/llui/llui.h b/indra/llui/llui.h
index e2629ee2a4..4366c38740 100644
--- a/indra/llui/llui.h
+++ b/indra/llui/llui.h
@@ -42,6 +42,7 @@
#include "llgl.h" // *TODO: break this dependency
#include <stack>
//#include "llimagegl.h"
+#include <boost/signal.hpp>
// LLUIFactory
#include "llsd.h"
@@ -150,11 +151,13 @@ typedef void (*LLUIAudioCallback)(const LLUUID& uuid);
class LLUI
{
+ LOG_CLASS(LLUI);
public:
//
// Methods
//
static void initClass(LLControlGroup* config,
+ LLControlGroup* ignores,
LLControlGroup* colors,
LLImageProviderInterface* image_provider,
LLUIAudioCallback audio_callback = NULL,
@@ -190,6 +193,7 @@ public:
// Data
//
static LLControlGroup* sConfigGroup;
+ static LLControlGroup* sIgnoresGroup;
static LLControlGroup* sColorsGroup;
static LLImageProviderInterface* sImageProvider;
static LLUIAudioCallback sAudioCallback;
@@ -597,4 +601,237 @@ public:
virtual void cleanUp() = 0;
};
+// This mix-in class adds support for tracking all instances of the specificed class parameter T
+// The (optional) key associates a value of type KEY with a given instance of T, for quick lookup
+// If KEY is not provided, then instances are stored in a simple list
+template<typename T, typename KEY = T*>
+class LLInstanceTracker : boost::noncopyable
+{
+public:
+ typedef typename std::map<KEY, T*>::iterator instance_iter;
+ typedef typename std::map<KEY, T*>::const_iterator instance_const_iter;
+
+ static T* getInstance(KEY k) { instance_iter found = sInstances.find(k); return (found == sInstances.end()) ? NULL : found->second; }
+
+ static instance_iter beginInstances() { return sInstances.begin(); }
+ static instance_iter endInstances() { return sInstances.end(); }
+ static S32 instanceCount() { return sInstances.size(); }
+protected:
+ LLInstanceTracker(KEY key) { add(key); }
+ virtual ~LLInstanceTracker() { remove(); }
+ virtual void setKey(KEY key) { remove(); add(key); }
+ virtual const KEY& getKey() const { return mKey; }
+
+private:
+ void add(KEY key)
+ {
+ mKey = key;
+ sInstances[key] = static_cast<T*>(this);
+ }
+ void remove() { sInstances.erase(mKey); }
+
+private:
+
+ KEY mKey;
+ static std::map<KEY, T*> sInstances;
+};
+
+template<typename T>
+class LLInstanceTracker<T, T*> : boost::noncopyable
+{
+public:
+ typedef typename std::set<T*>::iterator instance_iter;
+ typedef typename std::set<T*>::const_iterator instance_const_iter;
+
+ static instance_iter instancesBegin() { return sInstances.begin(); }
+ static instance_iter instancesEnd() { return sInstances.end(); }
+ static S32 instanceCount() { return sInstances.size(); }
+
+protected:
+ LLInstanceTracker() { sInstances.insert(static_cast<T*>(this)); }
+ virtual ~LLInstanceTracker() { sInstances.erase(static_cast<T*>(this)); }
+
+ static std::set<T*> sInstances;
+};
+
+template <typename T, typename KEY> std::map<KEY, T*> LLInstanceTracker<T, KEY>::sInstances;
+template <typename T> std::set<T*> LLInstanceTracker<T, T*>::sInstances;
+
+class LLCallbackRegistry
+{
+public:
+ typedef boost::signal<void()> callback_signal_t;
+
+ void registerCallback(const callback_signal_t::slot_type& slot)
+ {
+ mCallbacks.connect(slot);
+ }
+
+ void fireCallbacks()
+ {
+ mCallbacks();
+ }
+
+private:
+ callback_signal_t mCallbacks;
+};
+
+class LLInitClassList :
+ public LLCallbackRegistry,
+ public LLSingleton<LLInitClassList>
+{
+ friend class LLSingleton<LLInitClassList>;
+private:
+ LLInitClassList() {}
+};
+
+class LLDestroyClassList :
+ public LLCallbackRegistry,
+ public LLSingleton<LLDestroyClassList>
+{
+ friend class LLSingleton<LLDestroyClassList>;
+private:
+ LLDestroyClassList() {}
+};
+
+template<typename T>
+class LLRegisterWith
+{
+public:
+ LLRegisterWith(boost::function<void ()> func)
+ {
+ T::instance().registerCallback(func);
+ }
+
+ // this avoids a MSVC bug where non-referenced static members are "optimized" away
+ // even if their constructors have side effects
+ void reference()
+ {
+ S32 dummy;
+ dummy = 0;
+ }
+};
+
+template<typename T>
+class LLInitClass
+{
+public:
+ LLInitClass() { sRegister.reference(); }
+
+ static LLRegisterWith<LLInitClassList> sRegister;
+private:
+
+ static void initClass()
+ {
+ llerrs << "No static initClass() method defined for " << typeid(T).name() << llendl;
+ }
+};
+
+template<typename T>
+class LLDestroyClass
+{
+public:
+ LLDestroyClass() { sRegister.reference(); }
+
+ static LLRegisterWith<LLDestroyClassList> sRegister;
+private:
+
+ static void destroyClass()
+ {
+ llerrs << "No static destroyClass() method defined for " << typeid(T).name() << llendl;
+ }
+};
+
+template <typename T> LLRegisterWith<LLInitClassList> LLInitClass<T>::sRegister(&T::initClass);
+template <typename T> LLRegisterWith<LLDestroyClassList> LLDestroyClass<T>::sRegister(&T::destroyClass);
+
+
+template <typename DERIVED>
+class LLParamBlock
+{
+protected:
+ LLParamBlock() { sBlock = (DERIVED*)this; }
+
+ typedef typename boost::add_const<DERIVED>::type Tconst;
+
+ template <typename T>
+ class LLMandatoryParam
+ {
+ public:
+ typedef typename boost::add_const<T>::type T_const;
+
+ LLMandatoryParam(T_const initial_val) : mVal(initial_val), mBlock(sBlock) {}
+ LLMandatoryParam(const LLMandatoryParam<T>& other) : mVal(other.mVal) {}
+
+ DERIVED& operator ()(T_const set_value) { mVal = set_value; return *mBlock; }
+ operator T() const { return mVal; }
+ T operator=(T_const set_value) { mVal = set_value; return mVal; }
+
+ private:
+ T mVal;
+ DERIVED* mBlock;
+ };
+
+ template <typename T>
+ class LLOptionalParam
+ {
+ public:
+ typedef typename boost::add_const<T>::type T_const;
+
+ LLOptionalParam(T_const initial_val) : mVal(initial_val), mBlock(sBlock) {}
+ LLOptionalParam() : mBlock(sBlock) {}
+ LLOptionalParam(const LLOptionalParam<T>& other) : mVal(other.mVal) {}
+
+ DERIVED& operator ()(T_const set_value) { mVal = set_value; return *mBlock; }
+ operator T() const { return mVal; }
+ T operator=(T_const set_value) { mVal = set_value; return mVal; }
+
+ private:
+ T mVal;
+ DERIVED* mBlock;
+ };
+
+ // specialization that requires initialization for reference types
+ template <typename T>
+ class LLOptionalParam <T&>
+ {
+ public:
+ typedef typename boost::add_const<T&>::type T_const;
+
+ LLOptionalParam(T_const initial_val) : mVal(initial_val), mBlock(sBlock) {}
+ LLOptionalParam(const LLOptionalParam<T&>& other) : mVal(other.mVal) {}
+
+ DERIVED& operator ()(T_const set_value) { mVal = set_value; return *mBlock; }
+ operator T&() const { return mVal; }
+ T& operator=(T_const set_value) { mVal = set_value; return mVal; }
+
+ private:
+ T& mVal;
+ DERIVED* mBlock;
+ };
+
+ // specialization that initializes pointer params to NULL
+ template<typename T>
+ class LLOptionalParam<T*>
+ {
+ public:
+ typedef typename boost::add_const<T*>::type T_const;
+
+ LLOptionalParam(T_const initial_val) : mVal(initial_val), mBlock(sBlock) {}
+ LLOptionalParam() : mVal((T*)NULL), mBlock(sBlock) {}
+ LLOptionalParam(const LLOptionalParam<T*>& other) : mVal(other.mVal) {}
+
+ DERIVED& operator ()(T_const set_value) { mVal = set_value; return *mBlock; }
+ operator T*() const { return mVal; }
+ T* operator=(T_const set_value) { mVal = set_value; return mVal; }
+ private:
+ T* mVal;
+ DERIVED* mBlock;
+ };
+
+ static DERIVED* sBlock;
+};
+
+template <typename T> T* LLParamBlock<T>::sBlock = NULL;
+
#endif
diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp
index f7419d615b..6e822f7c03 100644
--- a/indra/llui/lluictrl.cpp
+++ b/indra/llui/lluictrl.cpp
@@ -475,10 +475,10 @@ BOOL LLUICtrl::focusPrevItem(BOOL text_fields_only)
return focusPrev(result);
}
-LLUICtrl* LLUICtrl::findRootMostFocusRoot() const
+LLUICtrl* LLUICtrl::findRootMostFocusRoot()
{
- const LLUICtrl* focus_root = NULL;
- const LLUICtrl* next_view = this;
+ LLUICtrl* focus_root = NULL;
+ LLUICtrl* next_view = this;
while(next_view)
{
if (next_view->isFocusRoot())
@@ -487,9 +487,8 @@ LLUICtrl* LLUICtrl::findRootMostFocusRoot() const
}
next_view = next_view->getParentUICtrl();
}
- // since focus_root could be this, need to cast away const to return
- // a non-const result
- return const_cast<LLUICtrl*>(focus_root);
+
+ return focus_root;
}
diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h
index 4ad9042b9a..7d1f504f79 100644
--- a/indra/llui/lluictrl.h
+++ b/indra/llui/lluictrl.h
@@ -141,7 +141,7 @@ public:
static LLView* fromXML(LLXMLNodePtr node, LLView* parent, class LLUICtrlFactory* factory);
- LLUICtrl* findRootMostFocusRoot() const;
+ LLUICtrl* findRootMostFocusRoot();
class LLTextInputFilter : public LLQueryFilter, public LLSingleton<LLTextInputFilter>
{
diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h
index 3e22e196b0..dfcea7290e 100644
--- a/indra/llui/lluictrlfactory.h
+++ b/indra/llui/lluictrlfactory.h
@@ -78,6 +78,7 @@ public:
static bool getLayeredXMLNode(const std::string &filename, LLXMLNodePtr& root);
private:
+ bool getLayeredXMLNodeImpl(const std::string &filename, LLXMLNodePtr& root);
typedef std::map<LLHandle<LLPanel>, std::string> built_panel_t;
built_panel_t mBuiltPanels;
diff --git a/indra/llui/lluistring.cpp b/indra/llui/lluistring.cpp
index 0dde20934c..51768ad885 100644
--- a/indra/llui/lluistring.cpp
+++ b/indra/llui/lluistring.cpp
@@ -31,6 +31,7 @@
#include "linden_common.h"
#include "lluistring.h"
+#include "llsd.h"
const LLStringUtil::format_map_t LLUIString::sNullArgs;
@@ -54,6 +55,18 @@ void LLUIString::setArgList(const LLStringUtil::format_map_t& args)
format();
}
+void LLUIString::setArgs(const LLSD& sd)
+{
+ if (!sd.isMap()) return;
+ for(LLSD::map_const_iterator sd_it = sd.beginMap();
+ sd_it != sd.endMap();
+ ++sd_it)
+ {
+ setArg(sd_it->first, sd_it->second.asString());
+ }
+ format();
+}
+
void LLUIString::setArg(const std::string& key, const std::string& replacement)
{
mArgs[key] = replacement;
diff --git a/indra/llui/lluistring.h b/indra/llui/lluistring.h
index 773bc09763..c99aeb50c6 100644
--- a/indra/llui/lluistring.h
+++ b/indra/llui/lluistring.h
@@ -50,9 +50,9 @@
// llinfos << mMessage.getString() << llendl; // outputs "Welcome Steve to Second Life"
// mMessage.setArg("[USERNAME]", "Joe");
// llinfos << mMessage.getString() << llendl; // outputs "Welcome Joe to Second Life"
-// mMessage = "Recepción a la [SECONDLIFE] [USERNAME]"
+// mMessage = "Recepci￳n a la [SECONDLIFE] [USERNAME]"
// mMessage.setArg("[SECONDLIFE]", "Segunda Vida");
-// llinfos << mMessage.getString() << llendl; // outputs "Recepción a la Segunda Vida Joe"
+// llinfos << mMessage.getString() << llendl; // outputs "Recepci￳n a la Segunda Vida Joe"
// Implementation Notes:
// Attempting to have operator[](const std::string& s) return mArgs[s] fails because we have
@@ -71,6 +71,8 @@ public:
LLUIString& operator=(const std::string& s) { assign(s); return *this; }
void setArgList(const LLStringUtil::format_map_t& args);
+ void setArgs(const LLStringUtil::format_map_t& args) { setArgList(args); }
+ void setArgs(const class LLSD& sd);
void setArg(const std::string& key, const std::string& replacement);
const std::string& getString() const { return mResult; }
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index 3e7e59876c..65e9417b8b 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -1260,7 +1260,7 @@ void LLView::draw()
{
LLView *viewp = *child_iter;
- if (viewp->getVisible() && viewp != focus_view)
+ if (viewp->getVisible() && viewp != focus_view && viewp->getRect().isValid())
{
// Only draw views that are within the root view
localRectToScreen(viewp->getRect(),&screenRect);
@@ -1357,7 +1357,8 @@ void LLView::drawChild(LLView* childp, S32 x_offset, S32 y_offset, BOOL force_dr
{
++sDepth;
- if (childp->getVisible() || force_draw)
+ if ((childp->getVisible() && childp->getRect().isValid())
+ || force_draw)
{
glMatrixMode(GL_MODELVIEW);
LLUI::pushMatrix();
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index ff7a1afb38..ae0df61599 100644
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -485,7 +485,7 @@ public:
// did we find *something* with that name?
if (child)
{
- llwarns << "Found child named " << name << " but of wrong type" << llendl;
+ llwarns << "Found child named " << name << " but of wrong type " << typeid(child).name() << ", expecting " << typeid(T).name() << llendl;
}
if (create_if_missing)
{
@@ -496,6 +496,11 @@ public:
return result;
}
+ template <class T> T& getChildRef(const std::string& name, BOOL recurse = TRUE) const
+ {
+ return *getChild<T>(name, recurse, TRUE);
+ }
+
virtual LLView* getChildView(const std::string& name, BOOL recurse = TRUE, BOOL create_if_missing = TRUE) const;
template <class T> T* createDummyWidget(const std::string& name) const
diff --git a/indra/llxml/llxmlnode.cpp b/indra/llxml/llxmlnode.cpp
index 750c1fc1ef..aef1488e51 100644
--- a/indra/llxml/llxmlnode.cpp
+++ b/indra/llxml/llxmlnode.cpp
@@ -65,6 +65,9 @@ LLXMLNode::LLXMLNode() :
mEncoding(ENCODING_DEFAULT),
mParent(NULL),
mChildren(NULL),
+ mAttributes(),
+ mPrev(NULL),
+ mNext(NULL),
mName(NULL),
mValue(""),
mDefault(NULL)
@@ -83,6 +86,9 @@ LLXMLNode::LLXMLNode(const char* name, BOOL is_attribute) :
mEncoding(ENCODING_DEFAULT),
mParent(NULL),
mChildren(NULL),
+ mAttributes(),
+ mPrev(NULL),
+ mNext(NULL),
mValue(""),
mDefault(NULL)
{
@@ -101,17 +107,65 @@ LLXMLNode::LLXMLNode(LLStringTableEntry* name, BOOL is_attribute) :
mEncoding(ENCODING_DEFAULT),
mParent(NULL),
mChildren(NULL),
+ mAttributes(),
+ mPrev(NULL),
+ mNext(NULL),
mName(name),
mValue(""),
mDefault(NULL)
{
}
+// copy constructor (except for the children)
+LLXMLNode::LLXMLNode(const LLXMLNode& rhs) :
+ mID(rhs.mID),
+ mIsAttribute(rhs.mIsAttribute),
+ mVersionMajor(rhs.mVersionMajor),
+ mVersionMinor(rhs.mVersionMinor),
+ mLength(rhs.mLength),
+ mPrecision(rhs.mPrecision),
+ mType(rhs.mType),
+ mEncoding(rhs.mEncoding),
+ mParent(NULL),
+ mChildren(NULL),
+ mAttributes(),
+ mPrev(NULL),
+ mNext(NULL),
+ mName(rhs.mName),
+ mValue(rhs.mValue),
+ mDefault(rhs.mDefault)
+{
+}
+
+// returns a new copy of this node and all its children
+LLXMLNodePtr LLXMLNode::deepCopy()
+{
+ LLXMLNodePtr newnode = LLXMLNodePtr(new LLXMLNode(*this));
+ if (mChildren.notNull())
+ {
+ for (LLXMLChildList::iterator iter = mChildren->map.begin();
+ iter != mChildren->map.end(); ++iter)
+ {
+ newnode->addChild(iter->second->deepCopy());
+ }
+ }
+ for (LLXMLAttribList::iterator iter = mAttributes.begin();
+ iter != mAttributes.end(); ++iter)
+ {
+ newnode->addChild(iter->second->deepCopy());
+ }
+
+ return newnode;
+}
+
// virtual
LLXMLNode::~LLXMLNode()
{
// Strictly speaking none of this should be required execept 'delete mChildren'...
- if (mChildren)
+ // Sadly, that's only true if we hadn't had reference-counted smart pointers linked
+ // in three different directions. This entire class is a frightening, hard-to-maintain
+ // mess.
+ if (mChildren.notNull())
{
for (LLXMLChildList::iterator iter = mChildren->map.begin();
iter != mChildren->map.end(); ++iter)
@@ -124,7 +178,7 @@ LLXMLNode::~LLXMLNode()
mChildren->map.clear();
mChildren->head = NULL;
mChildren->tail = NULL;
- delete mChildren;
+ mChildren = NULL;
}
for (LLXMLAttribList::iterator iter = mAttributes.begin();
iter != mAttributes.end(); ++iter)
@@ -160,7 +214,7 @@ BOOL LLXMLNode::removeChild(LLXMLNode *target_child)
return TRUE;
}
}
- else if (mChildren)
+ else if (mChildren.notNull())
{
LLXMLChildList::iterator children_itr = mChildren->map.find(target_child->mName);
while (children_itr != mChildren->map.end())
@@ -183,7 +237,6 @@ BOOL LLXMLNode::removeChild(LLXMLNode *target_child)
mChildren->map.erase(children_itr);
if (mChildren->map.empty())
{
- delete mChildren;
mChildren = NULL;
}
return TRUE;
@@ -201,7 +254,7 @@ BOOL LLXMLNode::removeChild(LLXMLNode *target_child)
return FALSE;
}
-void LLXMLNode::addChild(LLXMLNodePtr new_child)
+void LLXMLNode::addChild(LLXMLNodePtr new_child, LLXMLNodePtr after_child)
{
if (new_child->mParent != NULL)
{
@@ -219,7 +272,7 @@ void LLXMLNode::addChild(LLXMLNodePtr new_child)
}
else
{
- if (!mChildren)
+ if (mChildren.isNull())
{
mChildren = new LLXMLChildren();
mChildren->head = new_child;
@@ -227,11 +280,33 @@ void LLXMLNode::addChild(LLXMLNodePtr new_child)
}
mChildren->map.insert(std::make_pair(new_child->mName, new_child));
- if (mChildren->tail != new_child)
+ // if after_child is specified, it damn well better be in the list of children
+ // for this node. I'm not going to assert that, because it would be expensive,
+ // but don't specify that parameter if you didn't get the value for it from the
+ // list of children of this node!
+ if (after_child.isNull())
{
- mChildren->tail->mNext = new_child;
- new_child->mPrev = mChildren->tail;
- mChildren->tail = new_child;
+ if (mChildren->tail != new_child)
+ {
+ mChildren->tail->mNext = new_child;
+ new_child->mPrev = mChildren->tail;
+ mChildren->tail = new_child;
+ }
+ }
+ else
+ {
+ if (after_child->mNext.notNull())
+ {
+ // if after_child was not the last item, fix up some pointers
+ after_child->mNext->mPrev = new_child;
+ new_child->mNext = after_child->mNext;
+ }
+ new_child->mPrev = after_child;
+ after_child->mNext = new_child;
+ if (mChildren->tail == after_child)
+ {
+ mChildren->tail = new_child;
+ }
}
}
@@ -293,7 +368,7 @@ void LLXMLNode::updateDefault()
}
}
- if (mChildren)
+ if (mChildren.notNull())
{
LLXMLChildList::const_iterator children_itr;
LLXMLChildList::const_iterator children_end = mChildren->map.end();
@@ -566,6 +641,24 @@ bool LLXMLNode::updateNode(
}
+// static
+LLXMLNodePtr LLXMLNode::replaceNode(LLXMLNodePtr node, LLXMLNodePtr update_node)
+{
+ if (!node || !update_node)
+ {
+ llwarns << "Node invalid" << llendl;
+ return node;
+ }
+
+ LLXMLNodePtr cloned_node = update_node->deepCopy();
+ node->mParent->addChild(cloned_node, node); // add after node
+ LLXMLNodePtr parent = node->mParent;
+ parent->removeChild(node);
+ parent->updateDefault();
+
+ return cloned_node;
+}
+
// static
@@ -618,7 +711,7 @@ bool LLXMLNode::parseBuffer(
{
llwarns << "Error parsing xml error code: "
<< XML_ErrorString(XML_GetErrorCode(my_parser))
- << " on lne " << XML_GetCurrentLineNumber(my_parser)
+ << " on line " << XML_GetCurrentLineNumber(my_parser)
<< llendl;
}
@@ -722,7 +815,7 @@ BOOL LLXMLNode::isFullyDefault()
&& has_default_length
&& has_default_attribute)
{
- if (mChildren)
+ if (mChildren.notNull())
{
LLXMLChildList::const_iterator children_itr;
LLXMLChildList::const_iterator children_end = mChildren->map.end();
@@ -888,7 +981,7 @@ void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& i
}
}
- if (!mChildren && mValue == "")
+ if (mChildren.isNull() && mValue == "")
{
output_stream << " />\n";
return;
@@ -896,7 +989,7 @@ void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& i
else
{
output_stream << ">\n";
- if (mChildren)
+ if (mChildren.notNull())
{
// stream non-attributes
std::string next_indent = indent + "\t";
@@ -922,7 +1015,7 @@ void LLXMLNode::findName(const std::string& name, LLXMLNodeList &results)
results.insert(std::make_pair(this->mName->mString, this));
return;
}
- if (mChildren)
+ if (mChildren.notNull())
{
LLXMLChildList::const_iterator children_itr;
LLXMLChildList::const_iterator children_end = mChildren->map.end();
@@ -941,7 +1034,7 @@ void LLXMLNode::findName(LLStringTableEntry* name, LLXMLNodeList &results)
results.insert(std::make_pair(this->mName->mString, this));
return;
}
- if (mChildren)
+ if (mChildren.notNull())
{
LLXMLChildList::const_iterator children_itr;
LLXMLChildList::const_iterator children_end = mChildren->map.end();
@@ -960,7 +1053,7 @@ void LLXMLNode::findID(const std::string& id, LLXMLNodeList &results)
results.insert(std::make_pair(this->mName->mString, this));
return;
}
- if (mChildren)
+ if (mChildren.notNull())
{
LLXMLChildList::const_iterator children_itr;
LLXMLChildList::const_iterator children_end = mChildren->map.end();
@@ -974,11 +1067,11 @@ void LLXMLNode::findID(const std::string& id, LLXMLNodeList &results)
void LLXMLNode::scrubToTree(LLXMLNode *tree)
{
- if (!tree || !tree->mChildren)
+ if (!tree || tree->mChildren.isNull())
{
return;
}
- if (mChildren)
+ if (mChildren.notNull())
{
std::vector<LLXMLNodePtr> to_delete_list;
LLXMLChildList::iterator itor = mChildren->map.begin();
@@ -1023,7 +1116,7 @@ bool LLXMLNode::getChild(const char* name, LLXMLNodePtr& node, BOOL use_default_
bool LLXMLNode::getChild(const LLStringTableEntry* name, LLXMLNodePtr& node, BOOL use_default_if_missing)
{
- if (mChildren)
+ if (mChildren.notNull())
{
LLXMLChildList::const_iterator child_itr = mChildren->map.find(name);
if (child_itr != mChildren->map.end())
@@ -1047,7 +1140,7 @@ void LLXMLNode::getChildren(const char* name, LLXMLNodeList &children, BOOL use_
void LLXMLNode::getChildren(const LLStringTableEntry* name, LLXMLNodeList &children, BOOL use_default_if_missing) const
{
- if (mChildren)
+ if (mChildren.notNull())
{
LLXMLChildList::const_iterator child_itr = mChildren->map.find(name);
if (child_itr != mChildren->map.end())
@@ -1071,6 +1164,25 @@ void LLXMLNode::getChildren(const LLStringTableEntry* name, LLXMLNodeList &child
}
}
+// recursively walks the tree and returns all children at all nesting levels matching the name
+void LLXMLNode::getDescendants(const LLStringTableEntry* name, LLXMLNodeList &children) const
+{
+ if (mChildren.notNull())
+ {
+ for (LLXMLChildList::const_iterator child_itr = mChildren->map.begin();
+ child_itr != mChildren->map.end(); ++child_itr)
+ {
+ LLXMLNodePtr child = (*child_itr).second;
+ if (name == child->mName)
+ {
+ children.insert(std::make_pair(child->mName->mString, child));
+ }
+ // and check each child as well
+ child->getDescendants(name, children);
+ }
+ }
+}
+
bool LLXMLNode::getAttribute(const char* name, LLXMLNodePtr& node, BOOL use_default_if_missing)
{
return getAttribute(gStringTable.checkStringEntry(name), node, use_default_if_missing);
@@ -1111,6 +1223,23 @@ BOOL LLXMLNode::hasAttribute(const char* name )
return getAttribute(name, node);
}
+// the structure of these getAttribute_ functions is ugly, but it's because the
+// underlying system is based on BOOL and LLString; if we change
+// so that they're based on more generic mechanisms, these will be
+// simplified.
+bool LLXMLNode::getAttribute_bool(const char* name, bool& value )
+{
+ LLXMLNodePtr node;
+ if (!getAttribute(name, node))
+ {
+ return false;
+ }
+ BOOL temp;
+ bool retval = node->getBoolValue(1, &temp);
+ value = temp;
+ return retval;
+}
+
BOOL LLXMLNode::getAttributeBOOL(const char* name, BOOL& value )
{
LLXMLNodePtr node;
@@ -2521,7 +2650,7 @@ void LLXMLNode::setName(LLStringTableEntry* name)
U32 LLXMLNode::getChildCount() const
{
- if (mChildren)
+ if (mChildren.notNull())
{
return mChildren->map.size();
}
@@ -2540,7 +2669,7 @@ U32 get_rand(U32 max_value)
LLXMLNode *get_rand_node(LLXMLNode *node)
{
- if (node->mChildren)
+ if (node->mChildren.notNull())
{
U32 num_children = node->mChildren->map.size();
if (get_rand(2) == 0)
@@ -2748,7 +2877,7 @@ void LLXMLNode::createUnitTest(S32 max_num_children)
BOOL LLXMLNode::performUnitTest(std::string &error_buffer)
{
- if (!mChildren)
+ if (mChildren.isNull())
{
error_buffer.append(llformat("ERROR Node %s: No children found.\n", mName->mString));
return FALSE;
@@ -3007,14 +3136,14 @@ BOOL LLXMLNode::performUnitTest(std::string &error_buffer)
return TRUE;
}
-LLXMLNodePtr LLXMLNode::getFirstChild()
+LLXMLNodePtr LLXMLNode::getFirstChild() const
{
- if (!mChildren) return NULL;
+ if (mChildren.isNull()) return NULL;
LLXMLNodePtr ret = mChildren->head;
return ret;
}
-LLXMLNodePtr LLXMLNode::getNextSibling()
+LLXMLNodePtr LLXMLNode::getNextSibling() const
{
LLXMLNodePtr ret = mNext;
return ret;
diff --git a/indra/llxml/llxmlnode.h b/indra/llxml/llxmlnode.h
index 5ca726effe..dec225dde6 100644
--- a/indra/llxml/llxmlnode.h
+++ b/indra/llxml/llxmlnode.h
@@ -87,12 +87,13 @@ class LLVector3d;
class LLVector4;
class LLVector4U;
-struct LLXMLChildren
+struct LLXMLChildren : public LLThreadSafeRefCount
{
LLXMLChildList map; // Map of children names->pointers
LLXMLNodePtr head; // Head of the double-linked list
LLXMLNodePtr tail; // Tail of the double-linked list
};
+typedef LLPointer<LLXMLChildren> LLXMLChildrenPtr;
class LLXMLNode : public LLThreadSafeRefCount
{
@@ -124,11 +125,13 @@ public:
LLXMLNode();
LLXMLNode(const char* name, BOOL is_attribute);
LLXMLNode(LLStringTableEntry* name, BOOL is_attribute);
+ LLXMLNode(const LLXMLNode& rhs);
+ LLXMLNodePtr deepCopy();
BOOL isNull();
BOOL deleteChild(LLXMLNode* child);
- void addChild(LLXMLNodePtr new_parent);
+ void addChild(LLXMLNodePtr new_child, LLXMLNodePtr after_child = LLXMLNodePtr(NULL));
void setParent(LLXMLNodePtr new_parent); // reparent if necessary
// Serialization
@@ -146,8 +149,9 @@ public:
LLXMLNodePtr& node,
LLXMLNode* defaults);
static bool updateNode(
- LLXMLNodePtr& node,
- LLXMLNodePtr& update_node);
+ LLXMLNodePtr& node,
+ LLXMLNodePtr& update_node);
+ static LLXMLNodePtr replaceNode(LLXMLNodePtr node, LLXMLNodePtr replacement_node);
static void writeHeaderToFile(LLFILE *fOut);
void writeToFile(LLFILE *fOut, const std::string& indent = std::string());
void writeToOstream(std::ostream& output_stream, const std::string& indent = std::string());
@@ -176,6 +180,10 @@ public:
BOOL hasAttribute(const char* name );
+ // these are designed to be more generic versions of the functions
+ // rather than relying on LL-types
+ bool getAttribute_bool(const char* name, bool& value );
+
BOOL getAttributeBOOL(const char* name, BOOL& value );
BOOL getAttributeU8(const char* name, U8& value );
BOOL getAttributeS8(const char* name, S8& value );
@@ -211,13 +219,16 @@ public:
bool getChild(const LLStringTableEntry* name, LLXMLNodePtr& node, BOOL use_default_if_missing = TRUE);
void getChildren(const char* name, LLXMLNodeList &children, BOOL use_default_if_missing = TRUE) const;
void getChildren(const LLStringTableEntry* name, LLXMLNodeList &children, BOOL use_default_if_missing = TRUE) const;
+
+ // recursively finds all children at any level matching name
+ void getDescendants(const LLStringTableEntry* name, LLXMLNodeList &children) const;
bool getAttribute(const char* name, LLXMLNodePtr& node, BOOL use_default_if_missing = TRUE);
bool getAttribute(const LLStringTableEntry* name, LLXMLNodePtr& node, BOOL use_default_if_missing = TRUE);
// The following skip over attributes
- LLXMLNodePtr getFirstChild();
- LLXMLNodePtr getNextSibling();
+ LLXMLNodePtr getFirstChild() const;
+ LLXMLNodePtr getNextSibling() const;
LLXMLNodePtr getRoot();
@@ -251,7 +262,6 @@ public:
void setName(LLStringTableEntry* name);
// Escapes " (quot) ' (apos) & (amp) < (lt) > (gt)
- // TomY TODO: Make this private
static std::string escapeXML(const std::string& xml);
// Set the default node corresponding to this default node
@@ -291,7 +301,7 @@ public:
Encoding mEncoding; // The value encoding
LLXMLNode* mParent; // The parent node
- LLXMLChildren* mChildren; // The child nodes
+ LLXMLChildrenPtr mChildren; // The child nodes
LLXMLAttribList mAttributes; // The attribute nodes
LLXMLNodePtr mPrev; // Double-linked list previous node
LLXMLNodePtr mNext; // Double-linked list next node
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 21e491e1b5..0be8b53d41 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -169,6 +169,7 @@ set(viewer_SOURCE_FILES
llfloatermute.cpp
llfloaternamedesc.cpp
llfloaternewim.cpp
+ llfloaternotificationsconsole.cpp
llfloaterobjectiminfo.cpp
llfloateropenobject.cpp
llfloaterparcel.cpp
@@ -570,6 +571,7 @@ set(viewer_HEADER_FILES
llfloatermute.h
llfloaternamedesc.h
llfloaternewim.h
+ llfloaternotificationsconsole.h
llfloaterobjectiminfo.h
llfloateropenobject.h
llfloaterparcel.h
@@ -1091,6 +1093,8 @@ set(viewer_XUI_FILES
skins/default/xui/en-us/floater_name_description.xml
skins/default/xui/en-us/floater_new_im.xml
skins/default/xui/en-us/floater_new_outfit_dialog.xml
+ skins/default/xui/en-us/floater_notifications_console.xml
+ skins/default/xui/en-us/floater_notification.xml
skins/default/xui/en-us/floater_object_im_info.xml
skins/default/xui/en-us/floater_openobject.xml
skins/default/xui/en-us/floater_pay_object.xml
@@ -1149,6 +1153,7 @@ set(viewer_XUI_FILES
skins/default/xui/en-us/menu_slurl.xml
skins/default/xui/en-us/menu_viewer.xml
skins/default/xui/en-us/mime_types.xml
+ skins/default/xui/en-us/notifications.xml
skins/default/xui/en-us/notify.xml
skins/default/xui/en-us/panel_audio_device.xml
skins/default/xui/en-us/panel_audio.xml
@@ -1177,6 +1182,7 @@ set(viewer_XUI_FILES
skins/default/xui/en-us/panel_media_controls.xml
skins/default/xui/en-us/panel_media_remote_expanded.xml
skins/default/xui/en-us/panel_media_remote.xml
+ skins/default/xui/en-us/panel_notifications_channel.xml
skins/default/xui/en-us/panel_overlaybar.xml
skins/default/xui/en-us/panel_place_small.xml
skins/default/xui/en-us/panel_place.xml
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 13fc165010..b2f9f0a2ca 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -55,6 +55,17 @@
<real>1.0</real>
</array>
</map>
+ <key>AlertedUnsupportedHardware</key>
+ <map>
+ <key>Comment</key>
+ <string>Set if there's unsupported hardware and we've already done a notification.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>0</integer>
+ </map>
<key>AllowIdleAFK</key>
<map>
<key>Comment</key>
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 7eca956f7d..55b74abd62 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -583,7 +583,7 @@ void LLAgent::onAppFocusGained()
void LLAgent::ageChat()
{
- if (mAvatarObject)
+ if (mAvatarObject.notNull())
{
// get amount of time since I last chatted
F64 elapsed_time = (F64)mAvatarObject->mChatTimer.getElapsedTimeF32();
@@ -600,7 +600,7 @@ void LLAgent::unlockView()
{
if (getFocusOnAvatar())
{
- if (mAvatarObject)
+ if (mAvatarObject.notNull())
{
setFocusGlobal( LLVector3d::zero, mAvatarObject->mID );
}
@@ -1017,7 +1017,7 @@ void LLAgent::sendReliableMessage()
//-----------------------------------------------------------------------------
LLVector3 LLAgent::getVelocity() const
{
- if (mAvatarObject)
+ if (mAvatarObject.notNull())
{
return mAvatarObject->getVelocity();
}
@@ -1038,7 +1038,7 @@ void LLAgent::setPositionAgent(const LLVector3 &pos_agent)
llerrs << "setPositionAgent is not a number" << llendl;
}
- if (!mAvatarObject.isNull() && mAvatarObject->getParent())
+ if (mAvatarObject.notNull() && mAvatarObject->getParent())
{
LLVector3 pos_agent_sitting;
LLVector3d pos_agent_d;
@@ -1076,7 +1076,7 @@ void LLAgent::slamLookAt(const LLVector3 &look_at)
//-----------------------------------------------------------------------------
const LLVector3d &LLAgent::getPositionGlobal() const
{
- if (!mAvatarObject.isNull() && !mAvatarObject->mDrawable.isNull())
+ if (mAvatarObject.notNull() && !mAvatarObject->mDrawable.isNull())
{
mPositionGlobal = getPosGlobalFromAgent(mAvatarObject->getRenderPosition());
}
@@ -1093,7 +1093,7 @@ const LLVector3d &LLAgent::getPositionGlobal() const
//-----------------------------------------------------------------------------
const LLVector3 &LLAgent::getPositionAgent()
{
- if(!mAvatarObject.isNull() && !mAvatarObject->mDrawable.isNull())
+ if(mAvatarObject.notNull() && !mAvatarObject->mDrawable.isNull())
{
mFrameAgent.setOrigin(mAvatarObject->getRenderPosition());
}
@@ -2345,11 +2345,11 @@ void LLAgent::stopAutoPilot(BOOL user_cancel)
if (user_cancel && !mAutoPilotBehaviorName.empty())
{
if (mAutoPilotBehaviorName == "Sit")
- LLNotifyBox::showXml("CancelledSit");
+ LLNotifications::instance().add("CancelledSit");
else if (mAutoPilotBehaviorName == "Attach")
- LLNotifyBox::showXml("CancelledAttach");
+ LLNotifications::instance().add("CancelledAttach");
else
- LLNotifyBox::showXml("Cancelled");
+ LLNotifications::instance().add("Cancelled");
}
}
}
@@ -2374,7 +2374,7 @@ void LLAgent::autoPilot(F32 *delta_yaw)
mAutoPilotTargetGlobal = object->getPositionGlobal();
}
- if (!mAvatarObject)
+ if (mAvatarObject.isNull())
{
return;
}
@@ -2455,7 +2455,7 @@ void LLAgent::autoPilot(F32 *delta_yaw)
// If we're flying, handle autopilot points above or below you.
if (getFlying() && xy_distance < AUTOPILOT_HEIGHT_ADJUST_DISTANCE)
{
- if (mAvatarObject)
+ if (mAvatarObject.notNull())
{
F64 current_height = mAvatarObject->getPositionGlobal().mdV[VZ];
F32 delta_z = (F32)(mAutoPilotTargetGlobal.mdV[VZ] - current_height);
@@ -2540,7 +2540,7 @@ void LLAgent::propagate(const F32 dt)
pitch(PITCH_RATE * (F32) mPitchKey * dt);
// handle auto-land behavior
- if (mAvatarObject)
+ if (mAvatarObject.notNull())
{
BOOL in_air = mAvatarObject->mInAir;
LLVector3 land_vel = getVelocity();
@@ -2591,7 +2591,7 @@ void LLAgent::updateLookAt(const S32 mouse_x, const S32 mouse_y)
static LLVector3 last_at_axis;
- if ( mAvatarObject.isNull() )
+ if (mAvatarObject.isNull())
{
return;
}
@@ -2864,7 +2864,7 @@ void LLAgent::endAnimationUpdateUI()
}
// Disable mouselook-specific animations
- if (mAvatarObject)
+ if (mAvatarObject.notNull())
{
if( mAvatarObject->isAnyAnimationSignaled(AGENT_GUN_AIM_ANIMS, NUM_AGENT_GUN_AIM_ANIMS) )
{
@@ -2910,7 +2910,7 @@ void LLAgent::endAnimationUpdateUI()
gMorphView->setVisible( FALSE );
}
- if (mAvatarObject)
+ if (mAvatarObject.notNull())
{
if(mCustomAnim)
{
@@ -2953,7 +2953,7 @@ void LLAgent::endAnimationUpdateUI()
gIMMgr->setFloaterOpen( FALSE );
gConsole->setVisible( TRUE );
- if (mAvatarObject)
+ if (mAvatarObject.notNull())
{
// Trigger mouselook-specific animations
if( mAvatarObject->isAnyAnimationSignaled(AGENT_GUN_HOLD_ANIMS, NUM_AGENT_GUN_HOLD_ANIMS) )
@@ -3014,7 +3014,7 @@ void LLAgent::endAnimationUpdateUI()
}
// freeze avatar
- if (mAvatarObject)
+ if (mAvatarObject.notNull())
{
mPauseRequest = mAvatarObject->requestPause();
}
@@ -3048,7 +3048,7 @@ void LLAgent::updateCamera()
validateFocusObject();
- if (!mAvatarObject.isNull() &&
+ if (mAvatarObject.notNull() &&
mAvatarObject->mIsSitting &&
camera_mode == CAMERA_MODE_MOUSELOOK)
{
@@ -3162,7 +3162,7 @@ void LLAgent::updateCamera()
//Ventrella
if ( mCameraMode == CAMERA_MODE_FOLLOW )
{
- if ( !mAvatarObject.isNull() )
+ if ( mAvatarObject.notNull() )
{
//--------------------------------------------------------------------------------
// this is where the avatar's position and rotation are given to followCam, and
@@ -3472,7 +3472,7 @@ LLVector3d LLAgent::calcFocusPositionTargetGlobal()
{
LLVector3d at_axis(1.0, 0.0, 0.0);
LLQuaternion agent_rot = mFrameAgent.getQuaternion();
- if (!mAvatarObject.isNull() && mAvatarObject->getParent())
+ if (mAvatarObject.notNull() && mAvatarObject->getParent())
{
LLViewerObject* root_object = (LLViewerObject*)mAvatarObject->getRoot();
if (!root_object->flagCameraDecoupled())
@@ -3770,7 +3770,7 @@ LLVector3d LLAgent::calcCameraPositionTargetGlobal(BOOL *hit_limit)
camera_offset.setVec( local_camera_offset );
camera_position_global = frame_center_global + head_offset + camera_offset;
- if (!mAvatarObject.isNull())
+ if (mAvatarObject.notNull())
{
LLVector3d camera_lag_d;
F32 lag_interp = LLCriticalDamp::getInterpolant(CAMERA_LAG_HALF_LIFE);
@@ -4001,7 +4001,7 @@ void LLAgent::changeCameraToMouselook(BOOL animate)
gSavedSettings.setBOOL("ThirdPersonBtnState", FALSE);
gSavedSettings.setBOOL("BuildBtnState", FALSE);
- if (mAvatarObject)
+ if (mAvatarObject.notNull())
{
mAvatarObject->stopMotion( ANIM_AGENT_BODY_NOISE );
mAvatarObject->stopMotion( ANIM_AGENT_BREATHE_ROT );
@@ -4089,7 +4089,7 @@ void LLAgent::changeCameraToFollow(BOOL animate)
LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset);
}
- if (mAvatarObject)
+ if (mAvatarObject.notNull())
{
mAvatarObject->mPelvisp->setPosition(LLVector3::zero);
mAvatarObject->startMotion( ANIM_AGENT_BODY_NOISE );
@@ -4137,7 +4137,7 @@ void LLAgent::changeCameraToThirdPerson(BOOL animate)
mCameraZoomFraction = INITIAL_ZOOM_FRACTION;
- if (mAvatarObject)
+ if (mAvatarObject.notNull())
{
if (!mAvatarObject->mIsSitting)
{
@@ -4183,7 +4183,7 @@ void LLAgent::changeCameraToThirdPerson(BOOL animate)
}
// Remove any pitch from the avatar
- if (!mAvatarObject.isNull() && mAvatarObject->getParent())
+ if (mAvatarObject.notNull() && mAvatarObject->getParent())
{
LLQuaternion obj_rot = ((LLViewerObject*)mAvatarObject->getParent())->getRenderRotation();
at_axis = LLViewerCamera::getInstance()->getAtAxis();
@@ -4262,7 +4262,7 @@ void LLAgent::changeCameraToCustomizeAvatar(BOOL avatar_animate, BOOL camera_ani
LLVOAvatar::onCustomizeStart();
}
- if (!mAvatarObject.isNull())
+ if (mAvatarObject.notNull())
{
if(avatar_animate)
{
@@ -4362,7 +4362,7 @@ void LLAgent::setFocusGlobal(const LLVector3d& focus, const LLUUID &object_id)
{
if (focus.isExactlyZero())
{
- if (!mAvatarObject.isNull())
+ if (mAvatarObject.notNull())
{
mFocusTargetGlobal = getPosGlobalFromAgent(mAvatarObject->mHeadp->getWorldPosition());
}
@@ -4407,7 +4407,7 @@ void LLAgent::setFocusGlobal(const LLVector3d& focus, const LLUUID &object_id)
{
if (focus.isExactlyZero())
{
- if (!mAvatarObject.isNull())
+ if (mAvatarObject.notNull())
{
mFocusTargetGlobal = getPosGlobalFromAgent(mAvatarObject->mHeadp->getWorldPosition());
}
@@ -4544,7 +4544,7 @@ void LLAgent::setFocusOnAvatar(BOOL focus_on_avatar, BOOL animate)
if (mCameraMode == CAMERA_MODE_THIRD_PERSON)
{
LLVector3 at_axis;
- if (!mAvatarObject.isNull() && mAvatarObject->getParent())
+ if (mAvatarObject.notNull() && mAvatarObject->getParent())
{
LLQuaternion obj_rot = ((LLViewerObject*)mAvatarObject->getParent())->getRenderRotation();
at_axis = LLViewerCamera::getInstance()->getAtAxis();
@@ -4611,7 +4611,7 @@ void LLAgent::lookAtLastChat()
if (chatter->isAvatar())
{
LLVOAvatar *chatter_av = (LLVOAvatar*)chatter;
- if (!mAvatarObject.isNull() && chatter_av->mHeadp)
+ if (mAvatarObject.notNull() && chatter_av->mHeadp)
{
delta_pos = chatter_av->mHeadp->getWorldPosition() - mAvatarObject->mHeadp->getWorldPosition();
}
@@ -4692,7 +4692,7 @@ void LLAgent::setStartPosition( U32 location_id )
LLVector3 agent_pos = getPositionAgent();
LLVector3 agent_look_at = mFrameAgent.getAtAxis();
- if (mAvatarObject)
+ if (mAvatarObject.notNull())
{
// the z height is at the agent's feet
agent_pos.mV[VZ] -= 0.5f * mAvatarObject->mBodySize.mV[VZ];
@@ -4853,7 +4853,7 @@ void LLAgent::setTeen(bool teen)
void LLAgent::buildFullname(std::string& name) const
{
- if (mAvatarObject)
+ if (mAvatarObject.notNull())
{
name = mAvatarObject->getFullname();
}
@@ -4871,7 +4871,7 @@ void LLAgent::buildFullnameAndTitle(std::string& name) const
name.erase(0, name.length());
}
- if (mAvatarObject)
+ if (mAvatarObject.notNull())
{
name += mAvatarObject->getFullname();
}
@@ -5226,7 +5226,7 @@ void LLAgent::getName(std::string& name)
{
name.clear();
- if (mAvatarObject)
+ if (mAvatarObject.notNull())
{
LLNameValue *first_nv = mAvatarObject->getNVPair("FirstName");
LLNameValue *last_nv = mAvatarObject->getNVPair("LastName");
@@ -6726,7 +6726,7 @@ void LLAgent::onInitialWearableAssetArrived( LLWearable* wearable, void* userdat
void LLAgent::recoverMissingWearable( EWearableType type )
{
// Try to recover by replacing missing wearable with a new one.
- LLNotifyBox::showXml("ReplacedMissingWearable");
+ LLNotifications::instance().add("ReplacedMissingWearable");
lldebugs << "Wearable " << LLWearable::typeToTypeLabel( type ) << " could not be downloaded. Replaced inventory item with default wearable." << llendl;
LLWearable* new_wearable = gWearableList.createNewWearable(type);
@@ -7157,8 +7157,10 @@ void LLAgent::removeWearable( EWearableType type )
{
if( old_wearable->isDirty() )
{
+ LLSD payload;
+ payload["wearable_type"] = (S32)type;
// Bring up view-modal dialog: Save changes? Yes, No, Cancel
- gViewerWindow->alertXml("WearableSave", LLAgent::onRemoveWearableDialog, (void*)type );
+ LLNotifications::instance().add("WearableSave", LLSD(), payload, &LLAgent::onRemoveWearableDialog);
return;
}
else
@@ -7169,9 +7171,10 @@ void LLAgent::removeWearable( EWearableType type )
}
// static
-void LLAgent::onRemoveWearableDialog( S32 option, void* userdata )
+bool LLAgent::onRemoveWearableDialog(const LLSD& notification, const LLSD& response )
{
- EWearableType type = (EWearableType)(intptr_t)userdata;
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ EWearableType type = (EWearableType)notification["payload"]["wearable_type"].asInteger();
switch( option )
{
case 0: // "Save"
@@ -7190,6 +7193,7 @@ void LLAgent::onRemoveWearableDialog( S32 option, void* userdata )
llassert(0);
break;
}
+ return false;
}
// Called by removeWearable() and onRemoveWearableDialog() to actually do the removal.
@@ -7388,8 +7392,9 @@ void LLAgent::setWearable( LLInventoryItem* new_item, LLWearable* new_wearable )
if( old_wearable->isDirty() )
{
// Bring up modal dialog: Save changes? Yes, No, Cancel
- gViewerWindow->alertXml( "WearableSave", LLAgent::onSetWearableDialog,
- new LLSetWearableData( new_item->getUUID(), new_wearable ));
+ LLSD payload;
+ payload["item_id"] = new_item->getUUID();
+ LLNotifications::instance().add( "WearableSave", LLSD(), payload, boost::bind(LLAgent::onSetWearableDialog, _1, _2, new_wearable));
return;
}
}
@@ -7398,25 +7403,25 @@ void LLAgent::setWearable( LLInventoryItem* new_item, LLWearable* new_wearable )
}
// static
-void LLAgent::onSetWearableDialog( S32 option, void* userdata )
+bool LLAgent::onSetWearableDialog( const LLSD& notification, const LLSD& response, LLWearable* wearable )
{
- LLSetWearableData* data = (LLSetWearableData*)userdata;
- LLInventoryItem* new_item = gInventory.getItem( data->mNewItemID );
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ LLInventoryItem* new_item = gInventory.getItem( notification["payload"]["item_id"].asUUID());
if( !new_item )
{
- delete data;
- return;
+ delete wearable;
+ return false;
}
switch( option )
{
case 0: // "Save"
- gAgent.saveWearable( data->mNewWearable->getType() );
- gAgent.setWearableFinal( new_item, data->mNewWearable );
+ gAgent.saveWearable( wearable->getType() );
+ gAgent.setWearableFinal( new_item, wearable );
break;
case 1: // "Don't Save"
- gAgent.setWearableFinal( new_item, data->mNewWearable );
+ gAgent.setWearableFinal( new_item, wearable );
break;
case 2: // "Cancel"
@@ -7427,7 +7432,8 @@ void LLAgent::onSetWearableDialog( S32 option, void* userdata )
break;
}
- delete data;
+ delete wearable;
+ return false;
}
// Called from setWearable() and onSetWearableDialog() to actually set the wearable.
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index f561f55e46..f1e0bc9308 100644
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -591,10 +591,8 @@ public:
//--------------------------------------------------------------------
// Wearables
//--------------------------------------------------------------------
- BOOL getWearablesLoaded() const { return mWearablesLoaded; }
-
void setWearable( LLInventoryItem* new_item, LLWearable* wearable );
- static void onSetWearableDialog( S32 option, void* userdata );
+ static bool onSetWearableDialog( const LLSD& notification, const LLSD& response, LLWearable* wearable );
void setWearableFinal( LLInventoryItem* new_item, LLWearable* new_wearable );
void setWearableOutfit( const LLInventoryItem::item_array_t& items, const LLDynamicArray< LLWearable* >& wearables, BOOL remove );
void queryWearableCache();
@@ -624,7 +622,7 @@ public:
void makeNewOutfitDone(S32 index);
void removeWearable( EWearableType type );
- static void onRemoveWearableDialog( S32 option, void* userdata );
+ static bool onRemoveWearableDialog(const LLSD& notification, const LLSD& response );
void removeWearableFinal( EWearableType type );
void sendAgentWearablesUpdate();
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index b8b08855a8..54fdcc3894 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -652,6 +652,7 @@ bool LLAppViewer::init()
// Widget construction depends on LLUI being initialized
LLUI::initClass(&gSavedSettings,
+ &gSavedSettings,
&gColors,
LLUIImageList::getInstance(),
ui_audio_callback,
@@ -663,7 +664,7 @@ bool LLAppViewer::init()
&LLURLDispatcher::dispatchFromTextEditor);
LLUICtrlFactory::getInstance()->setupPaths(); // update paths with correct language set
-
+
/////////////////////////////////////////////////
//
// Load settings files
@@ -736,7 +737,10 @@ bool LLAppViewer::init()
//
initWindow();
-#if LL_LCD_COMPILE
+ // call all self-registered classes
+ LLInitClassList::instance().fireCallbacks();
+
+ #if LL_LCD_COMPILE
// start up an LCD window on a logitech keyboard, if there is one
HINSTANCE hInstance = GetModuleHandle(NULL);
gLcdScreen = new LLLCD(hInstance);
@@ -762,64 +766,67 @@ bool LLAppViewer::init()
// If we don't have the right GL requirements, exit.
if (!gGLManager.mHasRequirements && !gNoRender)
{
- // can't use an alert here since we're existing and
+ // can't use an alert here since we're exiting and
// all hell breaks lose.
OSMessageBox(
- LLAlertDialog::getTemplateMessage("UnsupportedGLRequirements"),
+ LLNotifications::instance().getGlobalString("UnsupportedGLRequirements"),
LLStringUtil::null,
OSMB_OK);
return 0;
}
-
- bool unsupported = false;
- LLStringUtil::format_map_t args;
- std::string minSpecs;
-
- // get cpu data from xml
- std::stringstream minCPUString(LLAlertDialog::getTemplateMessage("UnsupportedCPUAmount"));
- S32 minCPU = 0;
- minCPUString >> minCPU;
-
- // get RAM data from XML
- std::stringstream minRAMString(LLAlertDialog::getTemplateMessage("UnsupportedRAMAmount"));
- U64 minRAM = 0;
- minRAMString >> minRAM;
- minRAM = minRAM * 1024 * 1024;
-
- if(!LLFeatureManager::getInstance()->isGPUSupported() && LLFeatureManager::getInstance()->getGPUClass() != GPU_CLASS_UNKNOWN)
- {
- minSpecs += LLAlertDialog::getTemplateMessage("UnsupportedGPU");
- minSpecs += "\n";
- unsupported = true;
- }
- if(gSysCPU.getMhz() < minCPU)
- {
- minSpecs += LLAlertDialog::getTemplateMessage("UnsupportedCPU");
- minSpecs += "\n";
- unsupported = true;
- }
- if(gSysMemory.getPhysicalMemoryClamped() < minRAM)
- {
- minSpecs += LLAlertDialog::getTemplateMessage("UnsupportedRAM");
- minSpecs += "\n";
- unsupported = true;
- }
-
- if (LLFeatureManager::getInstance()->getGPUClass() == GPU_CLASS_UNKNOWN)
+ // alert the user if they are using unsupported hardware
+ if(!gSavedSettings.getBOOL("AlertedUnsupportedHardware"))
{
- gViewerWindow->alertXml("UnknownGPU");
- }
+ bool unsupported = false;
+ LLSD args;
+ std::string minSpecs;
- if(unsupported)
- {
- if(!gSavedSettings.controlExists("WarnUnsupportedHardware")
- || gSavedSettings.getBOOL("WarnUnsupportedHardware"))
+ // get cpu data from xml
+ std::stringstream minCPUString(LLNotifications::instance().getGlobalString("UnsupportedCPUAmount"));
+ S32 minCPU = 0;
+ minCPUString >> minCPU;
+
+ // get RAM data from XML
+ std::stringstream minRAMString(LLNotifications::instance().getGlobalString("UnsupportedRAMAmount"));
+ U64 minRAM = 0;
+ minRAMString >> minRAM;
+ minRAM = minRAM * 1024 * 1024;
+
+ if(!LLFeatureManager::getInstance()->isGPUSupported() && LLFeatureManager::getInstance()->getGPUClass() != GPU_CLASS_UNKNOWN)
+ {
+ minSpecs += LLNotifications::instance().getGlobalString("UnsupportedGPU");
+ minSpecs += "\n";
+ unsupported = true;
+ }
+ if(gSysCPU.getMhz() < minCPU)
+ {
+ minSpecs += LLNotifications::instance().getGlobalString("UnsupportedCPU");
+ minSpecs += "\n";
+ unsupported = true;
+ }
+ if(gSysMemory.getPhysicalMemoryClamped() < minRAM)
{
- args["MINSPECS"] = minSpecs;
- gViewerWindow->alertXml("UnsupportedHardware", args );
+ minSpecs += LLNotifications::instance().getGlobalString("UnsupportedRAM");
+ minSpecs += "\n";
+ unsupported = true;
}
+ if (LLFeatureManager::getInstance()->getGPUClass() == GPU_CLASS_UNKNOWN)
+ {
+ LLNotifications::instance().add("UnknownGPU");
+ }
+
+ if(unsupported)
+ {
+ if(!gSavedSettings.controlExists("WarnUnsupportedHardware")
+ || gSavedSettings.getBOOL("WarnUnsupportedHardware"))
+ {
+ args["MINSPECS"] = minSpecs;
+ LLNotifications::instance().add("UnsupportedHardware", args );
+ }
+
+ }
}
// save the graphics card
@@ -1153,8 +1160,6 @@ bool LLAppViewer::cleanup()
// Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be deleted.
- LLNotifyBox::cleanup();
-
LLWorldMap::getInstance()->reset(); // release any images
llinfos << "Global stuff deleted" << llendflush;
@@ -1705,25 +1710,6 @@ bool LLAppViewer::initConfiguration()
LLFirstUse::addConfigVariable("FirstVoice");
LLFirstUse::addConfigVariable("FirstMedia");
- //////
- // *FIX:Mani - Find a way to remove the gUICtrlFactory and
- // LLAlertDialog::parseAlerts dependecies on the being loaded
- // *before* the user settings. Having to do this init here
- // seems odd.
-
- // This is where gUICtrlFactory used to be instantiated with a new LLUICtrlFactory
- // which needed to happen before calling parseAlerts below.
- // TODO: That method is still dependant upon the base LLUICtrlFactory constructor being called
- // which registers some callbacks so I'm leaving in a call to getInstance here to cause that to
- // still happen. This needs to be cleaned up later when the base and derived classes
- // are planned to be combined. -MG
- LLUICtrlFactory::getInstance();
-
-
- // Pre-load alerts.xml to define the warnings settings (always loads from skins/xui/en-us/)
- // Do this *before* loading the settings file
- LLAlertDialog::parseAlerts("alerts.xml", &gSavedSettings, TRUE);
-
// - read command line settings.
LLControlGroupCLP clp;
std::string cmd_line_config = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,
@@ -2151,8 +2137,6 @@ bool LLAppViewer::initWindow()
LLUI::sWindow = gViewerWindow->getWindow();
- LLAlertDialog::parseAlerts("alerts.xml");
- LLNotifyBox::parseNotify("notify.xml");
LLTrans::parseStrings("strings.xml");
// Show watch cursor
@@ -2614,32 +2598,34 @@ void LLAppViewer::requestQuit()
mQuitRequested = true;
}
-static void finish_quit(S32 option, void *userdata)
+static bool finish_quit(const LLSD& notification, const LLSD& response)
{
+ S32 option = LLNotification::getSelectedOption(notification, response);
+
if (option == 0)
{
LLAppViewer::instance()->requestQuit();
}
+ return false;
}
+static LLNotificationFunctorRegistration finish_quit_reg("ConfirmQuit", finish_quit);
void LLAppViewer::userQuit()
{
- gViewerWindow->alertXml("ConfirmQuit", finish_quit, NULL);
+ LLNotifications::instance().add("ConfirmQuit");
}
-static void finish_early_exit(S32 option, void* userdata)
+static bool finish_early_exit(const LLSD& notification, const LLSD& response)
{
LLAppViewer::instance()->forceQuit();
+ return false;
}
-void LLAppViewer::earlyExit(const std::string& msg)
+void LLAppViewer::earlyExit(const std::string& name, const LLSD& substitutions)
{
- llwarns << "app_early_exit: " << msg << llendl;
+ llwarns << "app_early_exit: " << name << llendl;
gDoDisconnect = TRUE;
-// LLStringUtil::format_map_t args;
-// args["[MESSAGE]"] = mesg;
-// gViewerWindow->alertXml("AppEarlyExit", args, finish_early_exit);
- LLAlertDialog::showCritical(msg, finish_early_exit, NULL);
+ LLNotifications::instance().add(name, substitutions, LLSD(), finish_early_exit);
}
void LLAppViewer::forceExit(S32 arg)
@@ -2953,18 +2939,22 @@ const std::string& LLAppViewer::getWindowTitle() const
}
// Callback from a dialog indicating user was logged out.
-void finish_disconnect(S32 option, void* userdata)
+bool finish_disconnect(const LLSD& notification, const LLSD& response)
{
+ S32 option = LLNotification::getSelectedOption(notification, response);
+
if (1 == option)
{
LLAppViewer::instance()->forceQuit();
}
+ return false;
}
// Callback from an early disconnect dialog, force an exit
-void finish_forced_disconnect(S32 /* option */, void* /* userdata */)
+bool finish_forced_disconnect(const LLSD& notification, const LLSD& response)
{
LLAppViewer::instance()->forceQuit();
+ return false;
}
@@ -2984,19 +2974,19 @@ void LLAppViewer::forceDisconnect(const std::string& mesg)
big_reason = mesg;
}
- LLStringUtil::format_map_t args;
+ LLSD args;
gDoDisconnect = TRUE;
if (LLStartUp::getStartupState() < STATE_STARTED)
{
// Tell users what happened
- args["[ERROR_MESSAGE]"] = big_reason;
- gViewerWindow->alertXml("ErrorMessage", args, finish_forced_disconnect);
+ args["ERROR_MESSAGE"] = big_reason;
+ LLNotifications::instance().add("ErrorMessage", args, LLSD(), &finish_forced_disconnect);
}
else
{
- args["[MESSAGE]"] = big_reason;
- gViewerWindow->alertXml("YouHaveBeenLoggedOut", args, finish_disconnect );
+ args["MESSAGE"] = big_reason;
+ LLNotifications::instance().add("YouHaveBeenLoggedOut", args, LLSD(), &finish_disconnect );
}
}
@@ -3763,6 +3753,9 @@ void LLAppViewer::disconnectViewer()
// Now we just ask the LLWorld singleton to cleanly shut down.
LLWorld::getInstance()->destroyClass();
+ // call all self-registered classes
+ LLDestroyClassList::instance().fireCallbacks();
+
cleanup_xfer_manager();
gDisconnected = TRUE;
}
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index 41081237c7..f8940322c5 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -63,7 +63,8 @@ public:
void forceQuit(); // Puts the viewer into 'shutting down without error' mode.
void requestQuit(); // Request a quit. A kinder, gentler quit.
void userQuit(); // The users asks to quit. Confirm, then requestQuit()
- void earlyExit(const std::string& msg); // Display an error dialog and forcibly quit.
+ void earlyExit(const std::string& name,
+ const LLSD& substitutions = LLSD()); // Display an error dialog and forcibly quit.
void forceExit(S32 arg); // exit() immediately (after some cleanup).
void abortQuit(); // Called to abort a quit request.
diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp
index d25f827a72..a90532b451 100644
--- a/indra/newview/llassetuploadresponders.cpp
+++ b/indra/newview/llassetuploadresponders.cpp
@@ -102,21 +102,21 @@ void LLAssetUploadResponder::error(U32 statusNum, const std::string& reason)
{
llinfos << "LLAssetUploadResponder::error " << statusNum
<< " reason: " << reason << llendl;
- LLStringUtil::format_map_t args;
+ LLSD args;
switch(statusNum)
{
case 400:
- args["[FILE]"] = (mFileName.empty() ? mVFileID.asString() : mFileName);
- args["[REASON]"] = "Error in upload request. Please visit "
+ args["FILE"] = (mFileName.empty() ? mVFileID.asString() : mFileName);
+ args["REASON"] = "Error in upload request. Please visit "
"http://secondlife.com/support for help fixing this problem.";
- gViewerWindow->alertXml("CannotUploadReason", args);
+ LLNotifications::instance().add("CannotUploadReason", args);
break;
case 500:
default:
- args["[FILE]"] = (mFileName.empty() ? mVFileID.asString() : mFileName);
- args["[REASON]"] = "The server is experiencing unexpected "
+ args["FILE"] = (mFileName.empty() ? mVFileID.asString() : mFileName);
+ args["REASON"] = "The server is experiencing unexpected "
"difficulties.";
- gViewerWindow->alertXml("CannotUploadReason", args);
+ LLNotifications::instance().add("CannotUploadReason", args);
break;
}
LLUploadDialog::modalUploadFinished();
@@ -171,10 +171,10 @@ void LLAssetUploadResponder::uploadFailure(const LLSD& content)
}
else
{
- LLStringUtil::format_map_t args;
- args["[FILE]"] = (mFileName.empty() ? mVFileID.asString() : mFileName);
- args["[REASON]"] = content["message"].asString();
- gViewerWindow->alertXml("CannotUploadReason", args);
+ LLSD args;
+ args["FILE"] = (mFileName.empty() ? mVFileID.asString() : mFileName);
+ args["REASON"] = content["message"].asString();
+ LLNotifications::instance().add("CannotUploadReason", args);
}
}
@@ -220,9 +220,9 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content)
gMessageSystem->addUUIDFast(_PREHASH_TransactionID, LLUUID::null );
gAgent.sendReliableMessage();
- LLStringUtil::format_map_t args;
- args["[AMOUNT]"] = llformat("%d",LLGlobalEconomy::Singleton::getInstance()->getPriceUpload());
- LLNotifyBox::showXml("UploadPayment", args);
+ LLSD args;
+ args["AMOUNT"] = llformat("%d",LLGlobalEconomy::Singleton::getInstance()->getPriceUpload());
+ LLNotifications::instance().add("UploadPayment", args);
}
// Actually add the upload to viewer inventory
diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp
index 1fdefbac49..2395d1daab 100644
--- a/indra/newview/llcallingcard.cpp
+++ b/indra/newview/llcallingcard.cpp
@@ -592,19 +592,19 @@ void LLAvatarTracker::processChange(LLMessageSystem* msg)
if((mBuddyInfo[agent_id]->getRightsGrantedFrom() ^ new_rights) & LLRelationship::GRANT_MODIFY_OBJECTS)
{
std::string first, last;
- LLStringUtil::format_map_t args;
+ LLSD args;
if(gCacheName->getName(agent_id, first, last))
{
- args["[FIRST_NAME]"] = first;
- args["[LAST_NAME]"] = last;
+ args["FIRST_NAME"] = first;
+ args["LAST_NAME"] = last;
}
if(LLRelationship::GRANT_MODIFY_OBJECTS & new_rights)
{
- gViewerWindow->alertXml("GrantedModifyRights",args);
+ LLNotifications::instance().add("GrantedModifyRights",args);
}
else
{
- gViewerWindow->alertXml("RevokedModifyRights",args);
+ LLNotifications::instance().add("RevokedModifyRights",args);
}
}
(mBuddyInfo[agent_id])->setRightsFrom(new_rights);
@@ -638,7 +638,7 @@ void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online)
tracking_id = mTrackingData->mAvatarID;
}
BOOL notify = FALSE;
- LLStringUtil::format_map_t args;
+ LLSD args;
for(S32 i = 0; i < count; ++i)
{
msg->getUUIDFast(_PREHASH_AgentBlock, _PREHASH_AgentID, agent_id, i);
@@ -652,8 +652,8 @@ void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online)
if(gCacheName->getName(agent_id, first, last))
{
notify = TRUE;
- args["[FIRST]"] = first;
- args["[LAST]"] = last;
+ args["FIRST"] = first;
+ args["LAST"] = last;
}
}
}
@@ -674,14 +674,14 @@ void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online)
if(notify)
{
// Popup a notify box with online status of this agent
- LLNotifyBox::showXml(online ? "FriendOnline" : "FriendOffline", args);
+ LLNotificationPtr notification = LLNotifications::instance().add(online ? "FriendOnline" : "FriendOffline", args);
// If there's an open IM session with this agent, send a notification there too.
LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, agent_id);
LLFloaterIMPanel *floater = gIMMgr->findFloaterBySession(session_id);
if (floater)
{
- LLUIString notifyMsg = LLNotifyBox::getTemplateMessage((online ? "FriendOnline" : "FriendOffline"),args);
+ std::string notifyMsg = notification->getMessage();
if (!notifyMsg.empty())
floater->addHistoryLine(notifyMsg,gSavedSettings.getColor4("SystemChatColor"));
}
diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp
index e9dbc69bce..299a2cc33a 100644
--- a/indra/newview/llcompilequeue.cpp
+++ b/indra/newview/llcompilequeue.cpp
@@ -524,9 +524,9 @@ void LLFloaterCompileQueue::onSaveTextComplete(const LLUUID& asset_id, void* use
if (status)
{
llwarns << "Unable to save text for script." << llendl;
- LLStringUtil::format_map_t args;
- args["[REASON]"] = std::string(LLAssetStorage::getErrorString(status));
- gViewerWindow->alertXml("CompileQueueSaveText", args);
+ LLSD args;
+ args["REASON"] = std::string(LLAssetStorage::getErrorString(status));
+ LLNotifications::instance().add("CompileQueueSaveText", args);
}
}
@@ -545,9 +545,9 @@ void LLFloaterCompileQueue::onSaveBytecodeComplete(const LLUUID& asset_id, void*
else
{
llwarns << "Unable to save bytecode for script." << llendl;
- LLStringUtil::format_map_t args;
- args["[REASON]"] = std::string(LLAssetStorage::getErrorString(status));
- gViewerWindow->alertXml("CompileQueueSaveBytecode", args);
+ LLSD args;
+ args["REASON"] = std::string(LLAssetStorage::getErrorString(status));
+ LLNotifications::instance().add("CompileQueueSaveBytecode", args);
}
delete data;
data = NULL;
diff --git a/indra/newview/llconfirmationmanager.cpp b/indra/newview/llconfirmationmanager.cpp
index 167afb8062..6c465ccf92 100644
--- a/indra/newview/llconfirmationmanager.cpp
+++ b/indra/newview/llconfirmationmanager.cpp
@@ -45,24 +45,22 @@ LLConfirmationManager::ListenerBase::~ListenerBase()
}
-static void onConfirmAlert(S32 option, void* data)
+static bool onConfirmAlert(const LLSD& notification, const LLSD& response, LLConfirmationManager::ListenerBase* listener)
{
- LLConfirmationManager::ListenerBase* listener
- = (LLConfirmationManager::ListenerBase*)data;
-
+ S32 option = LLNotification::getSelectedOption(notification, response);
if (option == 0)
{
listener->confirmed("");
}
delete listener;
+ return false;
}
-static void onConfirmAlertPassword(
- S32 option, const std::string& text, void* data)
+static bool onConfirmAlertPassword(const LLSD& notification, const LLSD& response, LLConfirmationManager::ListenerBase* listener)
{
- LLConfirmationManager::ListenerBase* listener
- = (LLConfirmationManager::ListenerBase*)data;
+ std::string text = response["message"].asString();
+ S32 option = LLNotification::getSelectedOption(notification, response);
if (option == 0)
{
@@ -70,6 +68,7 @@ static void onConfirmAlertPassword(
}
delete listener;
+ return false;
}
@@ -77,22 +76,17 @@ void LLConfirmationManager::confirm(Type type,
const std::string& action,
ListenerBase* listener)
{
- LLStringUtil::format_map_t args;
- args["[ACTION]"] = action;
+ LLSD args;
+ args["ACTION"] = action;
switch (type)
{
case TYPE_CLICK:
- gViewerWindow->alertXml("ConfirmPurchase", args,
- onConfirmAlert, listener);
+ LLNotifications::instance().add("ConfirmPurchase", args, LLSD(), boost::bind(onConfirmAlert, _1, _2, listener));
break;
case TYPE_PASSWORD:
- gViewerWindow->alertXmlEditText("ConfirmPurchasePassword", args,
- NULL, NULL,
- onConfirmAlertPassword, listener,
- LLStringUtil::format_map_t(),
- TRUE);
+ LLNotifications::instance().add("ConfirmPurchasePassword", args, LLSD(), boost::bind(onConfirmAlertPassword, _1, _2, listener));
break;
case TYPE_NONE:
default:
diff --git a/indra/newview/lldelayedgestureerror.cpp b/indra/newview/lldelayedgestureerror.cpp
index 832b1b9130..9799bc1240 100644
--- a/indra/newview/lldelayedgestureerror.cpp
+++ b/indra/newview/lldelayedgestureerror.cpp
@@ -98,18 +98,18 @@ void LLDelayedGestureError::onIdle(void *userdata)
//static
bool LLDelayedGestureError::doDialog(const LLErrorEntry &ent, bool uuid_ok)
{
- LLStringUtil::format_map_t args;
+ LLSD args;
LLInventoryItem *item = gInventory.getItem( ent.mItemID );
if ( item )
{
- args["[NAME]"] = item->getName();
+ args["NAME"] = item->getName();
}
else
{
if ( uuid_ok || ent.mTimer.getElapsedTimeF32() > MAX_NAME_WAIT_TIME )
{
- args["[NAME]"] = std::string( ent.mItemID.asString() );
+ args["NAME"] = ent.mItemID.asString();
}
else
{
@@ -118,7 +118,7 @@ bool LLDelayedGestureError::doDialog(const LLErrorEntry &ent, bool uuid_ok)
}
- LLNotifyBox::showXml(ent.mNotifyName, args);
+ LLNotifications::instance().add(ent.mNotifyName, args);
return true;
}
diff --git a/indra/newview/lleventnotifier.cpp b/indra/newview/lleventnotifier.cpp
index 343a572a6a..59f5cd342b 100644
--- a/indra/newview/lleventnotifier.cpp
+++ b/indra/newview/lleventnotifier.cpp
@@ -77,11 +77,11 @@ void LLEventNotifier::update()
if (np->getEventDate() < (alert_time))
{
- LLStringUtil::format_map_t args;
- args["[NAME]"] = np->getEventName();
- args["[DATE]"] = np->getEventDateStr();
- LLNotifyBox::showXml("EventNotification", args,
- notifyCallback, np);
+ LLSD args;
+ args["NAME"] = np->getEventName();
+ args["DATE"] = np->getEventDateStr();
+ LLNotifications::instance().add("EventNotification", args, LLSD(),
+ boost::bind(&LLEventNotification::handleResponse, np, _1, _2));
mEventNotifications.erase(iter++);
}
else
@@ -173,47 +173,38 @@ void LLEventNotifier::remove(const U32 event_id)
mEventNotifications.erase(iter);
}
-//static
-void LLEventNotifier::notifyCallback(S32 option, void *user_data)
+LLEventNotification::LLEventNotification() :
+ mEventID(0),
+ mEventName("")
{
- LLEventNotification *np = (LLEventNotification *)user_data;
- if (!np)
- {
- llwarns << "Event notification callback without data!" << llendl;
- return;
- }
+}
+
+
+LLEventNotification::~LLEventNotification()
+{
+}
+
+bool LLEventNotification::handleResponse(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotification::getSelectedOption(notification, response);
switch (option)
{
case 0:
- gAgent.teleportViaLocation(np->getEventPosGlobal());
- gFloaterWorldMap->trackLocation(np->getEventPosGlobal());
+ gAgent.teleportViaLocation(getEventPosGlobal());
+ gFloaterWorldMap->trackLocation(getEventPosGlobal());
break;
case 1:
gDisplayEventHack = TRUE;
- LLFloaterDirectory::showEvents(np->getEventID());
+ LLFloaterDirectory::showEvents(getEventID());
break;
case 2:
break;
}
// We could clean up the notification on the server now if we really wanted to.
+ return false;
}
-
-
-LLEventNotification::LLEventNotification() :
- mEventID(0),
- mEventName(""),
- mEventDate(0)
-{
-}
-
-
-LLEventNotification::~LLEventNotification()
-{
-}
-
-
BOOL LLEventNotification::load(const LLUserAuth::response_t &response)
{
diff --git a/indra/newview/lleventnotifier.h b/indra/newview/lleventnotifier.h
index bbd1facf31..ac906521d2 100644
--- a/indra/newview/lleventnotifier.h
+++ b/indra/newview/lleventnotifier.h
@@ -56,7 +56,6 @@ public:
typedef std::map<U32, LLEventNotification *> en_map;
- static void notifyCallback(S32 option, void *user_data);
protected:
en_map mEventNotifications;
LLFrameTimer mNotificationTimer;
@@ -78,6 +77,7 @@ public:
time_t getEventDate() const { return mEventDate; }
const std::string &getEventDateStr() const { return mEventDateStr; }
LLVector3d getEventPosGlobal() const { return mEventPosGlobal; }
+ bool handleResponse(const LLSD& notification, const LLSD& payload);
protected:
U32 mEventID; // EventID for this event
std::string mEventName;
diff --git a/indra/newview/llfirstuse.cpp b/indra/newview/llfirstuse.cpp
index 475473abe7..fce4d41207 100644
--- a/indra/newview/llfirstuse.cpp
+++ b/indra/newview/llfirstuse.cpp
@@ -85,9 +85,9 @@ void LLFirstUse::useBalanceIncrease(S32 delta)
{
gSavedSettings.setWarning("FirstBalanceIncrease", FALSE);
- LLStringUtil::format_map_t args;
- args["[AMOUNT]"] = llformat("%d",delta);
- LLNotifyBox::showXml("FirstBalanceIncrease", args);
+ LLSD args;
+ args["AMOUNT"] = llformat("%d",delta);
+ LLNotifications::instance().add("FirstBalanceIncrease", args);
}
}
@@ -99,9 +99,9 @@ void LLFirstUse::useBalanceDecrease(S32 delta)
{
gSavedSettings.setWarning("FirstBalanceDecrease", FALSE);
- LLStringUtil::format_map_t args;
- args["[AMOUNT]"] = llformat("%d",-delta);
- LLNotifyBox::showXml("FirstBalanceDecrease", args);
+ LLSD args;
+ args["AMOUNT"] = llformat("%d",-delta);
+ LLNotifications::instance().add("FirstBalanceDecrease", args);
}
}
@@ -114,8 +114,8 @@ void LLFirstUse::useSit()
//if (gSavedSettings.getWarning("FirstSit"))
//{
// gSavedSettings.setWarning("FirstSit", FALSE);
-
- // LLNotifyBox::showXml("FirstSit");
+ //
+ // LLNotifications::instance().add("FirstSit");
//}
}
@@ -126,7 +126,7 @@ void LLFirstUse::useMap()
{
gSavedSettings.setWarning("FirstMap", FALSE);
- LLNotifyBox::showXml("FirstMap");
+ LLNotifications::instance().add("FirstMap");
}
}
@@ -143,7 +143,7 @@ void LLFirstUse::useBuild()
{
gSavedSettings.setWarning("FirstBuild", FALSE);
- LLNotifyBox::showXml("FirstBuild");
+ LLNotifications::instance().add("FirstBuild");
}
}
@@ -154,7 +154,7 @@ void LLFirstUse::useLeftClickNoHit()
{
gSavedSettings.setWarning("FirstLeftClickNoHit", FALSE);
- LLNotifyBox::showXml("FirstLeftClickNoHit");
+ LLNotifications::instance().add("FirstLeftClickNoHit");
}
}
@@ -168,7 +168,7 @@ void LLFirstUse::useTeleport()
{
gSavedSettings.setWarning("FirstTeleport", FALSE);
- LLNotifyBox::showXml("FirstTeleport");
+ LLNotifications::instance().add("FirstTeleport");
}
}
}
@@ -184,7 +184,7 @@ void LLFirstUse::useOverrideKeys()
{
gSavedSettings.setWarning("FirstOverrideKeys", FALSE);
- LLNotifyBox::showXml("FirstOverrideKeys");
+ LLNotifications::instance().add("FirstOverrideKeys");
}
}
}
@@ -202,7 +202,7 @@ void LLFirstUse::useAppearance()
{
gSavedSettings.setWarning("FirstAppearance", FALSE);
- LLNotifyBox::showXml("FirstAppearance");
+ LLNotifications::instance().add("FirstAppearance");
}
}
@@ -213,7 +213,7 @@ void LLFirstUse::useInventory()
{
gSavedSettings.setWarning("FirstInventory", FALSE);
- LLNotifyBox::showXml("FirstInventory");
+ LLNotifications::instance().add("FirstInventory");
}
}
@@ -225,10 +225,10 @@ void LLFirstUse::useSandbox()
{
gSavedSettings.setWarning("FirstSandbox", FALSE);
- LLStringUtil::format_map_t args;
- args["[HOURS]"] = llformat("%d",SANDBOX_CLEAN_FREQ);
- args["[TIME]"] = llformat("%d",SANDBOX_FIRST_CLEAN_HOUR);
- LLNotifyBox::showXml("FirstSandbox", args);
+ LLSD args;
+ args["HOURS"] = llformat("%d",SANDBOX_CLEAN_FREQ);
+ args["TIME"] = llformat("%d",SANDBOX_FIRST_CLEAN_HOUR);
+ LLNotifications::instance().add("FirstSandbox", args);
}
}
@@ -239,7 +239,7 @@ void LLFirstUse::useFlexible()
{
gSavedSettings.setWarning("FirstFlexible", FALSE);
- LLNotifyBox::showXml("FirstFlexible");
+ LLNotifications::instance().add("FirstFlexible");
}
}
@@ -250,7 +250,7 @@ void LLFirstUse::useDebugMenus()
{
gSavedSettings.setWarning("FirstDebugMenus", FALSE);
- LLNotifyBox::showXml("FirstDebugMenus");
+ LLNotifications::instance().add("FirstDebugMenus");
}
}
@@ -261,7 +261,7 @@ void LLFirstUse::useSculptedPrim()
{
gSavedSettings.setWarning("FirstSculptedPrim", FALSE);
- LLNotifyBox::showXml("FirstSculptedPrim");
+ LLNotifications::instance().add("FirstSculptedPrim");
}
}
@@ -273,6 +273,6 @@ void LLFirstUse::useMedia()
{
gSavedSettings.setWarning("FirstMedia", FALSE);
- LLNotifyBox::showXml("FirstMedia");
+ LLNotifications::instance().add("FirstMedia");
}
}
diff --git a/indra/newview/llfloateranimpreview.cpp b/indra/newview/llfloateranimpreview.cpp
index c7e35bcfb5..a84026e132 100644
--- a/indra/newview/llfloateranimpreview.cpp
+++ b/indra/newview/llfloateranimpreview.cpp
@@ -1001,7 +1001,7 @@ void LLFloaterAnimPreview::onBtnOK(void* userdata)
else
{
llwarns << "Failure writing animation data." << llendl;
- gViewerWindow->alertXml("WriteAnimationFail");
+ LLNotifications::instance().add("WriteAnimationFail");
}
}
diff --git a/indra/newview/llfloaterauction.cpp b/indra/newview/llfloaterauction.cpp
index a90d11f6ea..100c6ee20d 100644
--- a/indra/newview/llfloaterauction.cpp
+++ b/indra/newview/llfloaterauction.cpp
@@ -238,7 +238,7 @@ void LLFloaterAuction::onClickOK(void* data)
FALSE);
self->getWindow()->incBusyCount();
- LLNotifyBox::showXml("UploadingAuctionSnapshot");
+ LLNotifications::instance().add("UploadingAuctionSnapshot");
}
LLMessageSystem* msg = gMessageSystem;
@@ -277,13 +277,13 @@ void auction_tga_upload_done(const LLUUID& asset_id, void* user_data, S32 status
if (0 == status)
{
- LLNotifyBox::showXml("UploadWebSnapshotDone");
+ LLNotifications::instance().add("UploadWebSnapshotDone");
}
else
{
- LLStringUtil::format_map_t args;
- args["[REASON]"] = std::string(LLAssetStorage::getErrorString(status));
- gViewerWindow->alertXml("UploadAuctionSnapshotFail", args);
+ LLSD args;
+ args["REASON"] = std::string(LLAssetStorage::getErrorString(status));
+ LLNotifications::instance().add("UploadAuctionSnapshotFail", args);
}
}
@@ -298,12 +298,12 @@ void auction_j2c_upload_done(const LLUUID& asset_id, void* user_data, S32 status
if (0 == status)
{
- LLNotifyBox::showXml("UploadSnapshotDone");
+ LLNotifications::instance().add("UploadSnapshotDone");
}
else
{
- LLStringUtil::format_map_t args;
- args["[REASON]"] = std::string(LLAssetStorage::getErrorString(status));
- gViewerWindow->alertXml("UploadAuctionSnapshotFail", args);
+ LLSD args;
+ args["REASON"] = std::string(LLAssetStorage::getErrorString(status));
+ LLNotifications::instance().add("UploadAuctionSnapshotFail", args);
}
}
diff --git a/indra/newview/llfloaterbuy.cpp b/indra/newview/llfloaterbuy.cpp
index 9edb0afb5c..5bdb4a2374 100644
--- a/indra/newview/llfloaterbuy.cpp
+++ b/indra/newview/llfloaterbuy.cpp
@@ -86,7 +86,7 @@ void LLFloaterBuy::show(const LLSaleInfo& sale_info)
if (selection->getRootObjectCount() != 1)
{
- gViewerWindow->alertXml("BuyOneObjectOnly");
+ LLNotifications::instance().add("BuyOneObjectOnly");
return;
}
@@ -136,7 +136,7 @@ void LLFloaterBuy::show(const LLSaleInfo& sale_info)
BOOL owners_identical = LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name);
if (!owners_identical)
{
- gViewerWindow->alertXml("BuyObjectOneOwner");
+ LLNotifications::instance().add("BuyObjectOneOwner");
return;
}
diff --git a/indra/newview/llfloaterbuycontents.cpp b/indra/newview/llfloaterbuycontents.cpp
index d74707f6b1..1dd12413cc 100644
--- a/indra/newview/llfloaterbuycontents.cpp
+++ b/indra/newview/llfloaterbuycontents.cpp
@@ -83,7 +83,7 @@ void LLFloaterBuyContents::show(const LLSaleInfo& sale_info)
if (selection->getRootObjectCount() != 1)
{
- gViewerWindow->alertXml("BuyContentsOneOnly");
+ LLNotifications::instance().add("BuyContentsOneOnly");
return;
}
@@ -113,7 +113,7 @@ void LLFloaterBuyContents::show(const LLSaleInfo& sale_info)
BOOL owners_identical = LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name);
if (!owners_identical)
{
- gViewerWindow->alertXml("BuyContentsOneOwner");
+ LLNotifications::instance().add("BuyContentsOneOwner");
return;
}
diff --git a/indra/newview/llfloaterbuyland.cpp b/indra/newview/llfloaterbuyland.cpp
index 7aa6af2fea..65cea37a0f 100644
--- a/indra/newview/llfloaterbuyland.cpp
+++ b/indra/newview/llfloaterbuyland.cpp
@@ -213,7 +213,7 @@ void LLFloaterBuyLand::buyLand(
{
if(is_for_group && !gAgent.hasPowerInActiveGroup(GP_LAND_DEED))
{
- gViewerWindow->alertXml("OnlyOfficerCanBuyLand");
+ LLNotifications::instance().add("OnlyOfficerCanBuyLand");
return;
}
@@ -976,7 +976,7 @@ BOOL LLFloaterBuyLandUI::canClose()
if (!can_close)
{
// explain to user why they can't do this, see DEV-9605
- gViewerWindow->alertXml("CannotCloseFloaterBuyLand");
+ LLNotifications::instance().add("CannotCloseFloaterBuyLand");
}
return can_close;
}
diff --git a/indra/newview/llfloaterdaycycle.cpp b/indra/newview/llfloaterdaycycle.cpp
index af42a92ed8..de308b5425 100644
--- a/indra/newview/llfloaterdaycycle.cpp
+++ b/indra/newview/llfloaterdaycycle.cpp
@@ -98,17 +98,9 @@ LLFloaterDayCycle::~LLFloaterDayCycle()
void LLFloaterDayCycle::onClickHelp(void* data)
{
LLFloaterDayCycle* self = LLFloaterDayCycle::instance();
- const std::string* xml_alert = (std::string*)data;
- LLAlertDialog* dialogp = gViewerWindow->alertXml(*xml_alert);
- if (dialogp)
- {
- LLFloater* root_floater = gFloaterView->getParentFloater(self);
- if (root_floater)
- {
- root_floater->addDependentFloater(dialogp);
- }
- }
+ std::string xml_alert = *(std::string *) data;
+ LLNotifications::instance().add(self->contextualNotification(xml_alert));
}
void LLFloaterDayCycle::initHelpBtn(const std::string& name, const std::string& xml_alert)
diff --git a/indra/newview/llfloaterenvsettings.cpp b/indra/newview/llfloaterenvsettings.cpp
index b28cc04047..90225ecfa1 100644
--- a/indra/newview/llfloaterenvsettings.cpp
+++ b/indra/newview/llfloaterenvsettings.cpp
@@ -67,18 +67,8 @@ LLFloaterEnvSettings::~LLFloaterEnvSettings()
void LLFloaterEnvSettings::onClickHelp(void* data)
{
- LLFloaterEnvSettings* self = static_cast<LLFloaterEnvSettings*>(data);
-
- const char* xml_alert = "EnvSettingsHelpButton";
- LLAlertDialog* dialogp = gViewerWindow->alertXml(xml_alert);
- if (dialogp)
- {
- LLFloater* root_floater = gFloaterView->getParentFloater(self);
- if (root_floater)
- {
- root_floater->addDependentFloater(dialogp);
- }
- }
+ LLFloaterEnvSettings* self = (LLFloaterEnvSettings*)data;
+ LLNotifications::instance().add(self->contextualNotification("EnvSettingsHelpButton"));
}
void LLFloaterEnvSettings::initCallbacks(void)
diff --git a/indra/newview/llfloaterfriends.cpp b/indra/newview/llfloaterfriends.cpp
index 2d7d2ee15d..f5493172ba 100644
--- a/indra/newview/llfloaterfriends.cpp
+++ b/indra/newview/llfloaterfriends.cpp
@@ -523,9 +523,9 @@ void LLPanelFriends::onSelectName(LLUICtrl* ctrl, void* user_data)
//static
void LLPanelFriends::onMaximumSelect(void* user_data)
{
- LLStringUtil::format_map_t args;
- args["[MAX_SELECT]"] = llformat("%d", MAX_FRIEND_SELECT);
- LLNotifyBox::showXml("MaxListSelectMessage", args);
+ LLSD args;
+ args["MAX_SELECT"] = llformat("%d", MAX_FRIEND_SELECT);
+ LLNotifications::instance().add("MaxListSelectMessage", args);
};
// static
@@ -585,27 +585,22 @@ void LLPanelFriends::requestFriendship(const LLUUID& target_id, const std::strin
calling_card_folder_id);
}
-struct LLAddFriendData
-{
- LLUUID mID;
- std::string mName;
-};
-
// static
-void LLPanelFriends::callbackAddFriendWithMessage(S32 option, const std::string& text, void* data)
+bool LLPanelFriends::callbackAddFriendWithMessage(const LLSD& notification, const LLSD& response)
{
- LLAddFriendData* add = (LLAddFriendData*)data;
+ S32 option = LLNotification::getSelectedOption(notification, response);
if (option == 0)
{
- requestFriendship(add->mID, add->mName, text);
+ requestFriendship(notification["payload"]["id"].asUUID(),
+ notification["payload"]["name"].asString(),
+ response["message"].asString());
}
- delete add;
+ return false;
}
-// static
-void LLPanelFriends::callbackAddFriend(S32 option, void* data)
+bool LLPanelFriends::callbackAddFriend(const LLSD& notification, const LLSD& response)
{
- LLAddFriendData* add = (LLAddFriendData*)data;
+ S32 option = LLNotification::getSelectedOption(notification, response);
if (option == 0)
{
// Servers older than 1.25 require the text of the message to be the
@@ -613,9 +608,11 @@ void LLPanelFriends::callbackAddFriend(S32 option, void* data)
LLUUID calling_card_folder_id =
gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD);
std::string message = calling_card_folder_id.asString();
- requestFriendship(add->mID, add->mName, message);
+ requestFriendship(notification["payload"]["id"].asUUID(),
+ notification["payload"]["name"].asString(),
+ message);
}
- delete add;
+ return false;
}
// static
@@ -634,27 +631,25 @@ void LLPanelFriends::requestFriendshipDialog(const LLUUID& id,
{
if(id == gAgentID)
{
- LLNotifyBox::showXml("AddSelfFriend");
+ LLNotifications::instance().add("AddSelfFriend");
return;
}
- LLAddFriendData* data = new LLAddFriendData();
- data->mID = id;
- data->mName = name;
-
- LLStringUtil::format_map_t args;
- args["[NAME]"] = name;
-
- // Look for server versions like: Second Life Server 1.24.4.95600
+ LLSD args;
+ args["NAME"] = name;
+ LLSD payload;
+ payload["id"] = id;
+ payload["name"] = name;
+ // Look for server versions like: Second Life Server 1.24.4.95600
if (gLastVersionChannel.find(" 1.24.") != std::string::npos)
{
// Old and busted server version, doesn't support friend
// requests with messages.
- gViewerWindow->alertXml("AddFriend", args, callbackAddFriend, data);
+ LLNotifications::instance().add("AddFriend", args, payload, &callbackAddFriend);
}
else
{
- gViewerWindow->alertXmlEditText("AddFriendWithMessage", args, NULL, NULL, callbackAddFriendWithMessage, data);
+ LLNotifications::instance().add("AddFriendWithMessage", args, payload, &callbackAddFriendWithMessage);
}
}
@@ -677,7 +672,7 @@ void LLPanelFriends::onClickRemove(void* user_data)
//llinfos << "LLPanelFriends::onClickRemove()" << llendl;
LLDynamicArray<LLUUID> ids = panelp->getSelectedIDs();
- LLStringUtil::format_map_t args;
+ LLSD args;
if(ids.size() > 0)
{
std::string msgType = "RemoveFromFriends";
@@ -687,18 +682,27 @@ void LLPanelFriends::onClickRemove(void* user_data)
std::string first, last;
if(gCacheName->getName(agent_id, first, last))
{
- args["[FIRST_NAME]"] = first;
- args["[LAST_NAME]"] = last;
+ args["FIRST_NAME"] = first;
+ args["LAST_NAME"] = last;
}
}
else
{
msgType = "RemoveMultipleFromFriends";
}
- gViewerWindow->alertXml(msgType,
+ LLSD payload;
+
+ for (LLDynamicArray<LLUUID>::iterator it = ids.begin();
+ it != ids.end();
+ ++it)
+ {
+ payload["ids"].append(*it);
+ }
+
+ LLNotifications::instance().add(msgType,
args,
- &handleRemove,
- (void*)new LLDynamicArray<LLUUID>(ids));
+ payload,
+ &handleRemove);
}
}
@@ -730,13 +734,10 @@ void LLPanelFriends::confirmModifyRights(rights_map_t& ids, EGrantRevoke command
{
if (ids.empty()) return;
- LLStringUtil::format_map_t args;
+ LLSD args;
if(ids.size() > 0)
{
- // copy map of ids onto heap
- rights_map_t* rights = new rights_map_t(ids);
- // package with panel pointer
- std::pair<LLPanelFriends*, rights_map_t*>* user_data = new std::pair<LLPanelFriends*, rights_map_t*>(this, rights);
+ rights_map_t* rights = new rights_map_t(ids);
// for single friend, show their name
if(ids.size() == 1)
@@ -745,62 +746,65 @@ void LLPanelFriends::confirmModifyRights(rights_map_t& ids, EGrantRevoke command
std::string first, last;
if(gCacheName->getName(agent_id, first, last))
{
- args["[FIRST_NAME]"] = first;
- args["[LAST_NAME]"] = last;
+ args["FIRST_NAME"] = first;
+ args["LAST_NAME"] = last;
}
if (command == GRANT)
{
- gViewerWindow->alertXml("GrantModifyRights", args, modifyRightsConfirmation, user_data);
+ LLNotifications::instance().add("GrantModifyRights",
+ args,
+ LLSD(),
+ boost::bind(&LLPanelFriends::modifyRightsConfirmation, this, _1, _2, rights));
}
else
{
- gViewerWindow->alertXml("RevokeModifyRights", args, modifyRightsConfirmation, user_data);
+ LLNotifications::instance().add("RevokeModifyRights",
+ args,
+ LLSD(),
+ boost::bind(&LLPanelFriends::modifyRightsConfirmation, this, _1, _2, rights));
}
}
else
{
if (command == GRANT)
{
- gViewerWindow->alertXml("GrantModifyRightsMultiple", args, modifyRightsConfirmation, user_data);
+ LLNotifications::instance().add("GrantModifyRightsMultiple",
+ args,
+ LLSD(),
+ boost::bind(&LLPanelFriends::modifyRightsConfirmation, this, _1, _2, rights));
}
else
{
- gViewerWindow->alertXml("RevokeModifyRightsMultiple", args, modifyRightsConfirmation, user_data);
+ LLNotifications::instance().add("RevokeModifyRightsMultiple",
+ args,
+ LLSD(),
+ boost::bind(&LLPanelFriends::modifyRightsConfirmation, this, _1, _2, rights));
}
}
}
}
-// static
-void LLPanelFriends::modifyRightsConfirmation(S32 option, void* user_data)
+bool LLPanelFriends::modifyRightsConfirmation(const LLSD& notification, const LLSD& response, rights_map_t* rights)
{
- std::pair<LLPanelFriends*, rights_map_t*>* data = (std::pair<LLPanelFriends*, rights_map_t*>*)user_data;
- LLPanelFriends* panelp = data->first;
-
- if(panelp)
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ if(0 == option)
{
- if(0 == option)
- {
- panelp->sendRightsGrant(*(data->second));
- }
- else
+ sendRightsGrant(*rights);
+ }
+ else
+ {
+ // need to resync view with model, since user cancelled operation
+ rights_map_t::iterator rights_it;
+ for (rights_it = rights->begin(); rights_it != rights->end(); ++rights_it)
{
- // need to resync view with model, since user cancelled operation
- rights_map_t* rights = data->second;
- rights_map_t::iterator rights_it;
- for (rights_it = rights->begin(); rights_it != rights->end(); ++rights_it)
- {
- const LLRelationship* info = LLAvatarTracker::instance().getBuddyInfo(rights_it->first);
- panelp->updateFriendItem(rights_it->first, info);
- // Might have changed the column the user is sorted on.
- panelp->mFriendsList->sortItems();
- }
+ const LLRelationship* info = LLAvatarTracker::instance().getBuddyInfo(rights_it->first);
+ updateFriendItem(rights_it->first, info);
}
- panelp->refreshUI();
}
+ refreshUI();
- delete data->second;
- delete data;
+ delete rights;
+ return false;
}
void LLPanelFriends::applyRightsToFriends()
@@ -924,12 +928,14 @@ void LLPanelFriends::sendRightsGrant(rights_map_t& ids)
// static
-void LLPanelFriends::handleRemove(S32 option, void* user_data)
+bool LLPanelFriends::handleRemove(const LLSD& notification, const LLSD& response)
{
- LLDynamicArray<LLUUID>* ids = static_cast<LLDynamicArray<LLUUID>*>(user_data);
- for(LLDynamicArray<LLUUID>::iterator itr = ids->begin(); itr != ids->end(); ++itr)
+ S32 option = LLNotification::getSelectedOption(notification, response);
+
+ const LLSD& ids = notification["payload"]["ids"];
+ for(LLSD::array_const_iterator itr = ids.beginArray(); itr != ids.endArray(); ++itr)
{
- LLUUID id = (*itr);
+ LLUUID id = itr->asUUID();
const LLRelationship* ip = LLAvatarTracker::instance().getBuddyInfo(id);
if(ip)
{
@@ -955,5 +961,5 @@ void LLPanelFriends::handleRemove(S32 option, void* user_data)
}
}
- delete ids;
+ return false;
}
diff --git a/indra/newview/llfloaterfriends.h b/indra/newview/llfloaterfriends.h
index e3f3f96d00..58f7cc3bb2 100644
--- a/indra/newview/llfloaterfriends.h
+++ b/indra/newview/llfloaterfriends.h
@@ -119,8 +119,8 @@ private:
// callback methods
static void onSelectName(LLUICtrl* ctrl, void* user_data);
- static void callbackAddFriendWithMessage(S32 option, const std::string& text, void* user_data);
- static void callbackAddFriend(S32 option, void* user_data);
+ static bool callbackAddFriend(const LLSD& notification, const LLSD& response);
+ static bool callbackAddFriendWithMessage(const LLSD& notification, const LLSD& response);
static void onPickAvatar(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* user_data);
static void onMaximumSelect(void* user_data);
@@ -134,8 +134,8 @@ private:
static void onClickModifyStatus(LLUICtrl* ctrl, void* user_data);
- static void handleRemove(S32 option, void* user_data);
- static void modifyRightsConfirmation(S32 option, void* user_data);
+ static bool handleRemove(const LLSD& notification, const LLSD& response);
+ bool modifyRightsConfirmation(const LLSD& notification, const LLSD& response, rights_map_t* rights);
private:
// member data
diff --git a/indra/newview/llfloatergodtools.cpp b/indra/newview/llfloatergodtools.cpp
index a4022d844a..c1eb273acc 100644
--- a/indra/newview/llfloatergodtools.cpp
+++ b/indra/newview/llfloatergodtools.cpp
@@ -918,34 +918,31 @@ void LLPanelGridTools::refresh()
// static
void LLPanelGridTools::onClickKickAll(void* userdata)
{
- LLPanelGridTools* self = (LLPanelGridTools*) userdata;
-
S32 left, top;
gFloaterView->getNewFloaterPosition(&left, &top);
LLRect rect(left, top, left+400, top-300);
- gViewerWindow->alertXmlEditText("KickAllUsers", LLStringUtil::format_map_t(),
- NULL, NULL,
- LLPanelGridTools::confirmKick, self);
+ LLNotifications::instance().add("KickAllUsers", LLSD(), LLSD(), LLPanelGridTools::confirmKick);
}
-void LLPanelGridTools::confirmKick(S32 option, const std::string& text, void* userdata)
+bool LLPanelGridTools::confirmKick(const LLSD& notification, const LLSD& response)
{
- LLPanelGridTools* self = (LLPanelGridTools*) userdata;
-
- if (option == 0)
+ if (LLNotification::getSelectedOption(notification, response) == 0)
{
- self->mKickMessage = text;
- gViewerWindow->alertXml("ConfirmKick",LLPanelGridTools::finishKick, self);
+ LLSD payload;
+ payload["kick_message"] = response["message"].asString();
+ LLNotifications::instance().add("ConfirmKick", LLSD(), payload, LLPanelGridTools::finishKick);
}
+ return false;
}
// static
-void LLPanelGridTools::finishKick(S32 option, void* userdata)
+bool LLPanelGridTools::finishKick(const LLSD& notification, const LLSD& response)
{
- LLPanelGridTools* self = (LLPanelGridTools*) userdata;
+ S32 option = LLNotification::getSelectedOption(notification, response);
+
if (option == 0)
{
@@ -957,26 +954,24 @@ void LLPanelGridTools::finishKick(S32 option, void* userdata)
msg->addUUIDFast(_PREHASH_GodSessionID, gAgent.getSessionID());
msg->addUUIDFast(_PREHASH_AgentID, LL_UUID_ALL_AGENTS );
msg->addU32("KickFlags", KICK_FLAGS_DEFAULT );
- msg->addStringFast(_PREHASH_Reason, self->mKickMessage );
+ msg->addStringFast(_PREHASH_Reason, notification["payload"]["kick_message"].asString());
gAgent.sendReliableMessage();
}
+ return false;
}
// static
void LLPanelGridTools::onClickFlushMapVisibilityCaches(void* data)
{
- gViewerWindow->alertXml("FlushMapVisibilityCaches",
- flushMapVisibilityCachesConfirm, data);
+ LLNotifications::instance().add("FlushMapVisibilityCaches", LLSD(), LLSD(), flushMapVisibilityCachesConfirm);
}
// static
-void LLPanelGridTools::flushMapVisibilityCachesConfirm(S32 option, void* data)
+bool LLPanelGridTools::flushMapVisibilityCachesConfirm(const LLSD& notification, const LLSD& response)
{
- if (option != 0) return;
-
- LLPanelGridTools* self = (LLPanelGridTools*)data;
- if (!self) return;
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ if (option != 0) return false;
// HACK: Send this as an EstateOwnerRequest so it gets routed
// correctly by the spaceserver. JC
@@ -992,6 +987,7 @@ void LLPanelGridTools::flushMapVisibilityCachesConfirm(S32 option, void* data)
msg->nextBlock("ParamList");
msg->addString("Parameter", gAgent.getID().asString());
gAgent.sendReliableMessage();
+ return false;
}
@@ -1182,13 +1178,16 @@ void LLPanelObjectTools::onClickDeletePublicOwnedBy(void* userdata)
panelp->mSimWideDeletesFlags =
SWD_SCRIPTED_ONLY | SWD_OTHERS_LAND_ONLY;
- LLStringUtil::format_map_t args;
- args["[AVATAR_NAME]"] = panelp->childGetValue("target_avatar_name").asString();
+ LLSD args;
+ args["AVATAR_NAME"] = panelp->childGetValue("target_avatar_name").asString();
+ LLSD payload;
+ payload["avatar_id"] = panelp->mTargetAvatar;
+ payload["flags"] = (S32)panelp->mSimWideDeletesFlags;
- gViewerWindow->alertXml( "GodDeleteAllScriptedPublicObjectsByUser",
+ LLNotifications::instance().add( "GodDeleteAllScriptedPublicObjectsByUser",
args,
- callbackSimWideDeletes,
- userdata);
+ payload,
+ callbackSimWideDeletes);
}
}
@@ -1201,13 +1200,16 @@ void LLPanelObjectTools::onClickDeleteAllScriptedOwnedBy(void* userdata)
{
panelp->mSimWideDeletesFlags = SWD_SCRIPTED_ONLY;
- LLStringUtil::format_map_t args;
- args["[AVATAR_NAME]"] = panelp->childGetValue("target_avatar_name").asString();
+ LLSD args;
+ args["AVATAR_NAME"] = panelp->childGetValue("target_avatar_name").asString();
+ LLSD payload;
+ payload["avatar_id"] = panelp->mTargetAvatar;
+ payload["flags"] = (S32)panelp->mSimWideDeletesFlags;
- gViewerWindow->alertXml( "GodDeleteAllScriptedObjectsByUser",
+ LLNotifications::instance().add( "GodDeleteAllScriptedObjectsByUser",
args,
- callbackSimWideDeletes,
- userdata);
+ payload,
+ callbackSimWideDeletes);
}
}
@@ -1220,28 +1222,32 @@ void LLPanelObjectTools::onClickDeleteAllOwnedBy(void* userdata)
{
panelp->mSimWideDeletesFlags = 0;
- LLStringUtil::format_map_t args;
- args["[AVATAR_NAME]"] = panelp->childGetValue("target_avatar_name").asString();
+ LLSD args;
+ args["AVATAR_NAME"] = panelp->childGetValue("target_avatar_name").asString();
+ LLSD payload;
+ payload["avatar_id"] = panelp->mTargetAvatar;
+ payload["flags"] = (S32)panelp->mSimWideDeletesFlags;
- gViewerWindow->alertXml( "GodDeleteAllObjectsByUser",
+ LLNotifications::instance().add( "GodDeleteAllObjectsByUser",
args,
- callbackSimWideDeletes,
- userdata);
+ payload,
+ callbackSimWideDeletes);
}
}
// static
-void LLPanelObjectTools::callbackSimWideDeletes( S32 option, void* userdata )
+bool LLPanelObjectTools::callbackSimWideDeletes( const LLSD& notification, const LLSD& response )
{
+ S32 option = LLNotification::getSelectedOption(notification, response);
if (option == 0)
{
- LLPanelObjectTools* object_tools = (LLPanelObjectTools*) userdata;
- if (!object_tools->mTargetAvatar.isNull())
+ if (!notification["payload"]["avatar_id"].asUUID().isNull())
{
- send_sim_wide_deletes(object_tools->mTargetAvatar,
- object_tools->mSimWideDeletesFlags);
+ send_sim_wide_deletes(notification["payload"]["avatar_id"].asUUID(),
+ notification["payload"]["flags"].asInteger());
}
}
+ return false;
}
void LLPanelObjectTools::onClickSet(void* data)
@@ -1420,7 +1426,7 @@ void LLPanelRequestTools::onClickRequest(void* data)
void terrain_download_done(void** data, S32 status, LLExtStat ext_status)
{
- LLNotifyBox::showXml("TerrainDownloaded");
+ LLNotifications::instance().add("TerrainDownloaded");
}
diff --git a/indra/newview/llfloatergodtools.h b/indra/newview/llfloatergodtools.h
index 7cc840cc97..b70b9d795d 100644
--- a/indra/newview/llfloatergodtools.h
+++ b/indra/newview/llfloatergodtools.h
@@ -201,11 +201,11 @@ public:
void refresh();
static void onClickKickAll(void *data);
- static void confirmKick(S32 option, const std::string& text, void* userdata);
- static void finishKick(S32 option, void* userdata);
+ static bool confirmKick(const LLSD& notification, const LLSD& response);
+ static bool finishKick(const LLSD& notification, const LLSD& response);
static void onDragSunPhase(LLUICtrl *ctrl, void *userdata);
static void onClickFlushMapVisibilityCaches(void* data);
- static void flushMapVisibilityCachesConfirm(S32 option, void* data);
+ static bool flushMapVisibilityCachesConfirm(const LLSD& notification, const LLSD& response);
protected:
std::string mKickMessage; // Message to send on kick
@@ -240,7 +240,7 @@ public:
static void onClickDeletePublicOwnedBy(void* data);
static void onClickDeleteAllScriptedOwnedBy(void* data);
static void onClickDeleteAllOwnedBy(void* data);
- static void callbackSimWideDeletes(S32 option, void* userdata);
+ static bool callbackSimWideDeletes(const LLSD& notification, const LLSD& response);
static void onGetTopColliders(void* data);
static void onGetTopScripts(void* data);
static void onGetScriptDigest(void* data);
diff --git a/indra/newview/llfloatergroups.cpp b/indra/newview/llfloatergroups.cpp
index ca3332e4ad..e798327bb7 100644
--- a/indra/newview/llfloatergroups.cpp
+++ b/indra/newview/llfloatergroups.cpp
@@ -388,10 +388,11 @@ void LLPanelGroups::leave()
}
if(i < count)
{
- LLUUID* cb_data = new LLUUID((const LLUUID&)group_id);
- LLStringUtil::format_map_t args;
- args["[GROUP]"] = gAgent.mGroups.get(i).mName;
- gViewerWindow->alertXml("GroupLeaveConfirmMember", args, callbackLeaveGroup, (void*)cb_data);
+ LLSD args;
+ args["GROUP"] = gAgent.mGroups.get(i).mName;
+ LLSD payload;
+ payload["group_id"] = group_id;
+ LLNotifications::instance().add("GroupLeaveConfirmMember", args, payload, callbackLeaveGroup);
}
}
}
@@ -402,10 +403,11 @@ void LLPanelGroups::search()
}
// static
-void LLPanelGroups::callbackLeaveGroup(S32 option, void* userdata)
+bool LLPanelGroups::callbackLeaveGroup(const LLSD& notification, const LLSD& response)
{
- LLUUID* group_id = (LLUUID*)userdata;
- if(option == 0 && group_id)
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ LLUUID group_id = notification["payload"]["group_id"].asUUID();
+ if(option == 0)
{
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_LeaveGroupRequest);
@@ -413,10 +415,10 @@ void LLPanelGroups::callbackLeaveGroup(S32 option, void* userdata)
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
msg->nextBlockFast(_PREHASH_GroupData);
- msg->addUUIDFast(_PREHASH_GroupID, *group_id);
+ msg->addUUIDFast(_PREHASH_GroupID, group_id);
gAgent.sendReliableMessage();
}
- delete group_id;
+ return false;
}
void LLPanelGroups::onGroupList(LLUICtrl* ctrl, void* userdata)
diff --git a/indra/newview/llfloatergroups.h b/indra/newview/llfloatergroups.h
index 6d99f34085..a94b143d39 100644
--- a/indra/newview/llfloatergroups.h
+++ b/indra/newview/llfloatergroups.h
@@ -120,7 +120,7 @@ protected:
void search();
void callVote();
- static void callbackLeaveGroup(S32 option, void* userdata);
+ static bool callbackLeaveGroup(const LLSD& notification, const LLSD& response);
};
diff --git a/indra/newview/llfloaterhardwaresettings.cpp b/indra/newview/llfloaterhardwaresettings.cpp
index e4c13b2ae4..1db153434f 100644
--- a/indra/newview/llfloaterhardwaresettings.cpp
+++ b/indra/newview/llfloaterhardwaresettings.cpp
@@ -62,7 +62,7 @@ LLFloaterHardwareSettings::~LLFloaterHardwareSettings()
void LLFloaterHardwareSettings::onClickHelp(void* data)
{
const char* xml_alert = "HardwareSettingsHelpButton";
- gViewerWindow->alertXml(xml_alert);
+ LLNotifications::instance().add(xml_alert);
}
void LLFloaterHardwareSettings::initCallbacks(void)
diff --git a/indra/newview/llfloaterhud.cpp b/indra/newview/llfloaterhud.cpp
index 848068ee9d..8c97628e4e 100644
--- a/indra/newview/llfloaterhud.cpp
+++ b/indra/newview/llfloaterhud.cpp
@@ -102,7 +102,7 @@ void LLFloaterHUD::showHUD()
// do not build the floater if there the url is empty
if (gSavedSettings.getString("TutorialURL") == "")
{
- LLAlertDialog::showXml("TutorialNotFound");
+ LLNotifications::instance().add("TutorialNotFound");
return;
}
diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp
index a92634bc31..8b4b3805ee 100644
--- a/indra/newview/llfloaterland.cpp
+++ b/indra/newview/llfloaterland.cpp
@@ -85,8 +85,6 @@ static const BOOL BUY_PERSONAL_LAND = FALSE;
LLParcelSelectionObserver* LLFloaterLand::sObserver = NULL;
S32 LLFloaterLand::sLastTab = 0;
-LLHandle<LLFloater> LLPanelLandGeneral::sBuyPassDialogHandle;
-
// Local classes
class LLParcelSelectionObserver : public LLParcelObserver
{
@@ -872,12 +870,12 @@ void LLPanelLandGeneral::onClickBuyPass(void* data)
cost = llformat("%d", pass_price);
time = llformat("%.2f", pass_hours);
- LLStringUtil::format_map_t args;
- args["[COST]"] = cost;
- args["[PARCEL_NAME]"] = parcel_name;
- args["[TIME]"] = time;
+ LLSD args;
+ args["COST"] = cost;
+ args["PARCEL_NAME"] = parcel_name;
+ args["TIME"] = time;
- sBuyPassDialogHandle = gViewerWindow->alertXml("LandBuyPass", args, cbBuyPass)->getHandle();
+ LLNotifications::instance().add("LandBuyPass", args, LLSD(), cbBuyPass);
}
// static
@@ -889,7 +887,7 @@ void LLPanelLandGeneral::onClickStartAuction(void* data)
{
if(parcelp->getForSale())
{
- gViewerWindow->alertXml("CannotStartAuctionAlreadForSale");
+ LLNotifications::instance().add("CannotStartAuctionAlreadForSale");
}
else
{
@@ -899,19 +897,15 @@ void LLPanelLandGeneral::onClickStartAuction(void* data)
}
// static
-void LLPanelLandGeneral::cbBuyPass(S32 option, void* data)
+bool LLPanelLandGeneral::cbBuyPass(const LLSD& notification, const LLSD& response)
{
+ S32 option = LLNotification::getSelectedOption(notification, response);
if (0 == option)
{
// User clicked OK
LLViewerParcelMgr::getInstance()->buyPass();
}
-}
-
-//static
-BOOL LLPanelLandGeneral::buyPassDialogVisible()
-{
- return sBuyPassDialogHandle.get() != NULL;
+ return false;
}
// static
@@ -1249,28 +1243,27 @@ void send_return_objects_message(S32 parcel_local_id, S32 return_type,
msg->sendReliable(region->getHost());
}
-// static
-void LLPanelLandObjects::callbackReturnOwnerObjects(S32 option, void* userdata)
+bool LLPanelLandObjects::callbackReturnOwnerObjects(const LLSD& notification, const LLSD& response)
{
- LLPanelLandObjects *lop = (LLPanelLandObjects *)userdata;
- LLParcel *parcel = lop->mParcel->getParcel();
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ LLParcel *parcel = mParcel->getParcel();
if (0 == option)
{
if (parcel)
{
LLUUID owner_id = parcel->getOwnerID();
- LLStringUtil::format_map_t args;
+ LLSD args;
if (owner_id == gAgentID)
{
- LLNotifyBox::showXml("OwnedObjectsReturned");
+ LLNotifications::instance().add("OwnedObjectsReturned");
}
else
{
std::string first, last;
gCacheName->getName(owner_id, first, last);
- args["[FIRST]"] = first;
- args["[LAST]"] = last;
- LLNotifyBox::showXml("OtherObjectsReturned", args);
+ args["FIRST"] = first;
+ args["LAST"] = last;
+ LLNotifications::instance().add("OtherObjectsReturned", args);
}
send_return_objects_message(parcel->getLocalID(), RT_OWNER);
}
@@ -1278,81 +1271,82 @@ void LLPanelLandObjects::callbackReturnOwnerObjects(S32 option, void* userdata)
LLSelectMgr::getInstance()->unhighlightAll();
LLViewerParcelMgr::getInstance()->sendParcelPropertiesUpdate( parcel );
- lop->refresh();
+ refresh();
+ return false;
}
-// static
-void LLPanelLandObjects::callbackReturnGroupObjects(S32 option, void* userdata)
+bool LLPanelLandObjects::callbackReturnGroupObjects(const LLSD& notification, const LLSD& response)
{
- LLPanelLandObjects *lop = (LLPanelLandObjects *)userdata;
- LLParcel *parcel = lop->mParcel->getParcel();
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ LLParcel *parcel = mParcel->getParcel();
if (0 == option)
{
if (parcel)
{
std::string group_name;
gCacheName->getGroupName(parcel->getGroupID(), group_name);
- LLStringUtil::format_map_t args;
- args["[GROUPNAME]"] = group_name;
- LLNotifyBox::showXml("GroupObjectsReturned", args);
+ LLSD args;
+ args["GROUPNAME"] = group_name;
+ LLNotifications::instance().add("GroupObjectsReturned", args);
send_return_objects_message(parcel->getLocalID(), RT_GROUP);
}
}
LLSelectMgr::getInstance()->unhighlightAll();
LLViewerParcelMgr::getInstance()->sendParcelPropertiesUpdate( parcel );
- lop->refresh();
+ refresh();
+ return false;
}
-// static
-void LLPanelLandObjects::callbackReturnOtherObjects(S32 option, void* userdata)
+bool LLPanelLandObjects::callbackReturnOtherObjects(const LLSD& notification, const LLSD& response)
{
- LLPanelLandObjects *lop = (LLPanelLandObjects *)userdata;
- LLParcel *parcel = lop->mParcel->getParcel();
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ LLParcel *parcel = mParcel->getParcel();
if (0 == option)
{
if (parcel)
{
- LLNotifyBox::showXml("UnOwnedObjectsReturned");
+ LLNotifications::instance().add("UnOwnedObjectsReturned");
send_return_objects_message(parcel->getLocalID(), RT_OTHER);
}
}
LLSelectMgr::getInstance()->unhighlightAll();
LLViewerParcelMgr::getInstance()->sendParcelPropertiesUpdate( parcel );
- lop->refresh();
+ refresh();
+ return false;
}
-// static
-void LLPanelLandObjects::callbackReturnOwnerList(S32 option, void* userdata)
+bool LLPanelLandObjects::callbackReturnOwnerList(const LLSD& notification, const LLSD& response)
{
- LLPanelLandObjects *self = (LLPanelLandObjects *)userdata;
- LLParcel *parcel = self->mParcel->getParcel();
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ LLParcel *parcel = mParcel->getParcel();
if (0 == option)
{
if (parcel)
{
// Make sure we have something selected.
- uuid_list_t::iterator selected = self->mSelectedOwners.begin();
- if (selected != self->mSelectedOwners.end())
+ uuid_list_t::iterator selected = mSelectedOwners.begin();
+ if (selected != mSelectedOwners.end())
{
- LLStringUtil::format_map_t args;
- if (self->mSelectedIsGroup)
+ LLSD args;
+ if (mSelectedIsGroup)
{
- args["[GROUPNAME]"] = self->mSelectedName;
- LLNotifyBox::showXml("GroupObjectsReturned", args);
+ args["GROUPNAME"] = mSelectedName;
+ LLNotifications::instance().add("GroupObjectsReturned", args);
}
else
{
- args["[NAME]"] = self->mSelectedName;
- LLNotifyBox::showXml("OtherObjectsReturned2", args);
+ args["NAME"] = mSelectedName;
+ LLNotifications::instance().add("OtherObjectsReturned2", args);
}
- send_return_objects_message(parcel->getLocalID(), RT_LIST, &(self->mSelectedOwners));
+ send_return_objects_message(parcel->getLocalID(), RT_LIST, &(mSelectedOwners));
}
}
}
LLSelectMgr::getInstance()->unhighlightAll();
LLViewerParcelMgr::getInstance()->sendParcelPropertiesUpdate( parcel );
- self->refresh();
+ refresh();
+ return false;
}
@@ -1374,16 +1368,16 @@ void LLPanelLandObjects::onClickReturnOwnerList(void* userdata)
send_parcel_select_objects(parcelp->getLocalID(), RT_LIST, &(self->mSelectedOwners));
- LLStringUtil::format_map_t args;
- args["[NAME]"] = self->mSelectedName;
- args["[N]"] = llformat("%d",self->mSelectedCount);
+ LLSD args;
+ args["NAME"] = self->mSelectedName;
+ args["N"] = llformat("%d",self->mSelectedCount);
if (self->mSelectedIsGroup)
{
- gViewerWindow->alertXml("ReturnObjectsDeededToGroup", args, callbackReturnOwnerList, userdata);
+ LLNotifications::instance().add("ReturnObjectsDeededToGroup", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOwnerList, self, _1, _2));
}
else
{
- gViewerWindow->alertXml("ReturnObjectsOwnedByUser", args, callbackReturnOwnerList, userdata);
+ LLNotifications::instance().add("ReturnObjectsOwnedByUser", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOwnerList, self, _1, _2));
}
}
@@ -1591,19 +1585,19 @@ void LLPanelLandObjects::onClickReturnOwnerObjects(void* userdata)
LLUUID owner_id = parcel->getOwnerID();
- LLStringUtil::format_map_t args;
- args["[N]"] = llformat("%d",owned);
+ LLSD args;
+ args["N"] = llformat("%d",owned);
if (owner_id == gAgent.getID())
{
- gViewerWindow->alertXml("ReturnObjectsOwnedBySelf", args, callbackReturnOwnerObjects, userdata);
+ LLNotifications::instance().add("ReturnObjectsOwnedBySelf", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOwnerObjects, panelp, _1, _2));
}
else
{
std::string name;
gCacheName->getFullName(owner_id, name);
- args["[NAME]"] = name;
- gViewerWindow->alertXml("ReturnObjectsOwnedByUser", args, callbackReturnOwnerObjects, userdata);
+ args["NAME"] = name;
+ LLNotifications::instance().add("ReturnObjectsOwnedByUser", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOwnerObjects, panelp, _1, _2));
}
}
@@ -1619,12 +1613,12 @@ void LLPanelLandObjects::onClickReturnGroupObjects(void* userdata)
std::string group_name;
gCacheName->getGroupName(parcel->getGroupID(), group_name);
- LLStringUtil::format_map_t args;
- args["[NAME]"] = group_name;
- args["[N]"] = llformat("%d", parcel->getGroupPrimCount());
+ LLSD args;
+ args["NAME"] = group_name;
+ args["N"] = llformat("%d", parcel->getGroupPrimCount());
// create and show confirmation textbox
- gViewerWindow->alertXml("ReturnObjectsDeededToGroup", args, callbackReturnGroupObjects, userdata);
+ LLNotifications::instance().add("ReturnObjectsDeededToGroup", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnGroupObjects, panelp, _1, _2));
}
// static
@@ -1640,16 +1634,16 @@ void LLPanelLandObjects::onClickReturnOtherObjects(void* userdata)
send_parcel_select_objects(parcel->getLocalID(), RT_OTHER);
- LLStringUtil::format_map_t args;
- args["[N]"] = llformat("%d", other);
+ LLSD args;
+ args["N"] = llformat("%d", other);
if (parcel->getIsGroupOwned())
{
std::string group_name;
gCacheName->getGroupName(parcel->getGroupID(), group_name);
- args["[NAME]"] = group_name;
+ args["NAME"] = group_name;
- gViewerWindow->alertXml("ReturnObjectsNotOwnedByGroup", args, callbackReturnOtherObjects, userdata);
+ LLNotifications::instance().add("ReturnObjectsNotOwnedByGroup", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOtherObjects, panelp, _1, _2));
}
else
{
@@ -1657,15 +1651,15 @@ void LLPanelLandObjects::onClickReturnOtherObjects(void* userdata)
if (owner_id == gAgent.getID())
{
- gViewerWindow->alertXml("ReturnObjectsNotOwnedBySelf", args, callbackReturnOtherObjects, userdata);
+ LLNotifications::instance().add("ReturnObjectsNotOwnedBySelf", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOtherObjects, panelp, _1, _2));
}
else
{
std::string name;
gCacheName->getFullName(owner_id, name);
- args["[NAME]"] = name;
+ args["NAME"] = name;
- gViewerWindow->alertXml("ReturnObjectsNotOwnedByUser", args, callbackReturnOtherObjects, userdata);
+ LLNotifications::instance().add("ReturnObjectsNotOwnedByUser", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOtherObjects, panelp, _1, _2));
}
}
}
@@ -2073,7 +2067,7 @@ void LLPanelLandOptions::onCommitAny(LLUICtrl *ctrl, void *userdata)
if (!allow_other_scripts && region && region->getAllowDamage())
{
- gViewerWindow->alertXml("UnableToDisableOutsideScripts");
+ LLNotifications::instance().add("UnableToDisableOutsideScripts");
return;
}
@@ -2117,7 +2111,7 @@ void LLPanelLandOptions::onClickSet(void* userdata)
if (agent_parcel->getLocalID() != selected_parcel->getLocalID())
{
- gViewerWindow->alertXml("MustBeInParcel");
+ LLNotifications::instance().add("MustBeInParcel");
return;
}
@@ -2160,11 +2154,11 @@ void LLPanelLandOptions::onClickPublishHelp(void*)
if(! can_change_identity)
{
- gViewerWindow->alertXml("ClickPublishHelpLandDisabled");
+ LLNotifications::instance().add("ClickPublishHelpLandDisabled");
}
else
{
- gViewerWindow->alertXml("ClickPublishHelpLand");
+ LLNotifications::instance().add("ClickPublishHelpLand");
}
}
diff --git a/indra/newview/llfloaterland.h b/indra/newview/llfloaterland.h
index 9bed9d53ae..1d95a3e3f6 100644
--- a/indra/newview/llfloaterland.h
+++ b/indra/newview/llfloaterland.h
@@ -151,8 +151,7 @@ public:
static void finalizeSetSellChange(void * userdata);
static void onSalePriceChange(LLUICtrl *ctrl, void * userdata);
- static void cbBuyPass(S32 option, void*);
- static BOOL buyPassDialogVisible();
+ static bool cbBuyPass(const LLSD& notification, const LLSD& response);
static void onClickSellLand(void* data);
static void onClickStopSellLand(void* data);
@@ -234,10 +233,10 @@ public:
void refresh();
virtual void draw();
- static void callbackReturnOwnerObjects(S32, void*);
- static void callbackReturnGroupObjects(S32, void*);
- static void callbackReturnOtherObjects(S32, void*);
- static void callbackReturnOwnerList(S32, void*);
+ bool callbackReturnOwnerObjects(const LLSD& notification, const LLSD& response);
+ bool callbackReturnGroupObjects(const LLSD& notification, const LLSD& response);
+ bool callbackReturnOtherObjects(const LLSD& notification, const LLSD& response);
+ bool callbackReturnOwnerList(const LLSD& notification, const LLSD& response);
static void clickShowCore(LLPanelLandObjects* panelp, S32 return_type, uuid_list_t* list = 0);
static void onClickShowOwnerObjects(void*);
diff --git a/indra/newview/llfloaternotificationsconsole.cpp b/indra/newview/llfloaternotificationsconsole.cpp
new file mode 100644
index 0000000000..12dcd58254
--- /dev/null
+++ b/indra/newview/llfloaternotificationsconsole.cpp
@@ -0,0 +1,292 @@
+/**
+ * @file llnotificationsconsole.cpp
+ * @brief Debugging console for unified notifications.
+ *
+ * $LicenseInfo:firstyear=2003&license=viewergpl$
+ *
+ * Copyright (c) 2003-2007, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llfloaternotificationsconsole.h"
+#include "llnotifications.h"
+#include "lluictrlfactory.h"
+#include "llbutton.h"
+#include "llscrolllistctrl.h"
+#include "llpanel.h"
+#include "llcombobox.h"
+#include "llviewertexteditor.h"
+
+const S32 NOTIFICATION_PANEL_HEADER_HEIGHT = 20;
+const S32 HEADER_PADDING = 38;
+
+class LLNotificationChannelPanel : public LLPanel
+{
+public:
+ LLNotificationChannelPanel(const std::string& channel_name);
+ BOOL postBuild();
+
+private:
+ bool update(const LLSD& payload, bool passed_filter);
+ static void toggleClick(void* user_data);
+ static void onClickNotification(void* user_data);
+ static void onClickNotificationReject(void* user_data);
+ LLNotificationChannelPtr mChannelPtr;
+ LLNotificationChannelPtr mChannelRejectsPtr;
+};
+
+LLNotificationChannelPanel::LLNotificationChannelPanel(const std::string& channel_name)
+ : LLPanel(channel_name)
+{
+ mChannelPtr = LLNotifications::instance().getChannel(channel_name);
+ mChannelRejectsPtr = LLNotificationChannelPtr(
+ new LLNotificationChannel(channel_name + "rejects", mChannelPtr->getParentChannelName(), !boost::bind(mChannelPtr->getFilter(), _1)));
+ LLUICtrlFactory::instance().buildPanel(this, "panel_notifications_channel.xml");
+}
+
+BOOL LLNotificationChannelPanel::postBuild()
+{
+ LLButton* header_button = getChild<LLButton>("header");
+ header_button->setLabel(mChannelPtr->getName());
+ header_button->setClickedCallback(toggleClick, this);
+
+ mChannelPtr->connectChanged(boost::bind(&LLNotificationChannelPanel::update, this, _1, true));
+ mChannelRejectsPtr->connectChanged(boost::bind(&LLNotificationChannelPanel::update, this, _1, false));
+
+ LLScrollListCtrl* scroll = getChild<LLScrollListCtrl>("notifications_list");
+ scroll->setDoubleClickCallback(onClickNotification);
+ scroll->setCallbackUserData(this);
+
+ scroll = getChild<LLScrollListCtrl>("notification_rejects_list");
+ scroll->setDoubleClickCallback(onClickNotificationReject);
+ scroll->setCallbackUserData(this);
+
+ return TRUE;
+}
+
+//static
+void LLNotificationChannelPanel::toggleClick(void *user_data)
+{
+ LLNotificationChannelPanel* self = (LLNotificationChannelPanel*)user_data;
+ if (!self) return;
+
+ LLButton* header_button = self->getChild<LLButton>("header");
+
+ LLLayoutStack* stack = dynamic_cast<LLLayoutStack*>(self->getParent());
+ if (stack)
+ {
+ stack->collapsePanel(self, header_button->getToggleState());
+ }
+
+ // turn off tab stop for collapsed panel
+ self->getChild<LLScrollListCtrl>("notifications_list")->setTabStop(!header_button->getToggleState());
+ self->getChild<LLScrollListCtrl>("notifications_list")->setVisible(!header_button->getToggleState());
+ self->getChild<LLScrollListCtrl>("notification_rejects_list")->setTabStop(!header_button->getToggleState());
+ self->getChild<LLScrollListCtrl>("notification_rejects_list")->setVisible(!header_button->getToggleState());
+}
+
+/*static*/
+void LLNotificationChannelPanel::onClickNotification(void* user_data)
+{
+ LLNotificationChannelPanel* self = (LLNotificationChannelPanel*)user_data;
+ if (!self) return;
+ void* data = self->getChild<LLScrollListCtrl>("notifications_list")->getFirstSelected()->getUserdata();
+ if (data)
+ {
+ gFloaterView->getParentFloater(self)->addDependentFloater(new LLFloaterNotification((LLNotification*)data), TRUE);
+ }
+}
+
+/*static*/
+void LLNotificationChannelPanel::onClickNotificationReject(void* user_data)
+{
+ LLNotificationChannelPanel* self = (LLNotificationChannelPanel*)user_data;
+ if (!self) return;
+ void* data = self->getChild<LLScrollListCtrl>("notification_rejects_list")->getFirstSelected()->getUserdata();
+ if (data)
+ {
+ gFloaterView->getParentFloater(self)->addDependentFloater(new LLFloaterNotification((LLNotification*)data), TRUE);
+ }
+}
+
+bool LLNotificationChannelPanel::update(const LLSD& payload, bool passed_filter)
+{
+ LLNotificationPtr notification = LLNotifications::instance().find(payload["id"].asUUID());
+ if (notification)
+ {
+ LLSD row;
+ row["columns"][0]["value"] = notification->getName();
+ row["columns"][0]["column"] = "name";
+
+ row["columns"][1]["value"] = notification->getMessage();
+ row["columns"][1]["column"] = "content";
+
+ row["columns"][2]["value"] = notification->getDate();
+ row["columns"][2]["column"] = "date";
+ row["columns"][2]["type"] = "date";
+
+ LLScrollListItem* sli = passed_filter ?
+ getChild<LLScrollListCtrl>("notifications_list")->addElement(row) :
+ getChild<LLScrollListCtrl>("notification_rejects_list")->addElement(row);
+ sli->setUserdata(&(*notification));
+ }
+
+ return false;
+}
+
+//
+// LLFloaterNotificationConsole
+//
+LLFloaterNotificationConsole::LLFloaterNotificationConsole(const LLSD& key)
+{
+ LLUICtrlFactory::instance().buildFloater(this, "floater_notifications_console.xml");
+}
+
+void LLFloaterNotificationConsole::onClose(bool app_quitting)
+{
+ setVisible(FALSE);
+ //destroy();
+}
+
+
+BOOL LLFloaterNotificationConsole::postBuild()
+{
+ // these are in the order of processing
+ addChannel("Unexpired");
+ addChannel("Ignore");
+ addChannel("Visible", true);
+ // all the ones below attach to the Visible channel
+ addChannel("History");
+ addChannel("Alerts");
+ addChannel("AlertModal");
+ addChannel("Group Notifications");
+ addChannel("Notifications");
+ addChannel("NotificationTips");
+
+ getChild<LLButton>("add_notification")->setClickedCallback(onClickAdd, this);
+
+ LLComboBox* notifications = getChild<LLComboBox>("notification_types");
+ LLNotifications::TemplateNames names = LLNotifications::instance().getTemplateNames();
+ for (LLNotifications::TemplateNames::iterator template_it = names.begin();
+ template_it != names.end();
+ ++template_it)
+ {
+ notifications->add(*template_it);
+ }
+ notifications->sortByName();
+
+ return TRUE;
+}
+
+void LLFloaterNotificationConsole::addChannel(const std::string& name, bool open)
+{
+ LLLayoutStack& stack = getChildRef<LLLayoutStack>("notification_channels");
+ LLNotificationChannelPanel* panelp = new LLNotificationChannelPanel(name);
+ stack.addPanel(panelp, 0, NOTIFICATION_PANEL_HEADER_HEIGHT, TRUE, TRUE, LLLayoutStack::ANIMATE);
+
+ LLButton& header_button = panelp->getChildRef<LLButton>("header");
+ header_button.setToggleState(!open);
+ stack.collapsePanel(panelp, !open);
+
+ updateResizeLimits();
+}
+
+void LLFloaterNotificationConsole::removeChannel(const std::string& name)
+{
+ LLPanel* panelp = getChild<LLPanel>(name, TRUE, FALSE);
+ if (panelp)
+ {
+ getChildRef<LLLayoutStack>("notification_channels").removePanel(panelp);
+ delete panelp;
+ }
+
+ updateResizeLimits();
+}
+
+//static
+void LLFloaterNotificationConsole::updateResizeLimits()
+{
+ LLLayoutStack& stack = getChildRef<LLLayoutStack>("notification_channels");
+ setResizeLimits(getMinWidth(), LLFLOATER_HEADER_SIZE + HEADER_PADDING + ((NOTIFICATION_PANEL_HEADER_HEIGHT + 3) * stack.getNumPanels()));
+}
+
+void LLFloaterNotificationConsole::onClickAdd(void* user_data)
+{
+ LLFloaterNotificationConsole* floater = (LLFloaterNotificationConsole*)user_data;
+
+ std::string message_name = floater->getChild<LLComboBox>("notification_types")->getValue().asString();
+ if (!message_name.empty())
+ {
+ LLNotifications::instance().add(message_name, LLSD());
+ }
+}
+
+
+//=============== LLFloaterNotification ================
+
+LLFloaterNotification::LLFloaterNotification(LLNotification* note) : mNote(note)
+{
+ LLUICtrlFactory::instance().buildFloater(this, "floater_notification.xml");
+}
+
+BOOL LLFloaterNotification::postBuild()
+{
+ setTitle(mNote->getName());
+ getChild<LLViewerTextEditor>("payload")->setText(mNote->getMessage());
+
+ LLComboBox* responses_combo = getChild<LLComboBox>("response");
+ LLCtrlListInterface* response_list = responses_combo->getListInterface();
+ LLNotificationFormPtr form(mNote->getForm());
+ if(!form)
+ {
+ return TRUE;
+ }
+
+ responses_combo->setCommitCallback(onCommitResponse);
+ responses_combo->setCallbackUserData(this);
+
+ LLSD form_sd = form->asLLSD();
+
+ for (LLSD::array_const_iterator form_item = form_sd.beginArray(); form_item != form_sd.endArray(); ++form_item)
+ {
+ if ( (*form_item)["type"].asString() != "button") continue;
+ std::string text = (*form_item)["text"].asString();
+ response_list->addSimpleElement(text);
+ }
+
+ return TRUE;
+}
+
+void LLFloaterNotification::respond()
+{
+ LLComboBox* responses_combo = getChild<LLComboBox>("response");
+ LLCtrlListInterface* response_list = responses_combo->getListInterface();
+ const std::string& trigger = response_list->getSelectedValue().asString();
+ //llinfos << trigger << llendl;
+
+ LLSD response = mNote->getResponseTemplate();
+ response[trigger] = true;
+ mNote->respond(response);
+}
diff --git a/indra/newview/llfloaternotificationsconsole.h b/indra/newview/llfloaternotificationsconsole.h
new file mode 100644
index 0000000000..5b8e79f0bb
--- /dev/null
+++ b/indra/newview/llfloaternotificationsconsole.h
@@ -0,0 +1,78 @@
+/**
+ * @file llfloaternotificationsconsole.h
+ * @brief Debugging console for unified notifications.
+ *
+ * $LicenseInfo:firstyear=2003&license=viewergpl$
+ *
+ * Copyright (c) 2003-2007, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLFLOATER_NOTIFICATIONS_CONSOLE_H
+#define LL_LLFLOATER_NOTIFICATIONS_CONSOLE_H
+
+#include "llfloater.h"
+#include "llnotifications.h"
+
+class LLFloaterNotificationConsole :
+ public LLFloater,
+ public LLFloaterSingleton<LLFloaterNotificationConsole>
+{
+public:
+ LLFloaterNotificationConsole(const LLSD& key);
+
+ // LLPanel
+ BOOL postBuild();
+ void onClose(bool app_quitting);
+
+ void addChannel(const std::string& type, bool open = false);
+ void updateResizeLimits(LLLayoutStack &stack);
+
+ void removeChannel(const std::string& type);
+ void updateResizeLimits();
+
+private:
+ static void onClickAdd(void* user_data);
+};
+
+
+/*
+ * @brief Pop-up debugging view of a generic new notification.
+ */
+class LLFloaterNotification : public LLFloater
+{
+public:
+ LLFloaterNotification(LLNotification* note);
+
+ // LLPanel
+ BOOL postBuild();
+ void respond();
+ void onClose(bool app_quitting) { setVisible(FALSE); }
+
+private:
+ static void onCommitResponse(LLUICtrl* ctrl, void* data) { ((LLFloaterNotification*)data)->respond(); }
+ LLNotification* mNote;
+};
+#endif
+
diff --git a/indra/newview/llfloateropenobject.cpp b/indra/newview/llfloateropenobject.cpp
index b1380ccd8c..55376c5634 100644
--- a/indra/newview/llfloateropenobject.cpp
+++ b/indra/newview/llfloateropenobject.cpp
@@ -109,7 +109,7 @@ void LLFloaterOpenObject::show()
LLObjectSelectionHandle object_selection = LLSelectMgr::getInstance()->getSelection();
if (object_selection->getRootObjectCount() != 1)
{
- gViewerWindow->alertXml("UnableToViewContentsMoreThanOne");
+ LLNotifications::instance().add("UnableToViewContentsMoreThanOne");
return;
}
@@ -131,7 +131,7 @@ void LLFloaterOpenObject::moveToInventory(bool wear)
{
if (mObjectSelection->getRootObjectCount() != 1)
{
- gViewerWindow->alertXml("OnlyCopyContentsOfSingleItem");
+ LLNotifications::instance().add("OnlyCopyContentsOfSingleItem");
return;
}
@@ -172,7 +172,7 @@ void LLFloaterOpenObject::moveToInventory(bool wear)
delete data;
data = NULL;
- gViewerWindow->alertXml("OpenObjectCannotCopy");
+ LLNotifications::instance().add("OpenObjectCannotCopy");
}
}
diff --git a/indra/newview/llfloaterperms.cpp b/indra/newview/llfloaterperms.cpp
index 9405bc61b2..c2d67d602a 100644
--- a/indra/newview/llfloaterperms.cpp
+++ b/indra/newview/llfloaterperms.cpp
@@ -153,5 +153,5 @@ U32 LLFloaterPerms::getNextOwnerPerms(std::string prefix)
//static
void LLFloaterPerms::onClickHelp(void* data)
{
- gViewerWindow->alertXml("ClickUploadHelpPermissions");
+ LLNotifications::instance().add("ClickUploadHelpPermissions");
}
diff --git a/indra/newview/llfloaterpostcard.cpp b/indra/newview/llfloaterpostcard.cpp
index 3182568fe8..f5a7a65abf 100644
--- a/indra/newview/llfloaterpostcard.cpp
+++ b/indra/newview/llfloaterpostcard.cpp
@@ -249,20 +249,20 @@ void LLFloaterPostcard::onClickSend(void* data)
if (to.empty() || !boost::regex_match(to, emailFormat))
{
- gViewerWindow->alertXml("PromptRecipientEmail");
+ LLNotifications::instance().add("PromptRecipientEmail");
return;
}
if (from.empty() || !boost::regex_match(from, emailFormat))
{
- gViewerWindow->alertXml("PromptSelfEmail");
+ LLNotifications::instance().add("PromptSelfEmail");
return;
}
std::string subject(self->childGetValue("subject_form").asString());
if(subject.empty() || !self->mHasFirstMsgFocus)
{
- gViewerWindow->alertXml("PromptMissingSubjMsg", missingSubjMsgAlertCallback, self);
+ LLNotifications::instance().add("PromptMissingSubjMsg", LLSD(), LLSD(), boost::bind(&LLFloaterPostcard::missingSubjMsgAlertCallback, self, _1, _2));
return;
}
@@ -272,7 +272,7 @@ void LLFloaterPostcard::onClickSend(void* data)
}
else
{
- gViewerWindow->alertXml("ErrorProcessingSnapshot");
+ LLNotifications::instance().add("ErrorProcessingSnapshot");
}
}
}
@@ -286,9 +286,9 @@ void LLFloaterPostcard::uploadCallback(const LLUUID& asset_id, void *user_data,
if (result)
{
- LLStringUtil::format_map_t args;
- args["[REASON]"] = std::string(LLAssetStorage::getErrorString(result));
- gViewerWindow->alertXml("ErrorUploadingPostcard", args);
+ LLSD args;
+ args["REASON"] = std::string(LLAssetStorage::getErrorString(result));
+ LLNotifications::instance().add("ErrorUploadingPostcard", args);
}
else
{
@@ -345,30 +345,28 @@ void LLFloaterPostcard::onMsgFormFocusRecieved(LLFocusableElement* receiver, voi
}
}
-void LLFloaterPostcard::missingSubjMsgAlertCallback(S32 option, void* data)
+bool LLFloaterPostcard::missingSubjMsgAlertCallback(const LLSD& notification, const LLSD& response)
{
- if(data)
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ if(0 == option)
{
- LLFloaterPostcard* self = static_cast<LLFloaterPostcard*>(data);
- if(0 == option)
+ // User clicked OK
+ if((childGetValue("subject_form").asString()).empty())
{
- // User clicked OK
- if((self->childGetValue("subject_form").asString()).empty())
- {
- // Stuff the subject back into the form.
- self->childSetValue("subject_form", self->getString("default_subject"));
- }
-
- if(!self->mHasFirstMsgFocus)
- {
- // The user never switched focus to the messagee window.
- // Using the default string.
- self->childSetValue("msg_form", self->getString("default_message"));
- }
+ // Stuff the subject back into the form.
+ childSetValue("subject_form", getString("default_subject"));
+ }
- self->sendPostcard();
+ if(!mHasFirstMsgFocus)
+ {
+ // The user never switched focus to the messagee window.
+ // Using the default string.
+ childSetValue("msg_form", getString("default_message"));
}
+
+ sendPostcard();
}
+ return false;
}
void LLFloaterPostcard::sendPostcard()
diff --git a/indra/newview/llfloaterpostcard.h b/indra/newview/llfloaterpostcard.h
index 28248f65df..94c619c7e5 100644
--- a/indra/newview/llfloaterpostcard.h
+++ b/indra/newview/llfloaterpostcard.h
@@ -65,7 +65,7 @@ public:
static void updateUserInfo(const std::string& email);
static void onMsgFormFocusRecieved(LLFocusableElement* receiver, void* data);
- static void missingSubjMsgAlertCallback(S32 option, void* data);
+ bool missingSubjMsgAlertCallback(const LLSD& notification, const LLSD& response);
void sendPostcard();
diff --git a/indra/newview/llfloaterpostprocess.cpp b/indra/newview/llfloaterpostprocess.cpp
index 692b7e036f..ce5f9c124f 100644
--- a/indra/newview/llfloaterpostprocess.cpp
+++ b/indra/newview/llfloaterpostprocess.cpp
@@ -169,11 +169,13 @@ void LLFloaterPostProcess::onSaveEffect(void* userData)
{
LLLineEditor* editBox = static_cast<LLLineEditor*>(userData);
- LLSD::String effectName(editBox->getValue().asString());
+ std::string effectName(editBox->getValue().asString());
if (gPostProcess->mAllEffects.has(effectName))
{
- gViewerWindow->alertXml("PPSaveEffectAlert", &LLFloaterPostProcess::saveAlertCallback, userData);
+ LLSD payload;
+ payload["effect_name"] = effectName;
+ LLNotifications::instance().add("PPSaveEffectAlert", LLSD(), payload, &LLFloaterPostProcess::saveAlertCallback);
}
else
{
@@ -192,20 +194,18 @@ void LLFloaterPostProcess::onChangeEffectName(LLUICtrl* ctrl, void * userData)
editBox->setValue(comboBox->getSelectedValue());
}
-void LLFloaterPostProcess::saveAlertCallback(S32 option, void* userData)
+bool LLFloaterPostProcess::saveAlertCallback(const LLSD& notification, const LLSD& response)
{
- LLLineEditor* editBox = static_cast<LLLineEditor*>(userData);
+ S32 option = LLNotification::getSelectedOption(notification, response);
// if they choose save, do it. Otherwise, don't do anything
if (option == 0)
{
- LLSD::String effectName(editBox->getValue().asString());
-
- gPostProcess->saveEffect(effectName);
+ gPostProcess->saveEffect(notification["payload"]["effect_name"].asString());
sPostProcess->syncMenu();
}
-
+ return false;
}
void LLFloaterPostProcess::show()
diff --git a/indra/newview/llfloaterpostprocess.h b/indra/newview/llfloaterpostprocess.h
index 8b590f8b8e..88d3fd04e7 100644
--- a/indra/newview/llfloaterpostprocess.h
+++ b/indra/newview/llfloaterpostprocess.h
@@ -68,7 +68,7 @@ public:
static void onChangeEffectName(LLUICtrl* ctrl, void * userData);
/// prompts a user when overwriting an effect
- static void saveAlertCallback(S32 option, void* userData);
+ static bool saveAlertCallback(const LLSD& notification, const LLSD& response);
/// show off our menu
static void show();
diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp
index 737a2afbb7..1e10f90609 100644
--- a/indra/newview/llfloaterregioninfo.cpp
+++ b/indra/newview/llfloaterregioninfo.cpp
@@ -59,6 +59,7 @@
#include "llfloatergroups.h"
#include "llfloatertelehub.h"
#include "llfloaterwindlight.h"
+#include "llinventorymodel.h"
#include "lllineeditor.h"
#include "llalertdialog.h"
#include "llnamelistctrl.h"
@@ -540,8 +541,8 @@ void LLPanelRegionInfo::initHelpBtn(const std::string& name, const std::string&
// static
void LLPanelRegionInfo::onClickHelp(void* data)
{
- const std::string* xml_alert = (std::string*)data;
- gViewerWindow->alertXml(*xml_alert);
+ std::string* xml_alert = (std::string*)data;
+ LLNotifications::instance().add(*xml_alert);
}
/////////////////////////////////////////////////////////////////////////////
@@ -638,16 +639,17 @@ void LLPanelRegionGeneralInfo::onKickCommit(const std::vector<std::string>& name
void LLPanelRegionGeneralInfo::onClickKickAll(void* userdata)
{
llinfos << "LLPanelRegionGeneralInfo::onClickKickAll" << llendl;
- gViewerWindow->alertXml("KickUsersFromRegion", onKickAllCommit, userdata);
+ LLNotifications::instance().add("KickUsersFromRegion",
+ LLSD(),
+ LLSD(),
+ boost::bind(&LLPanelRegionGeneralInfo::onKickAllCommit, (LLPanelRegionGeneralInfo*)userdata, _1, _2));
}
-// static
-void LLPanelRegionGeneralInfo::onKickAllCommit(S32 option, void* userdata)
+bool LLPanelRegionGeneralInfo::onKickAllCommit(const LLSD& notification, const LLSD& response)
{
+ S32 option = LLNotification::getSelectedOption(notification, response);
if (option == 0)
{
- LLPanelRegionGeneralInfo* self = (LLPanelRegionGeneralInfo*)userdata;
- if(!self) return;
strings_t strings;
// [0] = our agent id
std::string buffer;
@@ -656,26 +658,29 @@ void LLPanelRegionGeneralInfo::onKickAllCommit(S32 option, void* userdata)
LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
// historical message name
- self->sendEstateOwnerMessage(gMessageSystem, "teleporthomeallusers", invoice, strings);
+ sendEstateOwnerMessage(gMessageSystem, "teleporthomeallusers", invoice, strings);
}
+ return false;
}
// static
void LLPanelRegionGeneralInfo::onClickMessage(void* userdata)
{
llinfos << "LLPanelRegionGeneralInfo::onClickMessage" << llendl;
- gViewerWindow->alertXmlEditText("MessageRegion", LLStringUtil::format_map_t(),
- NULL, NULL,
- onMessageCommit, userdata);
+ LLNotifications::instance().add("MessageRegion",
+ LLSD(),
+ LLSD(),
+ boost::bind(&LLPanelRegionGeneralInfo::onMessageCommit, (LLPanelRegionGeneralInfo*)userdata, _1, _2));
}
// static
-void LLPanelRegionGeneralInfo::onMessageCommit(S32 option, const std::string& text, void* userdata)
+bool LLPanelRegionGeneralInfo::onMessageCommit(const LLSD& notification, const LLSD& response)
{
- if(option != 0) return;
- if(text.empty()) return;
- LLPanelRegionGeneralInfo* self = (LLPanelRegionGeneralInfo*)userdata;
- if(!self) return;
+ if(LLNotification::getSelectedOption(notification, response) != 0) return false;
+
+ std::string text = response["message"].asString();
+ if (text.empty()) return false;
+
llinfos << "Message to everyone: " << text << llendl;
strings_t strings;
// [0] grid_x, unused here
@@ -693,7 +698,8 @@ void LLPanelRegionGeneralInfo::onMessageCommit(S32 option, const std::string& te
strings.push_back(strings_t::value_type(name));
strings.push_back(strings_t::value_type(text));
LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
- self->sendEstateOwnerMessage(gMessageSystem, "simulatormessage", invoice, strings);
+ sendEstateOwnerMessage(gMessageSystem, "simulatormessage", invoice, strings);
+ return false;
}
// static
@@ -780,7 +786,7 @@ BOOL LLPanelRegionGeneralInfo::sendUpdate()
LLViewerRegion* region = gAgent.getRegion();
if (region && access != region->getSimAccess() )
{
- gViewerWindow->alertXml("RegionMaturityChange");
+ LLNotifications::instance().add("RegionMaturityChange");
}
}
@@ -881,48 +887,56 @@ void LLPanelRegionDebugInfo::onClickReturn(void* data)
LLPanelRegionDebugInfo* panelp = (LLPanelRegionDebugInfo*) data;
if (panelp->mTargetAvatar.isNull()) return;
- LLStringUtil::format_map_t args;
- args["[USER_NAME]"] = panelp->childGetValue("target_avatar_name").asString();
- gViewerWindow->alertXml("EstateObjectReturn", args, callbackReturn, data);
+ LLSD args;
+ args["USER_NAME"] = panelp->childGetValue("target_avatar_name").asString();
+ LLSD payload;
+ payload["avatar_id"] = panelp->mTargetAvatar;
+
+ U32 flags = SWD_ALWAYS_RETURN_OBJECTS;
+
+ if (panelp->childGetValue("return_scripts").asBoolean())
+ {
+ flags |= SWD_SCRIPTED_ONLY;
+ }
+
+ if (panelp->childGetValue("return_other_land").asBoolean())
+ {
+ flags |= SWD_OTHERS_LAND_ONLY;
+ }
+ payload["flags"] = int(flags);
+ payload["return_estate_wide"] = panelp->childGetValue("return_estate_wide").asBoolean();
+ LLNotifications::instance().add("EstateObjectReturn", args, payload,
+ boost::bind(&LLPanelRegionDebugInfo::callbackReturn, panelp, _1, _2));
}
-// static
-void LLPanelRegionDebugInfo::callbackReturn( S32 option, void* userdata )
+bool LLPanelRegionDebugInfo::callbackReturn(const LLSD& notification, const LLSD& response)
{
- if (option != 0) return;
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ if (option != 0) return false;
- LLPanelRegionDebugInfo* self = (LLPanelRegionDebugInfo*) userdata;
- if (!self->mTargetAvatar.isNull())
+ LLUUID target_avatar = notification["payload"]["avatar_id"].asUUID();
+ if (!target_avatar.isNull())
{
- U32 flags = SWD_ALWAYS_RETURN_OBJECTS;
-
- if (self->childGetValue("return_scripts").asBoolean())
- {
- flags |= SWD_SCRIPTED_ONLY;
- }
-
- if (self->childGetValue("return_other_land").asBoolean())
- {
- flags |= SWD_OTHERS_LAND_ONLY;
- }
-
- if (self->childGetValue("return_estate_wide").asBoolean())
+ U32 flags = notification["payload"]["flags"].asInteger();
+ bool return_estate_wide = notification["payload"]["return_estate_wide"];
+ if (return_estate_wide)
{
// send as estate message - routed by spaceserver to all regions in estate
strings_t strings;
strings.push_back(llformat("%d", flags));
- strings.push_back(self->mTargetAvatar.asString());
+ strings.push_back(target_avatar.asString());
LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
- self->sendEstateOwnerMessage(gMessageSystem, "estateobjectreturn", invoice, strings);
+ sendEstateOwnerMessage(gMessageSystem, "estateobjectreturn", invoice, strings);
}
else
{
// send to this simulator only
- send_sim_wide_deletes(self->mTargetAvatar, flags);
- }
+ send_sim_wide_deletes(target_avatar, flags);
+ }
}
+ return false;
}
@@ -953,19 +967,20 @@ void LLPanelRegionDebugInfo::onClickTopScripts(void* data)
// static
void LLPanelRegionDebugInfo::onClickRestart(void* data)
{
- gViewerWindow->alertXml("ConfirmRestart", callbackRestart, data);
+ LLNotifications::instance().add("ConfirmRestart", LLSD(), LLSD(),
+ boost::bind(&LLPanelRegionDebugInfo::callbackRestart, (LLPanelRegionDebugInfo*)data, _1, _2));
}
-// static
-void LLPanelRegionDebugInfo::callbackRestart(S32 option, void* data)
+bool LLPanelRegionDebugInfo::callbackRestart(const LLSD& notification, const LLSD& response)
{
- if (option != 0) return;
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ if (option != 0) return false;
- LLPanelRegionDebugInfo* self = (LLPanelRegionDebugInfo*)data;
strings_t strings;
strings.push_back("120");
LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
- self->sendEstateOwnerMessage(gMessageSystem, "restart", invoice, strings);
+ sendEstateOwnerMessage(gMessageSystem, "restart", invoice, strings);
+ return false;
}
// static
@@ -1123,21 +1138,21 @@ BOOL LLPanelRegionTextureInfo::validateTextureSizes()
if (components != 3)
{
- LLStringUtil::format_map_t args;
- args["[TEXTURE_NUM]"] = llformat("%d",i+1);
- args["[TEXTURE_BIT_DEPTH]"] = llformat("%d",components * 8);
- gViewerWindow->alertXml("InvalidTerrainBitDepth", args);
+ LLSD args;
+ args["TEXTURE_NUM"] = i+1;
+ args["TEXTURE_BIT_DEPTH"] = llformat("%d",components * 8);
+ LLNotifications::instance().add("InvalidTerrainBitDepth", args);
return FALSE;
}
if (width > 512 || height > 512)
{
- LLStringUtil::format_map_t args;
- args["[TEXTURE_NUM]"] = llformat("%d",i+1);
- args["[TEXTURE_SIZE_X]"] = llformat("%d",width);
- args["[TEXTURE_SIZE_Y]"] = llformat("%d",height);
- gViewerWindow->alertXml("InvalidTerrainSize", args);
+ LLSD args;
+ args["TEXTURE_NUM"] = i+1;
+ args["TEXTURE_SIZE_X"] = width;
+ args["TEXTURE_SIZE_Y"] = height;
+ LLNotifications::instance().add("InvalidTerrainSize", args);
return FALSE;
}
@@ -1334,26 +1349,27 @@ void LLPanelRegionTerrainInfo::onClickUploadRaw(void* data)
LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
self->sendEstateOwnerMessage(gMessageSystem, "terrain", invoice, strings);
- gViewerWindow->alertXml("RawUploadStarted");
+ LLNotifications::instance().add("RawUploadStarted");
}
// static
void LLPanelRegionTerrainInfo::onClickBakeTerrain(void* data)
{
- gViewerWindow->alertXml("ConfirmBakeTerrain",
- callbackBakeTerrain, data);
+ LLNotifications::instance().add(
+ LLNotification::Params("ConfirmBakeTerrain")
+ .functor(boost::bind(&LLPanelRegionTerrainInfo::callbackBakeTerrain, (LLPanelRegionTerrainInfo*)data, _1, _2)));
}
-// static
-void LLPanelRegionTerrainInfo::callbackBakeTerrain(S32 option, void* data)
+bool LLPanelRegionTerrainInfo::callbackBakeTerrain(const LLSD& notification, const LLSD& response)
{
- if (option != 0) return;
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ if (option != 0) return false;
- LLPanelRegionTerrainInfo* self = (LLPanelRegionTerrainInfo*)data;
strings_t strings;
strings.push_back("bake");
LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
- self->sendEstateOwnerMessage(gMessageSystem, "terrain", invoice, strings);
+ sendEstateOwnerMessage(gMessageSystem, "terrain", invoice, strings);
+ return false;
}
/////////////////////////////////////////////////////////////////////////////
@@ -1440,9 +1456,9 @@ void LLPanelEstateInfo::onClickAddAllowedAgent(void* user_data)
{
//args
- LLStringUtil::format_map_t args;
- args["[MAX_AGENTS]"] = llformat("%d",ESTATE_MAX_ACCESS_IDS);
- gViewerWindow->alertXml("MaxAllowedAgentOnRegion", args);
+ LLSD args;
+ args["MAX_AGENTS"] = llformat("%d",ESTATE_MAX_ACCESS_IDS);
+ LLNotifications::instance().add("MaxAllowedAgentOnRegion", args);
return;
}
accessAddCore(ESTATE_ACCESS_ALLOWED_AGENT_ADD, "EstateAllowedAgentAdd");
@@ -1462,35 +1478,36 @@ void LLPanelEstateInfo::onClickAddAllowedGroup(void* user_data)
if (!list) return;
if (list->getItemCount() >= ESTATE_MAX_ACCESS_IDS)
{
- LLStringUtil::format_map_t args;
- args["[MAX_GROUPS]"] = llformat("%d",ESTATE_MAX_ACCESS_IDS);
- gViewerWindow->alertXml("MaxAllowedGroupsOnRegion", args);
+ LLSD args;
+ args["MAX_GROUPS"] = llformat("%d",ESTATE_MAX_ACCESS_IDS);
+ LLNotifications::instance().add("MaxAllowedGroupsOnRegion", args);
return;
}
+
+ LLNotification::Params params("ChangeLindenAccess");
+ params.functor(boost::bind(&LLPanelEstateInfo::addAllowedGroup, self, _1, _2));
if (isLindenEstate())
{
- gViewerWindow->alertXml("ChangeLindenAccess", addAllowedGroup, user_data);
+ LLNotifications::instance().add(params);
}
else
{
- addAllowedGroup(0, user_data);
+ LLNotifications::instance().forceResponse(params, 0);
}
}
-// static
-void LLPanelEstateInfo::addAllowedGroup(S32 option, void* user_data)
+bool LLPanelEstateInfo::addAllowedGroup(const LLSD& notification, const LLSD& response)
{
- if (option != 0) return;
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ if (option != 0) return false;
- LLPanelEstateInfo* panelp = (LLPanelEstateInfo*)user_data;
-
- LLFloater* parent_floater = gFloaterView->getParentFloater(panelp);
+ LLFloater* parent_floater = gFloaterView->getParentFloater(this);
LLFloaterGroupPicker* widget;
widget = LLFloaterGroupPicker::showInstance(LLSD(gAgent.getID()));
if (widget)
{
- widget->setSelectCallback(addAllowedGroup2, user_data);
+ widget->setSelectCallback(addAllowedGroup2, NULL);
if (parent_floater)
{
LLRect new_rect = gFloaterView->findNeighboringPosition(parent_floater, widget);
@@ -1498,6 +1515,8 @@ void LLPanelEstateInfo::addAllowedGroup(S32 option, void* user_data)
parent_floater->addDependentFloater(widget);
}
}
+
+ return false;
}
// static
@@ -1514,9 +1533,9 @@ void LLPanelEstateInfo::onClickAddBannedAgent(void* user_data)
if (!list) return;
if (list->getItemCount() >= ESTATE_MAX_ACCESS_IDS)
{
- LLStringUtil::format_map_t args;
- args["[MAX_BANNED]"] = llformat("%d",ESTATE_MAX_ACCESS_IDS);
- gViewerWindow->alertXml("MaxBannedAgentsOnRegion", args);
+ LLSD args;
+ args["MAX_BANNED"] = llformat("%d",ESTATE_MAX_ACCESS_IDS);
+ LLNotifications::instance().add("MaxBannedAgentsOnRegion", args);
return;
}
accessAddCore(ESTATE_ACCESS_BANNED_AGENT_ADD, "EstateBannedAgentAdd");
@@ -1536,9 +1555,9 @@ void LLPanelEstateInfo::onClickAddEstateManager(void* user_data)
if (!list) return;
if (list->getItemCount() >= ESTATE_MAX_MANAGERS)
{ // Tell user they can't add more managers
- LLStringUtil::format_map_t args;
- args["[MAX_MANAGER]"] = llformat("%d",ESTATE_MAX_MANAGERS);
- gViewerWindow->alertXml("MaxManagersOnRegion", args);
+ LLSD args;
+ args["MAX_MANAGER"] = llformat("%d",ESTATE_MAX_MANAGERS);
+ LLNotifications::instance().add("MaxManagersOnRegion", args);
}
else
{ // Go pick managers to add
@@ -1558,7 +1577,6 @@ void LLPanelEstateInfo::onClickRemoveEstateManager(void* user_data)
struct LLKickFromEstateInfo
{
LLPanelEstateInfo *mEstatePanelp;
- std::string mDialogName;
LLUUID mAgentID;
};
@@ -1590,45 +1608,42 @@ void LLPanelEstateInfo::onKickUserCommit(const std::vector<std::string>& names,
//keep track of what user they want to kick and other misc info
LLKickFromEstateInfo *kick_info = new LLKickFromEstateInfo();
kick_info->mEstatePanelp = self;
- kick_info->mDialogName = "EstateKickUser";
kick_info->mAgentID = ids[0];
//Bring up a confirmation dialog
- LLStringUtil::format_map_t args;
- args["[EVIL_USER]"] = names[0];
- gViewerWindow->alertXml(kick_info->mDialogName, args, LLPanelEstateInfo::kickUserConfirm, (void*)kick_info);
+ LLSD args;
+ args["EVIL_USER"] = names[0];
+ LLSD payload;
+ payload["agent_id"] = ids[0];
+ LLNotifications::instance().add("EstateKickUser", args, payload, boost::bind(&LLPanelEstateInfo::kickUserConfirm, self, _1, _2));
}
-void LLPanelEstateInfo::kickUserConfirm(S32 option, void* userdata)
+bool LLPanelEstateInfo::kickUserConfirm(const LLSD& notification, const LLSD& response)
{
- //extract the callback parameter
- LLKickFromEstateInfo *kick_info = (LLKickFromEstateInfo*) userdata;
- if (!kick_info) return;
-
- LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
- strings_t strings;
- std::string buffer;
-
+ S32 option = LLNotification::getSelectedOption(notification, response);
switch(option)
{
case 0:
- //Kick User
- kick_info->mAgentID.toString(buffer);
- strings.push_back(buffer);
+ {
+ //Kick User
+ strings_t strings;
+ strings.push_back(notification["payload"]["agent_id"].asString());
- kick_info->mEstatePanelp->sendEstateOwnerMessage(gMessageSystem, "kickestate", invoice, strings);
- break;
+ sendEstateOwnerMessage(gMessageSystem, "kickestate", LLFloaterRegionInfo::getLastInvoice(), strings);
+ break;
+ }
default:
break;
}
-
- delete kick_info;
- kick_info = NULL;
+ return false;
}
//---------------------------------------------------------------------------
// Core Add/Remove estate access methods
+// TODO: INTERNATIONAL: don't build message text here;
+// instead, create multiple translatable messages and choose
+// one based on the status.
//---------------------------------------------------------------------------
std::string all_estates_text()
{
@@ -1669,6 +1684,33 @@ bool LLPanelEstateInfo::isLindenEstate()
typedef std::vector<LLUUID> AgentOrGroupIDsVector;
struct LLEstateAccessChangeInfo
{
+ LLEstateAccessChangeInfo(const LLSD& sd)
+ {
+ mDialogName = sd["dialog_name"].asString();
+ mOperationFlag = (U32)sd["operation"].asInteger();
+ LLSD::array_const_iterator end_it = sd["allowed_ids"].endArray();
+ for (LLSD::array_const_iterator id_it = sd["allowed_ids"].beginArray();
+ id_it != end_it;
+ ++id_it)
+ {
+ mAgentOrGroupIDs.push_back(id_it->asUUID());
+ }
+ }
+
+ const LLSD asLLSD() const
+ {
+ LLSD sd;
+ sd["name"] = mDialogName;
+ sd["operation"] = (S32)mOperationFlag;
+ for (AgentOrGroupIDsVector::const_iterator it = mAgentOrGroupIDs.begin();
+ it != mAgentOrGroupIDs.end();
+ ++it)
+ {
+ sd["allowed_ids"].append(*it);
+ }
+ return sd;
+ }
+
U32 mOperationFlag; // ESTATE_ACCESS_BANNED_AGENT_ADD, _REMOVE, etc.
std::string mDialogName;
AgentOrGroupIDsVector mAgentOrGroupIDs; // List of agent IDs to apply to this change
@@ -1678,56 +1720,65 @@ struct LLEstateAccessChangeInfo
// static
void LLPanelEstateInfo::addAllowedGroup2(LLUUID id, void* user_data)
{
- LLEstateAccessChangeInfo* change_info = new LLEstateAccessChangeInfo;
- change_info->mOperationFlag = ESTATE_ACCESS_ALLOWED_GROUP_ADD;
- change_info->mDialogName = "EstateAllowedGroupAdd";
- change_info->mAgentOrGroupIDs.push_back(id);
+ LLSD payload;
+ payload["operation"] = (S32)ESTATE_ACCESS_ALLOWED_GROUP_ADD;
+ payload["dialog_name"] = "EstateAllowedGroupAdd";
+ payload["allowed_ids"].append(id);
+
+ LLSD args;
+ args["ALL_ESTATES"] = all_estates_text();
+ LLNotification::Params params("EstateAllowedGroupAdd");
+ params.payload(payload)
+ .substitutions(args)
+ .functor(accessCoreConfirm);
if (isLindenEstate())
{
- accessCoreConfirm(0, (void*)change_info);
+ LLNotifications::instance().forceResponse(params, 0);
}
else
{
- LLStringUtil::format_map_t args;
- args["[ALL_ESTATES]"] = all_estates_text();
- gViewerWindow->alertXml(change_info->mDialogName, args, accessCoreConfirm, (void*)change_info);
+ LLNotifications::instance().add(params);
}
}
// static
void LLPanelEstateInfo::accessAddCore(U32 operation_flag, const std::string& dialog_name)
{
- LLEstateAccessChangeInfo* change_info = new LLEstateAccessChangeInfo;
- change_info->mOperationFlag = operation_flag;
- change_info->mDialogName = dialog_name;
+ LLSD payload;
+ payload["operation"] = (S32)operation_flag;
+ payload["dialog_name"] = dialog_name;
// agent id filled in after avatar picker
+ LLNotification::Params params("ChangeLindenAccess");
+ params.payload(payload)
+ .functor(accessAddCore2);
+
if (isLindenEstate())
{
- gViewerWindow->alertXml("ChangeLindenAccess", accessAddCore2, change_info);
+ LLNotifications::instance().add(params);
}
else
{
// same as clicking "OK"
- accessAddCore2(0, change_info);
+ LLNotifications::instance().forceResponse(params, 0);
}
}
// static
-void LLPanelEstateInfo::accessAddCore2(S32 option, void* data)
+bool LLPanelEstateInfo::accessAddCore2(const LLSD& notification, const LLSD& response)
{
- LLEstateAccessChangeInfo* change_info = (LLEstateAccessChangeInfo*)data;
+ S32 option = LLNotification::getSelectedOption(notification, response);
if (option != 0)
{
// abort change
- delete change_info;
- change_info = NULL;
- return;
+ return false;
}
+ LLEstateAccessChangeInfo* change_info = new LLEstateAccessChangeInfo(notification["payload"]);
// avatar picker yes multi-select, yes close-on-select
LLFloaterAvatarPicker::show(accessAddCore3, (void*)change_info, TRUE, TRUE);
+ return false;
}
// static
@@ -1756,12 +1807,12 @@ void LLPanelEstateInfo::accessAddCore3(const std::vector<std::string>& names, co
int currentCount = (list ? list->getItemCount() : 0);
if (ids.size() + currentCount > ESTATE_MAX_ACCESS_IDS)
{
- LLStringUtil::format_map_t args;
- args["[NUM_ADDED]"] = llformat("%d",ids.size());
- args["[MAX_AGENTS]"] = llformat("%d",ESTATE_MAX_ACCESS_IDS);
- args["[LIST_TYPE]"] = "Allowed Residents";
- args["[NUM_EXCESS]"] = llformat("%d",(ids.size()+currentCount)-ESTATE_MAX_ACCESS_IDS);
- gViewerWindow->alertXml("MaxAgentOnRegionBatch", args);
+ LLSD args;
+ args["NUM_ADDED"] = llformat("%d",ids.size());
+ args["MAX_AGENTS"] = llformat("%d",ESTATE_MAX_ACCESS_IDS);
+ args["LIST_TYPE"] = "Allowed Residents";
+ args["NUM_EXCESS"] = llformat("%d",(ids.size()+currentCount)-ESTATE_MAX_ACCESS_IDS);
+ LLNotifications::instance().add("MaxAgentOnRegionBatch", args);
delete change_info;
return;
}
@@ -1772,28 +1823,34 @@ void LLPanelEstateInfo::accessAddCore3(const std::vector<std::string>& names, co
int currentCount = (list ? list->getItemCount() : 0);
if (ids.size() + currentCount > ESTATE_MAX_ACCESS_IDS)
{
- LLStringUtil::format_map_t args;
- args["[NUM_ADDED]"] = llformat("%d",ids.size());
- args["[MAX_AGENTS]"] = llformat("%d",ESTATE_MAX_ACCESS_IDS);
- args["[LIST_TYPE]"] = "Banned Residents";
- args["[NUM_EXCESS]"] = llformat("%d",(ids.size()+currentCount)-ESTATE_MAX_ACCESS_IDS);
- gViewerWindow->alertXml("MaxAgentOnRegionBatch", args);
+ LLSD args;
+ args["NUM_ADDED"] = llformat("%d",ids.size());
+ args["MAX_AGENTS"] = llformat("%d",ESTATE_MAX_ACCESS_IDS);
+ args["LIST_TYPE"] = "Banned Residents";
+ args["NUM_EXCESS"] = llformat("%d",(ids.size()+currentCount)-ESTATE_MAX_ACCESS_IDS);
+ LLNotifications::instance().add("MaxAgentOnRegionBatch", args);
delete change_info;
return;
}
}
+ LLSD args;
+ args["ALL_ESTATES"] = all_estates_text();
+
+ LLNotification::Params params(change_info->mDialogName);
+ params.substitutions(args)
+ .payload(change_info->asLLSD())
+ .functor(accessCoreConfirm);
+
if (isLindenEstate())
{
// just apply to this estate
- accessCoreConfirm(0, (void*)change_info);
+ LLNotifications::instance().forceResponse(params, 0);
}
else
{
// ask if this estate or all estates with this owner
- LLStringUtil::format_map_t args;
- args["[ALL_ESTATES]"] = all_estates_text();
- gViewerWindow->alertXml(change_info->mDialogName, args, accessCoreConfirm, (void*)change_info);
+ LLNotifications::instance().add(params);
}
}
@@ -1809,85 +1866,87 @@ void LLPanelEstateInfo::accessRemoveCore(U32 operation_flag, const std::string&
if (list_vector.size() == 0)
return;
- LLEstateAccessChangeInfo* change_info = new LLEstateAccessChangeInfo;
- change_info->mOperationFlag = operation_flag;
- change_info->mDialogName = dialog_name;
+ LLSD payload;
+ payload["operation"] = (S32)operation_flag;
+ payload["dialog_name"] = dialog_name;
for (std::vector<LLScrollListItem*>::const_iterator iter = list_vector.begin();
iter != list_vector.end();
iter++)
{
LLScrollListItem *item = (*iter);
- change_info->mAgentOrGroupIDs.push_back(item->getUUID());
+ payload["allowed_ids"].append(item->getUUID());
}
+ LLNotification::Params params("ChangeLindenAccess");
+ params.payload(payload)
+ .functor(accessRemoveCore2);
+
if (isLindenEstate())
{
// warn on change linden estate
- gViewerWindow->alertXml("ChangeLindenAccess",
- accessRemoveCore2,
- (void*)change_info);
+ LLNotifications::instance().add(params);
}
else
{
// just proceed, as if clicking OK
- accessRemoveCore2(0, (void*)change_info);
+ LLNotifications::instance().forceResponse(params, 0);
}
}
// static
-void LLPanelEstateInfo::accessRemoveCore2(S32 option, void* data)
+bool LLPanelEstateInfo::accessRemoveCore2(const LLSD& notification, const LLSD& response)
{
- LLEstateAccessChangeInfo* change_info = (LLEstateAccessChangeInfo*)data;
+ S32 option = LLNotification::getSelectedOption(notification, response);
if (option != 0)
{
// abort
- delete change_info;
- change_info = NULL;
- return;
+ return false;
}
// If Linden estate, can only apply to "this" estate, not all estates
// owned by NULL.
if (isLindenEstate())
{
- accessCoreConfirm(0, (void*)change_info);
+ accessCoreConfirm(notification, response);
}
else
{
- LLStringUtil::format_map_t args;
- args["[ALL_ESTATES]"] = all_estates_text();
- gViewerWindow->alertXml(change_info->mDialogName,
- args,
- accessCoreConfirm,
- (void*)change_info);
+ LLSD args;
+ args["ALL_ESTATES"] = all_estates_text();
+ LLNotifications::instance().add(notification["payload"]["dialog_name"],
+ args,
+ notification["payload"],
+ accessCoreConfirm);
}
+ return false;
}
// Used for both access add and remove operations, depending on the mOperationFlag
// passed in (ESTATE_ACCESS_BANNED_AGENT_ADD, ESTATE_ACCESS_ALLOWED_AGENT_REMOVE, etc.)
// static
-void LLPanelEstateInfo::accessCoreConfirm(S32 option, void* data)
+bool LLPanelEstateInfo::accessCoreConfirm(const LLSD& notification, const LLSD& response)
{
- LLEstateAccessChangeInfo* change_info = (LLEstateAccessChangeInfo*)data;
- const U32 originalFlags = change_info->mOperationFlag;
- AgentOrGroupIDsVector& ids = change_info->mAgentOrGroupIDs;
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ const U32 originalFlags = (U32)notification["payload"]["operation"].asInteger();
LLViewerRegion* region = gAgent.getRegion();
- for (AgentOrGroupIDsVector::const_iterator iter = ids.begin();
- iter != ids.end();
+ LLSD::array_const_iterator end_it = notification["payload"]["allowed_ids"].endArray();
+
+ for (LLSD::array_const_iterator iter = notification["payload"]["allowed_ids"].beginArray();
+ iter != end_it;
iter++)
{
U32 flags = originalFlags;
- if (iter + 1 != ids.end())
+ if (iter + 1 != end_it)
flags |= ESTATE_ACCESS_NO_REPLY;
- const LLUUID id = (*iter);
- if ((change_info->mOperationFlag & ESTATE_ACCESS_BANNED_AGENT_ADD)
+ const LLUUID id = iter->asUUID();
+ if (((U32)notification["payload"]["operation"].asInteger() & ESTATE_ACCESS_BANNED_AGENT_ADD)
&& region && (region->getOwner() == id))
{
- gViewerWindow->alertXml("OwnerCanNotBeDenied");
+ LLNotifications::instance().add("OwnerCanNotBeDenied");
break;
}
switch(option)
@@ -1919,8 +1978,7 @@ void LLPanelEstateInfo::accessCoreConfirm(S32 option, void* data)
break;
}
}
- delete change_info;
- change_info = NULL;
+ return false;
}
// key = "estateaccessdelta"
@@ -2146,34 +2204,34 @@ BOOL LLPanelEstateInfo::sendUpdate()
{
llinfos << "LLPanelEsateInfo::sendUpdate()" << llendl;
+ LLNotification::Params params("ChangeLindenEstate");
+ params.functor(boost::bind(&LLPanelEstateInfo::callbackChangeLindenEstate, this, _1, _2));
+
if (getEstateID() <= ESTATE_LAST_LINDEN)
{
// trying to change reserved estate, warn
- gViewerWindow->alertXml("ChangeLindenEstate",
- callbackChangeLindenEstate,
- this);
+ LLNotifications::instance().add(params);
}
else
{
// for normal estates, just make the change
- callbackChangeLindenEstate(0, this);
+ LLNotifications::instance().forceResponse(params, 0);
}
return TRUE;
}
-// static
-void LLPanelEstateInfo::callbackChangeLindenEstate(S32 option, void* data)
+bool LLPanelEstateInfo::callbackChangeLindenEstate(const LLSD& notification, const LLSD& response)
{
- LLPanelEstateInfo* self = (LLPanelEstateInfo*)data;
+ S32 option = LLNotification::getSelectedOption(notification, response);
switch(option)
{
case 0:
// send the update
- if (!self->commitEstateInfoCaps())
+ if (!commitEstateInfoCaps())
{
// the caps method failed, try the old way
LLFloaterRegionInfo::nextInvoice();
- self->commitEstateInfoDataserver();
+ commitEstateInfoDataserver();
}
// we don't want to do this because we'll get it automatically from the sim
// after the spaceserver processes it
@@ -2188,6 +2246,7 @@ void LLPanelEstateInfo::callbackChangeLindenEstate(S32 option, void* data)
// do nothing
break;
}
+ return false;
}
@@ -2572,18 +2631,15 @@ BOOL LLPanelEstateInfo::checkSunHourSlider(LLUICtrl* child_ctrl)
void LLPanelEstateInfo::onClickMessageEstate(void* userdata)
{
llinfos << "LLPanelEstateInfo::onClickMessageEstate" << llendl;
- gViewerWindow->alertXmlEditText("MessageEstate", LLStringUtil::format_map_t(),
- NULL, NULL,
- onMessageCommit, userdata);
+ LLNotifications::instance().add("MessageEstate", LLSD(), LLSD(), boost::bind(&LLPanelEstateInfo::onMessageCommit, (LLPanelEstateInfo*)userdata, _1, _2));
}
-// static
-void LLPanelEstateInfo::onMessageCommit(S32 option, const std::string& text, void* userdata)
+bool LLPanelEstateInfo::onMessageCommit(const LLSD& notification, const LLSD& response)
{
- if(option != 0) return;
- if(text.empty()) return;
- LLPanelEstateInfo* self = (LLPanelEstateInfo*)userdata;
- if(!self) return;
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ std::string text = response["message"].asString();
+ if(option != 0) return false;
+ if(text.empty()) return false;
llinfos << "Message to everyone: " << text << llendl;
strings_t strings;
//integers_t integers;
@@ -2592,7 +2648,8 @@ void LLPanelEstateInfo::onMessageCommit(S32 option, const std::string& text, voi
strings.push_back(strings_t::value_type(name));
strings.push_back(strings_t::value_type(text));
LLUUID invoice(LLFloaterRegionInfo::getLastInvoice());
- self->sendEstateOwnerMessage(gMessageSystem, "instantmessage", invoice, strings);
+ sendEstateOwnerMessage(gMessageSystem, "instantmessage", invoice, strings);
+ return false;
}
LLPanelEstateCovenant::LLPanelEstateCovenant()
@@ -2695,9 +2752,10 @@ BOOL LLPanelEstateCovenant::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop
*accept = ACCEPT_YES_COPY_SINGLE;
if (item && drop)
{
- gViewerWindow->alertXml("EstateChangeCovenant",
- LLPanelEstateCovenant::confirmChangeCovenantCallback,
- item);
+ LLSD payload;
+ payload["item_id"] = item->getUUID();
+ LLNotifications::instance().add("EstateChangeCovenant", LLSD(), payload,
+ LLPanelEstateCovenant::confirmChangeCovenantCallback);
}
break;
default:
@@ -2709,12 +2767,13 @@ BOOL LLPanelEstateCovenant::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop
}
// static
-void LLPanelEstateCovenant::confirmChangeCovenantCallback(S32 option, void* userdata)
+bool LLPanelEstateCovenant::confirmChangeCovenantCallback(const LLSD& notification, const LLSD& response)
{
- LLInventoryItem* item = (LLInventoryItem*)userdata;
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ LLInventoryItem* item = gInventory.getItem(notification["payload"]["item_id"].asUUID());
LLPanelEstateCovenant* self = LLFloaterRegionInfo::getPanelCovenant();
- if (!item || !self) return;
+ if (!item || !self) return false;
switch(option)
{
@@ -2724,22 +2783,22 @@ void LLPanelEstateCovenant::confirmChangeCovenantCallback(S32 option, void* user
default:
break;
}
+ return false;
}
// static
void LLPanelEstateCovenant::resetCovenantID(void* userdata)
{
- gViewerWindow->alertXml("EstateChangeCovenant",
- LLPanelEstateCovenant::confirmResetCovenantCallback,
- NULL);
+ LLNotifications::instance().add("EstateChangeCovenant", LLSD(), LLSD(), confirmResetCovenantCallback);
}
// static
-void LLPanelEstateCovenant::confirmResetCovenantCallback(S32 option, void* userdata)
+bool LLPanelEstateCovenant::confirmResetCovenantCallback(const LLSD& notification, const LLSD& response)
{
LLPanelEstateCovenant* self = LLFloaterRegionInfo::getPanelCovenant();
- if (!self) return;
+ if (!self) return false;
+ S32 option = LLNotification::getSelectedOption(notification, response);
switch(option)
{
case 0:
@@ -2748,6 +2807,7 @@ void LLPanelEstateCovenant::confirmResetCovenantCallback(S32 option, void* userd
default:
break;
}
+ return false;
}
void LLPanelEstateCovenant::loadInvItem(LLInventoryItem *itemp)
@@ -2808,7 +2868,7 @@ void LLPanelEstateCovenant::onLoadComplete(LLVFS *vfs,
if( !panelp->mEditor->importBuffer( buffer, file_length+1 ) )
{
llwarns << "Problem importing estate covenant." << llendl;
- gViewerWindow->alertXml("ProblemImportingEstateCovenant");
+ LLNotifications::instance().add("ProblemImportingEstateCovenant");
}
else
{
@@ -2829,15 +2889,15 @@ void LLPanelEstateCovenant::onLoadComplete(LLVFS *vfs,
if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status ||
LL_ERR_FILE_EMPTY == status)
{
- gViewerWindow->alertXml("MissingNotecardAssetID");
+ LLNotifications::instance().add("MissingNotecardAssetID");
}
else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status)
{
- gViewerWindow->alertXml("NotAllowedToViewNotecard");
+ LLNotifications::instance().add("NotAllowedToViewNotecard");
}
else
{
- gViewerWindow->alertXml("UnableToLoadNotecard");
+ LLNotifications::instance().add("UnableToLoadNotecardAsset");
}
llwarns << "Problem loading notecard: " << status << llendl;
diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h
index 8580189a2e..8c14e463ff 100644
--- a/indra/newview/llfloaterregioninfo.h
+++ b/indra/newview/llfloaterregioninfo.h
@@ -161,9 +161,9 @@ protected:
static void onClickKick(void* userdata);
static void onKickCommit(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* userdata);
static void onClickKickAll(void* userdata);
- static void onKickAllCommit(S32 option, void* userdata);
+ bool onKickAllCommit(const LLSD& notification, const LLSD& response);
static void onClickMessage(void* userdata);
- static void onMessageCommit(S32 option, const std::string& text, void* userdata);
+ bool onMessageCommit(const LLSD& notification, const LLSD& response);
static void onClickManageTelehub(void* data);
};
@@ -186,11 +186,11 @@ protected:
static void onClickChooseAvatar(void*);
static void callbackAvatarID(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* data);
static void onClickReturn(void *);
- static void callbackReturn(S32 option, void*);
+ bool callbackReturn(const LLSD& notification, const LLSD& response);
static void onClickTopColliders(void*);
static void onClickTopScripts(void*);
static void onClickRestart(void* data);
- static void callbackRestart(S32 option, void* data);
+ bool callbackRestart(const LLSD& notification, const LLSD& response);
static void onClickCancelRestart(void* data);
private:
@@ -240,7 +240,7 @@ protected:
static void onClickDownloadRaw(void*);
static void onClickUploadRaw(void*);
static void onClickBakeTerrain(void*);
- static void callbackBakeTerrain(S32 option, void* data);
+ bool callbackBakeTerrain(const LLSD& notification, const LLSD& response);
};
/////////////////////////////////////////////////////////////////////////////
@@ -269,27 +269,27 @@ public:
static void onClickKickUser(void* userdata);
// Group picker callback is different, can't use core methods below
- static void addAllowedGroup(S32 option, void* data);
+ bool addAllowedGroup(const LLSD& notification, const LLSD& response);
static void addAllowedGroup2(LLUUID id, void* data);
// Core methods for all above add/remove button clicks
static void accessAddCore(U32 operation_flag, const std::string& dialog_name);
- static void accessAddCore2(S32 option, void* data);
+ static bool accessAddCore2(const LLSD& notification, const LLSD& response);
static void accessAddCore3(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* data);
static void accessRemoveCore(U32 operation_flag, const std::string& dialog_name, const std::string& list_ctrl_name);
- static void accessRemoveCore2(S32 option, void* data);
+ static bool accessRemoveCore2(const LLSD& notification, const LLSD& response);
// used for both add and remove operations
- static void accessCoreConfirm(S32 option, void* data);
- static void kickUserConfirm(S32 option, void* userdata);
+ static bool accessCoreConfirm(const LLSD& notification, const LLSD& response);
+ bool kickUserConfirm(const LLSD& notification, const LLSD& response);
// Send the actual EstateOwnerRequest "estateaccessdelta" message
static void sendEstateAccessDelta(U32 flags, const LLUUID& agent_id);
static void onKickUserCommit(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* userdata);
static void onClickMessageEstate(void* data);
- static void onMessageCommit(S32 option, const std::string& text, void* data);
+ bool onMessageCommit(const LLSD& notification, const LLSD& response);
LLPanelEstateInfo();
~LLPanelEstateInfo() {}
@@ -344,7 +344,7 @@ public:
protected:
virtual BOOL sendUpdate();
// confirmation dialog callback
- static void callbackChangeLindenEstate(S32 opt, void* data);
+ bool callbackChangeLindenEstate(const LLSD& notification, const LLSD& response);
void commitEstateInfoDataserver();
bool commitEstateInfoCaps();
@@ -377,9 +377,9 @@ public:
BOOL drop, EDragAndDropType cargo_type,
void *cargo_data, EAcceptance *accept,
std::string& tooltip_msg);
- static void confirmChangeCovenantCallback(S32 option, void* userdata);
+ static bool confirmChangeCovenantCallback(const LLSD& notification, const LLSD& response);
static void resetCovenantID(void* userdata);
- static void confirmResetCovenantCallback(S32 option, void* userdata);
+ static bool confirmResetCovenantCallback(const LLSD& notification, const LLSD& response);
void sendChangeCovenantID(const LLUUID &asset_id);
void loadInvItem(LLInventoryItem *itemp);
static void onLoadComplete(LLVFS *vfs,
diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp
index da435c9452..e87ffeb258 100644
--- a/indra/newview/llfloaterreporter.cpp
+++ b/indra/newview/llfloaterreporter.cpp
@@ -207,10 +207,10 @@ void LLFloaterReporter::processRegionInfo(LLMessageSystem* msg)
{
if ( gEmailToEstateOwner )
{
- gViewerWindow->alertXml("HelpReportAbuseEmailEO");
+ LLNotifications::instance().add("HelpReportAbuseEmailEO");
}
else
- gViewerWindow->alertXml("HelpReportAbuseEmailLL");
+ LLNotifications::instance().add("HelpReportAbuseEmailLL");
};
}
@@ -406,7 +406,7 @@ void LLFloaterReporter::onClickSend(void *userdata)
category_value == IP_CONTENT_REMOVAL ||
category_value == IP_PERMISSONS_EXPLOIT)
{
- gViewerWindow->alertXml("HelpReportAbuseContainsCopyright");
+ LLNotifications::instance().add("HelpReportAbuseContainsCopyright");
self->mCopyrightWarningSeen = TRUE;
return;
}
@@ -415,7 +415,7 @@ void LLFloaterReporter::onClickSend(void *userdata)
{
// IP_CONTENT_REMOVAL *always* shows the dialog -
// ergo you can never send that abuse report type.
- gViewerWindow->alertXml("HelpReportAbuseContainsCopyright");
+ LLNotifications::instance().add("HelpReportAbuseContainsCopyright");
return;
}
}
@@ -524,7 +524,7 @@ void LLFloaterReporter::showFromMenu(EReportType report_type)
if (report_type == BUG_REPORT)
{
- gViewerWindow->alertXml("HelpReportBug");
+ LLNotifications::instance().add("HelpReportBug");
}
else
{
@@ -610,11 +610,11 @@ bool LLFloaterReporter::validateReport()
{
if ( mReportType != BUG_REPORT )
{
- gViewerWindow->alertXml("HelpReportAbuseSelectCategory");
+ LLNotifications::instance().add("HelpReportAbuseSelectCategory");
}
else
{
- gViewerWindow->alertXml("HelpReportBugSelectCategory");
+ LLNotifications::instance().add("HelpReportBugSelectCategory");
}
return false;
}
@@ -623,13 +623,13 @@ bool LLFloaterReporter::validateReport()
{
if ( childGetText("abuser_name_edit").empty() )
{
- gViewerWindow->alertXml("HelpReportAbuseAbuserNameEmpty");
+ LLNotifications::instance().add("HelpReportAbuseAbuserNameEmpty");
return false;
};
if ( childGetText("abuse_location_edit").empty() )
{
- gViewerWindow->alertXml("HelpReportAbuseAbuserLocationEmpty");
+ LLNotifications::instance().add("HelpReportAbuseAbuserLocationEmpty");
return false;
};
};
@@ -638,11 +638,11 @@ bool LLFloaterReporter::validateReport()
{
if ( mReportType != BUG_REPORT )
{
- gViewerWindow->alertXml("HelpReportAbuseSummaryEmpty");
+ LLNotifications::instance().add("HelpReportAbuseSummaryEmpty");
}
else
{
- gViewerWindow->alertXml("HelpReportBugSummaryEmpty");
+ LLNotifications::instance().add("HelpReportBugSummaryEmpty");
}
return false;
};
@@ -651,11 +651,11 @@ bool LLFloaterReporter::validateReport()
{
if ( mReportType != BUG_REPORT )
{
- gViewerWindow->alertXml("HelpReportAbuseDetailsEmpty");
+ LLNotifications::instance().add("HelpReportAbuseDetailsEmpty");
}
else
{
- gViewerWindow->alertXml("HelpReportBugDetailsEmpty");
+ LLNotifications::instance().add("HelpReportBugDetailsEmpty");
}
return false;
};
@@ -951,13 +951,12 @@ void LLFloaterReporter::uploadDoneCallback(const LLUUID &uuid, void *user_data,
if(result < 0)
{
- LLStringUtil::format_map_t args;
- std::string reason = std::string(LLAssetStorage::getErrorString(result));
- args["[REASON]"] = reason;
- gViewerWindow->alertXml("ErrorUploadingReportScreenshot", args);
+ LLSD args;
+ args["REASON"] = std::string(LLAssetStorage::getErrorString(result));
+ LLNotifications::instance().add("ErrorUploadingReportScreenshot", args);
std::string err_msg("There was a problem uploading a report screenshot");
- err_msg += " due to the following reason: " + reason;
+ err_msg += " due to the following reason: " + args["REASON"].asString();
llwarns << err_msg << llendl;
return;
}
diff --git a/indra/newview/llfloatersellland.cpp b/indra/newview/llfloatersellland.cpp
index 749ccbe7fa..1e1d1f6fd2 100644
--- a/indra/newview/llfloatersellland.cpp
+++ b/indra/newview/llfloatersellland.cpp
@@ -79,9 +79,9 @@ private:
static void doSelectAgent(void *userdata);
static void doCancel(void *userdata);
static void doSellLand(void *userdata);
- static void onConfirmSale(S32 option, void *userdata);
+ bool onConfirmSale(const LLSD& notification, const LLSD& response);
static void doShowObjects(void *userdata);
- static void callbackHighlightTransferable(S32 option, void* userdata);
+ static bool callbackHighlightTransferable(const LLSD& notification, const LLSD& response);
static void callbackAvatarPick(const std::vector<std::string>& names, const std::vector<LLUUID>& ids, void* data);
@@ -443,15 +443,16 @@ void LLFloaterSellLandUI::doShowObjects(void *userdata)
send_parcel_select_objects(parcel->getLocalID(), RT_SELL);
- LLNotifyBox::showXml("TransferObjectsHighlighted",
- callbackHighlightTransferable,
- userdata);
+ LLNotifications::instance().add("TransferObjectsHighlighted",
+ LLSD(), LLSD(),
+ &LLFloaterSellLandUI::callbackHighlightTransferable);
}
// static
-void LLFloaterSellLandUI::callbackHighlightTransferable(S32 option, void* userdata)
+bool LLFloaterSellLandUI::callbackHighlightTransferable(const LLSD& notification, const LLSD& data)
{
LLSelectMgr::getInstance()->unhighlightAll();
+ return false;
}
// static
@@ -462,83 +463,89 @@ void LLFloaterSellLandUI::doSellLand(void *userdata)
LLParcel* parcel = self->mParcelSelection->getParcel();
// Do a confirmation
- if (!parcel->getForSale())
+ S32 sale_price = self->childGetValue("price");
+ S32 area = parcel->getArea();
+ std::string authorizedBuyerName = "Anyone";
+ bool sell_to_anyone = true;
+ if ("user" == self->childGetValue("sell_to").asString())
{
- S32 sale_price = self->childGetValue("price");
- S32 area = parcel->getArea();
- std::string authorizedBuyerName = "Anyone";
- bool sell_to_anyone = true;
- if ("user" == self->childGetValue("sell_to").asString())
- {
- authorizedBuyerName = self->childGetText("sell_to_agent");
- sell_to_anyone = false;
- }
+ authorizedBuyerName = self->childGetText("sell_to_agent");
+ sell_to_anyone = false;
+ }
- // must sell to someone if indicating sale to anyone
- if ((sale_price == 0) && sell_to_anyone)
- {
- gViewerWindow->alertXml("SalePriceRestriction");
- return;
- }
+ // must sell to someone if indicating sale to anyone
+ if (!parcel->getForSale()
+ && (sale_price == 0)
+ && sell_to_anyone)
+ {
+ LLNotifications::instance().add("SalePriceRestriction");
+ return;
+ }
- LLStringUtil::format_map_t args;
- args["[LAND_SIZE]"] = llformat("%d",area);
- args["[SALE_PRICE]"] = llformat("%d",sale_price);
- args["[NAME]"] = authorizedBuyerName;
+ LLSD args;
+ args["LAND_SIZE"] = llformat("%d",area);
+ args["SALE_PRICE"] = llformat("%d",sale_price);
+ args["NAME"] = authorizedBuyerName;
- if (sell_to_anyone)
- {
- gViewerWindow->alertXml("ConfirmLandSaleToAnyoneChange", args, onConfirmSale, self);
- }
- else
- {
- gViewerWindow->alertXml("ConfirmLandSaleChange", args, onConfirmSale, self);
- }
+ LLNotification::Params params("ConfirmLandSaleChange");
+ params.substitutions(args)
+ .functor(boost::bind(&LLFloaterSellLandUI::onConfirmSale, self, _1, _2));
+
+ if (sell_to_anyone)
+ {
+ params.name("ConfirmLandSaleToAnyoneChange");
+ }
+
+ if (parcel->getForSale())
+ {
+ // parcel already for sale, so ignore this question
+ LLNotifications::instance().forceResponse(params, -1);
}
else
{
- onConfirmSale(-1, self);
+ // ask away
+ LLNotifications::instance().add(params);
}
+
}
-// static
-void LLFloaterSellLandUI::onConfirmSale(S32 option, void *userdata)
+bool LLFloaterSellLandUI::onConfirmSale(const LLSD& notification, const LLSD& response)
{
+ S32 option = LLNotification::getSelectedOption(notification, response);
if (option != 0)
{
- return;
+ return false;
}
- LLFloaterSellLandUI* self = (LLFloaterSellLandUI*)userdata;
- S32 sale_price = self->childGetValue("price");
+ S32 sale_price = childGetValue("price");
// Valid extracted data
if (sale_price < 0)
{
// TomY TODO: Throw an error
- return;
+ return false;
}
- LLParcel* parcel = self->mParcelSelection->getParcel();
- if (!parcel) return;
+ LLParcel* parcel = mParcelSelection->getParcel();
+ if (!parcel) return false;
// can_agent_modify_parcel deprecated by GROUPS
// if (!can_agent_modify_parcel(parcel))
// {
-// self->close();
+// close();
// return;
// }
parcel->setParcelFlag(PF_FOR_SALE, TRUE);
parcel->setSalePrice(sale_price);
bool sell_with_objects = false;
- if ("yes" == self->childGetValue("sell_objects").asString())
+ if ("yes" == childGetValue("sell_objects").asString())
{
sell_with_objects = true;
}
parcel->setSellWithObjects(sell_with_objects);
- if ("user" == self->childGetValue("sell_to").asString())
+ if ("user" == childGetValue("sell_to").asString())
{
- parcel->setAuthorizedBuyerID(self->mAuthorizedBuyer);
+ parcel->setAuthorizedBuyerID(mAuthorizedBuyer);
}
else
{
@@ -548,5 +555,6 @@ void LLFloaterSellLandUI::onConfirmSale(S32 option, void *userdata)
// Send update to server
LLViewerParcelMgr::getInstance()->sendParcelPropertiesUpdate( parcel );
- self->close();
+ close();
+ return false;
}
diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index dcfb1e9442..207b2ea655 100644
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -966,7 +966,7 @@ void LLSnapshotLivePreview::saveTexture()
}
else
{
- gViewerWindow->alertXml("ErrorEncodingSnapshot");
+ LLNotifications::instance().add("ErrorEncodingSnapshot");
llwarns << "Error encoding snapshot" << llendl;
}
diff --git a/indra/newview/llfloatertopobjects.cpp b/indra/newview/llfloatertopobjects.cpp
index eea6b40cba..3b79f58db7 100644
--- a/indra/newview/llfloatertopobjects.cpp
+++ b/indra/newview/llfloatertopobjects.cpp
@@ -353,17 +353,19 @@ void LLFloaterTopObjects::doToObjects(int action, bool all)
}
//static
-void LLFloaterTopObjects::callbackReturnAll(S32 option, void* userdata)
+bool LLFloaterTopObjects::callbackReturnAll(const LLSD& notification, const LLSD& response)
{
+ S32 option = LLNotification::getSelectedOption(notification, response);
if (option == 0)
{
sInstance->doToObjects(ACTION_RETURN, true);
}
+ return false;
}
void LLFloaterTopObjects::onReturnAll(void* data)
{
- gViewerWindow->alertXml("ReturnAllTopObjects", callbackReturnAll, NULL);
+ LLNotifications::instance().add("ReturnAllTopObjects", LLSD(), LLSD(), &callbackReturnAll);
}
@@ -374,17 +376,19 @@ void LLFloaterTopObjects::onReturnSelected(void* data)
//static
-void LLFloaterTopObjects::callbackDisableAll(S32 option, void* userdata)
+bool LLFloaterTopObjects::callbackDisableAll(const LLSD& notification, const LLSD& response)
{
+ S32 option = LLNotification::getSelectedOption(notification, response);
if (option == 0)
{
sInstance->doToObjects(ACTION_DISABLE, true);
}
+ return false;
}
void LLFloaterTopObjects::onDisableAll(void* data)
{
- gViewerWindow->alertXml("DisableAllTopObjects", callbackDisableAll, NULL);
+ LLNotifications::instance().add("DisableAllTopObjects", LLSD(), LLSD(), callbackDisableAll);
}
void LLFloaterTopObjects::onDisableSelected(void* data)
diff --git a/indra/newview/llfloatertopobjects.h b/indra/newview/llfloatertopobjects.h
index 5b23e737d7..a6f07a6a34 100644
--- a/indra/newview/llfloatertopobjects.h
+++ b/indra/newview/llfloatertopobjects.h
@@ -72,8 +72,8 @@ private:
static void onDisableAll(void* data);
static void onDisableSelected(void* data);
- static void callbackReturnAll(S32 option, void* userdata);
- static void callbackDisableAll(S32 option, void* userdata);
+ static bool callbackReturnAll(const LLSD& notification, const LLSD& response);
+ static bool callbackDisableAll(const LLSD& notification, const LLSD& response);
static void onGetByOwnerName(LLUICtrl* ctrl, void* data);
static void onGetByObjectName(LLUICtrl* ctrl, void* data);
diff --git a/indra/newview/llfloatertos.cpp b/indra/newview/llfloatertos.cpp
index ad592f909e..bd09bf9ef6 100644
--- a/indra/newview/llfloatertos.cpp
+++ b/indra/newview/llfloatertos.cpp
@@ -257,7 +257,7 @@ void LLFloaterTOS::onCancel( void* userdata )
{
LLFloaterTOS* self = (LLFloaterTOS*) userdata;
llinfos << "User disagrees with TOS." << llendl;
- gViewerWindow->alertXml("MustAgreeToLogIn", login_alert_done);
+ LLNotifications::instance().add("MustAgreeToLogIn", LLSD(), LLSD(), login_alert_done);
LLStartUp::setStartupState( STATE_LOGIN_SHOW );
self->mLoadCompleteCount = 0; // reset counter for next time we come to TOS
self->close(); // destroys this object
diff --git a/indra/newview/llfloaterurlentry.cpp b/indra/newview/llfloaterurlentry.cpp
index 69916f80ea..3efd6eed61 100644
--- a/indra/newview/llfloaterurlentry.cpp
+++ b/indra/newview/llfloaterurlentry.cpp
@@ -262,32 +262,30 @@ void LLFloaterURLEntry::onBtnCancel( void* userdata )
//-----------------------------------------------------------------------------
void LLFloaterURLEntry::onBtnClear( void* userdata )
{
- gViewerWindow->alertXml( "ConfirmClearMediaUrlList", callback_clear_url_list, userdata );
+ LLNotifications::instance().add( "ConfirmClearMediaUrlList", LLSD(), LLSD(),
+ boost::bind(&LLFloaterURLEntry::callback_clear_url_list, (LLFloaterURLEntry*)userdata, _1, _2) );
}
-void LLFloaterURLEntry::callback_clear_url_list(S32 option, void* userdata)
+bool LLFloaterURLEntry::callback_clear_url_list(const LLSD& notification, const LLSD& response)
{
+ S32 option = LLNotification::getSelectedOption(notification, response);
if ( option == 0 ) // YES
{
- LLFloaterURLEntry *self =(LLFloaterURLEntry *)userdata;
-
- if ( self )
+ // clear saved list
+ LLCtrlListInterface* url_list = childGetListInterface("media_entry");
+ if ( url_list )
{
- // clear saved list
- LLCtrlListInterface* url_list = self->childGetListInterface("media_entry");
- if ( url_list )
- {
- url_list->operateOnAll( LLCtrlListInterface::OP_DELETE );
- }
+ url_list->operateOnAll( LLCtrlListInterface::OP_DELETE );
+ }
- // clear current contents of combo box
- self->mMediaURLEdit->clear();
+ // clear current contents of combo box
+ mMediaURLEdit->clear();
- // clear stored version of list
- LLURLHistory::clear("parcel");
+ // clear stored version of list
+ LLURLHistory::clear("parcel");
- // cleared the list so disable Clear button
- self->childSetEnabled( "clear_btn", false );
- }
+ // cleared the list so disable Clear button
+ childSetEnabled( "clear_btn", false );
}
+ return false;
}
diff --git a/indra/newview/llfloaterurlentry.h b/indra/newview/llfloaterurlentry.h
index 53e77880f5..f85106dffe 100644
--- a/indra/newview/llfloaterurlentry.h
+++ b/indra/newview/llfloaterurlentry.h
@@ -63,7 +63,7 @@ private:
static void onBtnOK(void*);
static void onBtnCancel(void*);
static void onBtnClear(void*);
- static void callback_clear_url_list(S32 option, void* userdata);
+ bool callback_clear_url_list(const LLSD& notification, const LLSD& response);
};
#endif // LL_LLFLOATERURLENTRY_H
diff --git a/indra/newview/llfloaterwater.cpp b/indra/newview/llfloaterwater.cpp
index 4705b2f5ba..1a8beb7a58 100644
--- a/indra/newview/llfloaterwater.cpp
+++ b/indra/newview/llfloaterwater.cpp
@@ -176,15 +176,7 @@ void LLFloaterWater::onClickHelp(void* data)
LLFloaterWater* self = LLFloaterWater::instance();
const std::string* xml_alert = (std::string*)data;
- LLAlertDialog* dialogp = gViewerWindow->alertXml(*xml_alert);
- if (dialogp)
- {
- LLFloater* root_floater = gFloaterView->getParentFloater(self);
- if (root_floater)
- {
- root_floater->addDependentFloater(dialogp);
- }
- }
+ LLNotifications::instance().add(self->contextualNotification(*xml_alert));
}
void LLFloaterWater::initHelpBtn(const std::string& name, const std::string& xml_alert)
@@ -192,11 +184,14 @@ void LLFloaterWater::initHelpBtn(const std::string& name, const std::string& xml
childSetAction(name, onClickHelp, new std::string(xml_alert));
}
-void LLFloaterWater::newPromptCallback(S32 option, const std::string& text, void* userData)
+bool LLFloaterWater::newPromptCallback(const LLSD& notification, const LLSD& response)
{
+ std::string text = response["message"].asString();
+ S32 option = LLNotification::getSelectedOption(notification, response);
+
if(text == "")
{
- return;
+ return false;
}
if(option == 0) {
@@ -224,9 +219,10 @@ void LLFloaterWater::newPromptCallback(S32 option, const std::string& text, void
}
else
{
- gViewerWindow->alertXml("ExistsWaterPresetAlert");
+ LLNotifications::instance().add("ExistsWaterPresetAlert");
}
}
+ return false;
}
void LLFloaterWater::syncMenu()
@@ -596,8 +592,7 @@ void LLFloaterWater::onNormalMapPicked(LLUICtrl* ctrl, void* userData)
void LLFloaterWater::onNewPreset(void* userData)
{
- gViewerWindow->alertXmlEditText("NewWaterPreset", LLStringUtil::format_map_t(),
- NULL, NULL, newPromptCallback, NULL);
+ LLNotifications::instance().add("NewWaterPreset", LLSD(), LLSD(), newPromptCallback);
}
void LLFloaterWater::onSavePreset(void* userData)
@@ -619,15 +614,16 @@ void LLFloaterWater::onSavePreset(void* userData)
comboBox->getSelectedItemLabel());
if(sIt != sDefaultPresets.end() && !gSavedSettings.getBOOL("WaterEditPresets"))
{
- gViewerWindow->alertXml("WLNoEditDefault");
+ LLNotifications::instance().add("WLNoEditDefault");
return;
}
- gViewerWindow->alertXml("WLSavePresetAlert", saveAlertCallback, sWaterMenu);
+ LLNotifications::instance().add("WLSavePresetAlert", LLSD(), LLSD(), saveAlertCallback);
}
-void LLFloaterWater::saveAlertCallback(S32 option, void* userdata)
+bool LLFloaterWater::saveAlertCallback(const LLSD& notification, const LLSD& response)
{
+ S32 option = LLNotification::getSelectedOption(notification, response);
// if they choose save, do it. Otherwise, don't do anything
if(option == 0)
{
@@ -640,7 +636,7 @@ void LLFloaterWater::saveAlertCallback(S32 option, void* userdata)
// comment this back in to save to file
param_mgr->savePreset(param_mgr->mCurParams.mName);
}
-
+ return false;
}
void LLFloaterWater::onDeletePreset(void* userData)
@@ -652,13 +648,14 @@ void LLFloaterWater::onDeletePreset(void* userData)
return;
}
- LLStringUtil::format_map_t args;
- args["[SKY]"] = combo_box->getSelectedValue().asString();
- gViewerWindow->alertXml("WLDeletePresetAlert", args, deleteAlertCallback, sWaterMenu);
+ LLSD args;
+ args["SKY"] = combo_box->getSelectedValue().asString();
+ LLNotifications::instance().add("WLDeletePresetAlert", args, LLSD(), deleteAlertCallback);
}
-void LLFloaterWater::deleteAlertCallback(S32 option, void* userdata)
+bool LLFloaterWater::deleteAlertCallback(const LLSD& notification, const LLSD& response)
{
+ S32 option = LLNotification::getSelectedOption(notification, response);
// if they choose delete, do it. Otherwise, don't do anything
if(option == 0)
{
@@ -680,8 +677,8 @@ void LLFloaterWater::deleteAlertCallback(S32 option, void* userdata)
std::set<std::string>::iterator sIt = sDefaultPresets.find(name);
if(sIt != sDefaultPresets.end())
{
- gViewerWindow->alertXml("WaterNoEditDefault");
- return;
+ LLNotifications::instance().add("WaterNoEditDefault");
+ return false;
}
LLWaterParamManager::instance()->removeParamSet(name, true);
@@ -710,6 +707,7 @@ void LLFloaterWater::deleteAlertCallback(S32 option, void* userdata)
combo_box->setCurrentByIndex(new_index);
}
}
+ return false;
}
diff --git a/indra/newview/llfloaterwater.h b/indra/newview/llfloaterwater.h
index 883b2a35f1..ad361266fe 100644
--- a/indra/newview/llfloaterwater.h
+++ b/indra/newview/llfloaterwater.h
@@ -63,7 +63,7 @@ public:
static void onClickHelp(void* data);
void initHelpBtn(const std::string& name, const std::string& xml_alert);
- static void newPromptCallback(S32 option, const std::string& text, void* userData);
+ static bool newPromptCallback(const LLSD& notification, const LLSD& response);
/// general purpose callbacks for dealing with color controllers
static void onColorControlRMoved(LLUICtrl* ctrl, void* userData);
@@ -97,13 +97,13 @@ public:
static void onSavePreset(void* userData);
/// prompts a user when overwriting a preset
- static void saveAlertCallback(S32 option, void* userdata);
+ static bool saveAlertCallback(const LLSD& notification, const LLSD& response);
/// when user hits the save preset button
static void onDeletePreset(void* userData);
/// prompts a user when overwriting a preset
- static void deleteAlertCallback(S32 option, void* userdata);
+ static bool deleteAlertCallback(const LLSD& notification, const LLSD& response);
/// what to do when you change the preset name
static void onChangePresetName(LLUICtrl* ctrl, void* userData);
diff --git a/indra/newview/llfloaterwindlight.cpp b/indra/newview/llfloaterwindlight.cpp
index 4e27774029..8ae291f24c 100644
--- a/indra/newview/llfloaterwindlight.cpp
+++ b/indra/newview/llfloaterwindlight.cpp
@@ -233,16 +233,8 @@ void LLFloaterWindLight::onClickHelp(void* data)
{
LLFloaterWindLight* self = LLFloaterWindLight::instance();
- const std::string* xml_alert = (std::string*)data;
- LLAlertDialog* dialogp = gViewerWindow->alertXml(*xml_alert);
- if (dialogp)
- {
- LLFloater* root_floater = gFloaterView->getParentFloater(self);
- if (root_floater)
- {
- root_floater->addDependentFloater(dialogp);
- }
- }
+ const std::string xml_alert = *(std::string*)data;
+ LLNotifications::instance().add(self->contextualNotification(xml_alert));
}
void LLFloaterWindLight::initHelpBtn(const std::string& name, const std::string& xml_alert)
@@ -250,11 +242,14 @@ void LLFloaterWindLight::initHelpBtn(const std::string& name, const std::string&
childSetAction(name, onClickHelp, new std::string(xml_alert));
}
-void LLFloaterWindLight::newPromptCallback(S32 option, const std::string& text, void* userData)
+bool LLFloaterWindLight::newPromptCallback(const LLSD& notification, const LLSD& response)
{
+ std::string text = response["message"].asString();
+ S32 option = LLNotification::getSelectedOption(notification, response);
+
if(text == "")
{
- return;
+ return false;
}
if(option == 0) {
@@ -303,9 +298,10 @@ void LLFloaterWindLight::newPromptCallback(S32 option, const std::string& text,
}
else
{
- gViewerWindow->alertXml("ExistsSkyPresetAlert");
+ LLNotifications::instance().add("ExistsSkyPresetAlert");
}
}
+ return false;
}
void LLFloaterWindLight::syncMenu()
@@ -784,8 +780,7 @@ void LLFloaterWindLight::onStarAlphaMoved(LLUICtrl* ctrl, void* userData)
void LLFloaterWindLight::onNewPreset(void* userData)
{
- gViewerWindow->alertXmlEditText("NewSkyPreset", LLStringUtil::format_map_t(),
- NULL, NULL, newPromptCallback, NULL);
+ LLNotifications::instance().add("NewSkyPreset", LLSD(), LLSD(), newPromptCallback);
}
void LLFloaterWindLight::onSavePreset(void* userData)
@@ -805,18 +800,19 @@ void LLFloaterWindLight::onSavePreset(void* userData)
comboBox->getSelectedItemLabel());
if(sIt != sDefaultPresets.end() && !gSavedSettings.getBOOL("SkyEditPresets"))
{
- gViewerWindow->alertXml("WLNoEditDefault");
+ LLNotifications::instance().add("WLNoEditDefault");
return;
}
LLWLParamManager::instance()->mCurParams.mName =
comboBox->getSelectedItemLabel();
- gViewerWindow->alertXml("WLSavePresetAlert", saveAlertCallback, sWindLight);
+ LLNotifications::instance().add("WLSavePresetAlert", LLSD(), LLSD(), saveAlertCallback);
}
-void LLFloaterWindLight::saveAlertCallback(S32 option, void* userdata)
+bool LLFloaterWindLight::saveAlertCallback(const LLSD& notification, const LLSD& response)
{
+ S32 option = LLNotification::getSelectedOption(notification, response);
// if they choose save, do it. Otherwise, don't do anything
if(option == 0)
{
@@ -827,7 +823,7 @@ void LLFloaterWindLight::saveAlertCallback(S32 option, void* userdata)
// comment this back in to save to file
param_mgr->savePreset(param_mgr->mCurParams.mName);
}
-
+ return false;
}
void LLFloaterWindLight::onDeletePreset(void* userData)
@@ -840,17 +836,20 @@ void LLFloaterWindLight::onDeletePreset(void* userData)
return;
}
- LLStringUtil::format_map_t args;
- args["[SKY]"] = combo_box->getSelectedValue().asString();
- gViewerWindow->alertXml("WLDeletePresetAlert", args, deleteAlertCallback, sWindLight);
+ LLSD args;
+ args["SKY"] = combo_box->getSelectedValue().asString();
+ LLNotifications::instance().add("WLDeletePresetAlert", args, LLSD(),
+ boost::bind(&LLFloaterWindLight::deleteAlertCallback, sWindLight, _1, _2));
}
-void LLFloaterWindLight::deleteAlertCallback(S32 option, void* userdata)
+bool LLFloaterWindLight::deleteAlertCallback(const LLSD& notification, const LLSD& response)
{
+ S32 option = LLNotification::getSelectedOption(notification, response);
+
// if they choose delete, do it. Otherwise, don't do anything
if(option == 0)
{
- LLComboBox* combo_box = sWindLight->getChild<LLComboBox>(
+ LLComboBox* combo_box = getChild<LLComboBox>(
"WLPresetsCombo");
LLFloaterDayCycle* day_cycle = NULL;
LLComboBox* key_combo = NULL;
@@ -870,8 +869,8 @@ void LLFloaterWindLight::deleteAlertCallback(S32 option, void* userdata)
std::set<std::string>::iterator sIt = sDefaultPresets.find(name);
if(sIt != sDefaultPresets.end())
{
- gViewerWindow->alertXml("WLNoEditDefault");
- return;
+ LLNotifications::instance().add("WLNoEditDefault");
+ return false;
}
LLWLParamManager::instance()->removeParamSet(name, true);
@@ -899,6 +898,7 @@ void LLFloaterWindLight::deleteAlertCallback(S32 option, void* userdata)
combo_box->setCurrentByIndex(new_index);
}
}
+ return false;
}
diff --git a/indra/newview/llfloaterwindlight.h b/indra/newview/llfloaterwindlight.h
index d9e02b1117..35f8a65cbd 100644
--- a/indra/newview/llfloaterwindlight.h
+++ b/indra/newview/llfloaterwindlight.h
@@ -63,7 +63,7 @@ public:
static void onClickHelp(void* data);
void initHelpBtn(const std::string& name, const std::string& xml_alert);
- static void newPromptCallback(S32 option, const std::string& text, void* userData);
+ static bool newPromptCallback(const LLSD& notification, const LLSD& response);
/// general purpose callbacks for dealing with color controllers
static void onColorControlRMoved(LLUICtrl* ctrl, void* userData);
@@ -94,13 +94,13 @@ public:
static void onSavePreset(void* userData);
/// prompts a user when overwriting a preset
- static void saveAlertCallback(S32 option, void* userdata);
+ static bool saveAlertCallback(const LLSD& notification, const LLSD& response);
/// when user hits the save preset button
static void onDeletePreset(void* userData);
/// prompts a user when overwriting a preset
- static void deleteAlertCallback(S32 option, void* userdata);
+ bool deleteAlertCallback(const LLSD& notification, const LLSD& response);
/// what to do when you change the preset name
static void onChangePresetName(LLUICtrl* ctrl, void* userData);
diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp
index 2281f1b598..1c6eb84a8a 100644
--- a/indra/newview/llfloaterworldmap.cpp
+++ b/indra/newview/llfloaterworldmap.cpp
@@ -1303,10 +1303,10 @@ void LLFloaterWorldMap::onCopySLURL(void* data)
LLFloaterWorldMap* self = (LLFloaterWorldMap*)data;
gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(self->mSLURL));
- LLStringUtil::format_map_t args;
- args["[SLURL]"] = self->mSLURL;
+ LLSD args;
+ args["SLURL"] = self->mSLURL;
- LLAlertDialog::showXml("CopySLURL", args);
+ LLNotifications::instance().add("CopySLURL", args);
}
void LLFloaterWorldMap::onCheckEvents(LLUICtrl*, void* data)
diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp
index a25b1daebf..eba295531a 100644
--- a/indra/newview/llgesturemgr.cpp
+++ b/indra/newview/llgesturemgr.cpp
@@ -952,9 +952,9 @@ void LLGestureManager::onLoadComplete(LLVFS *vfs,
&& gGestureManager.mDeactivateSimilarNames.length() > 0)
{
// we're done with this set of deactivations
- LLStringUtil::format_map_t args;
- args["[NAMES]"] = gGestureManager.mDeactivateSimilarNames;
- LLNotifyBox::showXml("DeactivatedGesturesTrigger", args);
+ LLSD args;
+ args["NAMES"] = gGestureManager.mDeactivateSimilarNames;
+ LLNotifications::instance().add("DeactivatedGesturesTrigger", args);
}
}
diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp
index 631b2caa91..9a8e70242c 100644
--- a/indra/newview/llgroupmgr.cpp
+++ b/indra/newview/llgroupmgr.cpp
@@ -1288,9 +1288,9 @@ void LLGroupMgr::processCreateGroupReply(LLMessageSystem* msg, void ** data)
else
{
// *TODO:translate
- LLStringUtil::format_map_t args;
- args["[MESSAGE]"] = message;
- gViewerWindow->alertXml("UnableToCreateGroup", args);
+ LLSD args;
+ args["MESSAGE"] = message;
+ LLNotifications::instance().add("UnableToCreateGroup", args);
}
}
diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp
index 770c117798..98b0786200 100644
--- a/indra/newview/llimpanel.cpp
+++ b/indra/newview/llimpanel.cpp
@@ -306,13 +306,13 @@ void LLVoiceCallCapResponder::error(U32 status, const std::string& reason)
if ( 403 == status )
{
//403 == no ability
- LLNotifyBox::showXml(
+ LLNotifications::instance().add(
"VoiceNotAllowed",
channelp->getNotifyArgs());
}
else
{
- LLNotifyBox::showXml(
+ LLNotifications::instance().add(
"VoiceCallGenericError",
channelp->getNotifyArgs());
}
@@ -348,7 +348,7 @@ LLVoiceChannel::LLVoiceChannel(const LLUUID& session_id, const std::string& sess
mSessionName(session_name),
mIgnoreNextSessionLeave(FALSE)
{
- mNotifyArgs["[VOICE_CHANNEL_NAME]"] = mSessionName;
+ mNotifyArgs["VOICE_CHANNEL_NAME"] = mSessionName;
if (!sVoiceChannelMap.insert(std::make_pair(session_id, this)).second)
{
@@ -384,13 +384,13 @@ void LLVoiceChannel::setChannelInfo(
{
if (mURI.empty())
{
- LLNotifyBox::showXml("VoiceChannelJoinFailed", mNotifyArgs);
+ LLNotifications::instance().add("VoiceChannelJoinFailed", mNotifyArgs);
llwarns << "Received empty URI for channel " << mSessionName << llendl;
deactivate();
}
else if (mCredentials.empty())
{
- LLNotifyBox::showXml("VoiceChannelJoinFailed", mNotifyArgs);
+ LLNotifications::instance().add("VoiceChannelJoinFailed", mNotifyArgs);
llwarns << "Received empty credentials for channel " << mSessionName << llendl;
deactivate();
}
@@ -433,25 +433,26 @@ void LLVoiceChannel::handleStatusChange(EStatusType type)
switch(type)
{
case STATUS_LOGIN_RETRY:
- mLoginNotificationHandle = LLNotifyBox::showXml("VoiceLoginRetry")->getHandle();
+ //mLoginNotificationHandle = LLNotifyBox::showXml("VoiceLoginRetry")->getHandle();
+ LLNotifications::instance().add("VoiceLoginRetry");
break;
case STATUS_LOGGED_IN:
- if (!mLoginNotificationHandle.isDead())
- {
- LLNotifyBox* notifyp = (LLNotifyBox*)mLoginNotificationHandle.get();
- if (notifyp)
- {
- notifyp->close();
- }
- mLoginNotificationHandle.markDead();
- }
+ //if (!mLoginNotificationHandle.isDead())
+ //{
+ // LLNotifyBox* notifyp = (LLNotifyBox*)mLoginNotificationHandle.get();
+ // if (notifyp)
+ // {
+ // notifyp->close();
+ // }
+ // mLoginNotificationHandle.markDead();
+ //}
break;
case STATUS_LEFT_CHANNEL:
if (callStarted() && !mIgnoreNextSessionLeave && !sSuspended)
{
// if forceably removed from channel
// update the UI and revert to default channel
- LLNotifyBox::showXml("VoiceChannelDisconnected", mNotifyArgs);
+ LLNotifications::instance().add("VoiceChannelDisconnected", mNotifyArgs);
deactivate();
}
mIgnoreNextSessionLeave = FALSE;
@@ -793,9 +794,9 @@ void LLVoiceChannelGroup::handleError(EStatusType status)
// notification
if (!notify.empty())
{
- LLNotifyBox::showXml(notify, mNotifyArgs);
+ LLNotificationPtr notification = LLNotifications::instance().add(notify, mNotifyArgs);
// echo to im window
- gIMMgr->addMessage(mSessionID, LLUUID::null, SYSTEM_FROM, LLNotifyBox::getTemplateMessage(notify, mNotifyArgs));
+ gIMMgr->addMessage(mSessionID, LLUUID::null, SYSTEM_FROM, notification->getMessage());
}
LLVoiceChannel::handleError(status);
@@ -896,7 +897,7 @@ void LLVoiceChannelProximal::handleError(EStatusType status)
// notification
if (!notify.empty())
{
- LLNotifyBox::showXml(notify, mNotifyArgs);
+ LLNotifications::instance().add(notify, mNotifyArgs);
}
LLVoiceChannel::handleError(status);
@@ -934,12 +935,12 @@ void LLVoiceChannelP2P::handleStatusChange(EStatusType type)
if (mState == STATE_RINGING)
{
// other user declined call
- LLNotifyBox::showXml("P2PCallDeclined", mNotifyArgs);
+ LLNotifications::instance().add("P2PCallDeclined", mNotifyArgs);
}
else
{
// other user hung up
- LLNotifyBox::showXml("VoiceChannelDisconnectedP2P", mNotifyArgs);
+ LLNotifications::instance().add("VoiceChannelDisconnectedP2P", mNotifyArgs);
}
deactivate();
}
@@ -957,7 +958,7 @@ void LLVoiceChannelP2P::handleError(EStatusType type)
switch(type)
{
case ERROR_NOT_AVAILABLE:
- LLNotifyBox::showXml("P2PCallNoAnswer", mNotifyArgs);
+ LLNotifications::instance().add("P2PCallNoAnswer", mNotifyArgs);
break;
default:
break;
@@ -2213,35 +2214,33 @@ void LLFloaterIMPanel::showSessionStartError(
//their own XML file which would be read in by any LLIMPanel
//post build function instead of repeating the same info
//in the group, adhoc and normal IM xml files.
- LLStringUtil::format_map_t args;
- args["[REASON]"] =
+ LLSD args;
+ args["REASON"] =
LLFloaterIM::sErrorStringsMap[error_string];
- args["[RECIPIENT]"] = getTitle();
+ args["RECIPIENT"] = getTitle();
+
+ LLSD payload;
+ payload["session_id"] = mSessionUUID;
- gViewerWindow->alertXml(
+ LLNotifications::instance().add(
"ChatterBoxSessionStartError",
args,
- onConfirmForceCloseError,
- new LLUUID(mSessionUUID));
+ payload,
+ onConfirmForceCloseError);
}
void LLFloaterIMPanel::showSessionEventError(
const std::string& event_string,
const std::string& error_string)
{
- LLStringUtil::format_map_t args;
- std::string event;
-
- event = LLFloaterIM::sEventStringsMap[event_string];
- args["[RECIPIENT]"] = getTitle();
- LLStringUtil::format(event, args);
-
-
- args = LLStringUtil::format_map_t();
- args["[REASON]"] = LLFloaterIM::sErrorStringsMap[error_string];
- args["[EVENT]"] = event;
+ LLSD args;
+ args["REASON"] =
+ LLFloaterIM::sErrorStringsMap[error_string];
+ args["EVENT"] =
+ LLFloaterIM::sEventStringsMap[event_string];
+ args["RECIPIENT"] = getTitle();
- gViewerWindow->alertXml(
+ LLNotifications::instance().add(
"ChatterBoxSessionEventError",
args);
}
@@ -2249,16 +2248,19 @@ void LLFloaterIMPanel::showSessionEventError(
void LLFloaterIMPanel::showSessionForceClose(
const std::string& reason_string)
{
- LLStringUtil::format_map_t args;
+ LLSD args;
- args["[NAME]"] = getTitle();
- args["[REASON]"] = LLFloaterIM::sForceCloseSessionMap[reason_string];
+ args["NAME"] = getTitle();
+ args["REASON"] = LLFloaterIM::sForceCloseSessionMap[reason_string];
- gViewerWindow->alertXml(
+ LLSD payload;
+ payload["session_id"] = mSessionUUID;
+
+ LLNotifications::instance().add(
"ForceCloseChatterBoxSession",
args,
- LLFloaterIMPanel::onConfirmForceCloseError,
- new LLUUID(mSessionUUID));
+ payload,
+ LLFloaterIMPanel::onConfirmForceCloseError);
}
@@ -2268,10 +2270,10 @@ void LLFloaterIMPanel::onKickSpeaker(void* user_data)
}
-void LLFloaterIMPanel::onConfirmForceCloseError(S32 option, void* data)
+bool LLFloaterIMPanel::onConfirmForceCloseError(const LLSD& notification, const LLSD& response)
{
//only 1 option really
- LLUUID session_id = *((LLUUID*) data);
+ LLUUID session_id = notification["payload"]["session_id"];
if ( gIMMgr )
{
@@ -2280,6 +2282,7 @@ void LLFloaterIMPanel::onConfirmForceCloseError(S32 option, void* data)
if ( floaterp ) floaterp->close(FALSE);
}
+ return false;
}
diff --git a/indra/newview/llimpanel.h b/indra/newview/llimpanel.h
index b20dcd02bd..4681c5684b 100644
--- a/indra/newview/llimpanel.h
+++ b/indra/newview/llimpanel.h
@@ -81,7 +81,7 @@ public:
EState getState() { return mState; }
void updateSessionID(const LLUUID& new_session_id);
- const LLStringUtil::format_map_t& getNotifyArgs() { return mNotifyArgs; }
+ const LLSD& getNotifyArgs() { return mNotifyArgs; }
static LLVoiceChannel* getChannelByID(const LLUUID& session_id);
static LLVoiceChannel* getChannelByURI(std::string uri);
@@ -100,7 +100,7 @@ protected:
LLUUID mSessionID;
EState mState;
std::string mSessionName;
- LLStringUtil::format_map_t mNotifyArgs;
+ LLSD mNotifyArgs;
BOOL mIgnoreNextSessionLeave;
LLHandle<LLPanel> mLoginNotificationHandle;
@@ -266,7 +266,7 @@ public:
const std::string& error_string);
void showSessionForceClose(const std::string& reason);
- static void onConfirmForceCloseError(S32 option, void* data);
+ static bool onConfirmForceCloseError(const LLSD& notification, const LLSD& response);
private:
// called by constructors
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index c33de4c457..552854e7fa 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -97,6 +97,96 @@ std::map<std::string,std::string> LLFloaterIM::sForceCloseSessionMap;
// return (LLStringUtil::compareDict( a->mName, b->mName ) < 0);
//}
+class LLViewerChatterBoxInvitationAcceptResponder :
+ public LLHTTPClient::Responder
+{
+public:
+ LLViewerChatterBoxInvitationAcceptResponder(
+ const LLUUID& session_id,
+ LLIMMgr::EInvitationType invitation_type)
+ {
+ mSessionID = session_id;
+ mInvitiationType = invitation_type;
+ }
+
+ void result(const LLSD& content)
+ {
+ if ( gIMMgr)
+ {
+ LLFloaterIMPanel* floaterp =
+ gIMMgr->findFloaterBySession(mSessionID);
+
+ if (floaterp)
+ {
+ //we've accepted our invitation
+ //and received a list of agents that were
+ //currently in the session when the reply was sent
+ //to us. Now, it is possible that there were some agents
+ //to slip in/out between when that message was sent to us
+ //and now.
+
+ //the agent list updates we've received have been
+ //accurate from the time we were added to the session
+ //but unfortunately, our base that we are receiving here
+ //may not be the most up to date. It was accurate at
+ //some point in time though.
+ floaterp->setSpeakers(content);
+
+ //we now have our base of users in the session
+ //that was accurate at some point, but maybe not now
+ //so now we apply all of the udpates we've received
+ //in case of race conditions
+ floaterp->updateSpeakersList(
+ gIMMgr->getPendingAgentListUpdates(mSessionID));
+
+ if ( mInvitiationType == LLIMMgr::INVITATION_TYPE_VOICE )
+ {
+ floaterp->requestAutoConnect();
+ LLFloaterIMPanel::onClickStartCall(floaterp);
+ // always open IM window when connecting to voice
+ LLFloaterChatterBox::showInstance(TRUE);
+ }
+ else if ( mInvitiationType == LLIMMgr::INVITATION_TYPE_IMMEDIATE )
+ {
+ LLFloaterChatterBox::showInstance(TRUE);
+ }
+ }
+
+ gIMMgr->clearPendingAgentListUpdates(mSessionID);
+ gIMMgr->clearPendingInvitation(mSessionID);
+ }
+ }
+
+ void error(U32 statusNum, const std::string& reason)
+ {
+ //throw something back to the viewer here?
+ if ( gIMMgr )
+ {
+ gIMMgr->clearPendingAgentListUpdates(mSessionID);
+ gIMMgr->clearPendingInvitation(mSessionID);
+
+ LLFloaterIMPanel* floaterp =
+ gIMMgr->findFloaterBySession(mSessionID);
+
+ if ( floaterp )
+ {
+ if ( 404 == statusNum )
+ {
+ std::string error_string;
+ error_string = "does not exist";
+
+ floaterp->showSessionStartError(
+ error_string);
+ }
+ }
+ }
+ }
+
+private:
+ LLUUID mSessionID;
+ LLIMMgr::EInvitationType mInvitiationType;
+};
+
// the other_participant_id is either an agent_id, a group_id, or an inventory
// folder item_id (collection of calling cards)
@@ -256,38 +346,104 @@ protected:
};
-class LLIMMgr::LLIMSessionInvite
+bool inviteUserResponse(const LLSD& notification, const LLSD& response)
{
-public:
- LLIMSessionInvite(
- const LLUUID& session_id,
- const std::string& session_name,
- const LLUUID& caller_id,
- const std::string& caller_name,
- EInstantMessage type,
- EInvitationType inv_type,
- const std::string& session_handle,
- const std::string& notify_box) :
- mSessionID(session_id),
- mSessionName(session_name),
- mCallerID(caller_id),
- mCallerName(caller_name),
- mType(type),
- mInvType(inv_type),
- mSessionHandle(session_handle),
- mNotifyBox(notify_box)
- {};
-
- LLUUID mSessionID;
- std::string mSessionName;
- LLUUID mCallerID;
- std::string mCallerName;
- EInstantMessage mType;
- EInvitationType mInvType;
- std::string mSessionHandle;
- std::string mNotifyBox;
-};
+ const LLSD& payload = notification["payload"];
+ LLUUID session_id = payload["session_id"].asUUID();
+ EInstantMessage type = (EInstantMessage)payload["type"].asInteger();
+ LLIMMgr::EInvitationType inv_type = (LLIMMgr::EInvitationType)payload["inv_type"].asInteger();
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ switch(option)
+ {
+ case 0: // accept
+ {
+ if (type == IM_SESSION_P2P_INVITE)
+ {
+ // create a normal IM session
+ session_id = gIMMgr->addP2PSession(
+ payload["session_name"].asString(),
+ payload["caller_id"].asUUID(),
+ payload["session_handle"].asString());
+
+ LLFloaterIMPanel* im_floater =
+ gIMMgr->findFloaterBySession(
+ session_id);
+ if (im_floater)
+ {
+ im_floater->requestAutoConnect();
+ LLFloaterIMPanel::onClickStartCall(im_floater);
+ // always open IM window when connecting to voice
+ LLFloaterChatterBox::showInstance(session_id);
+ }
+
+ gIMMgr->clearPendingAgentListUpdates(session_id);
+ gIMMgr->clearPendingInvitation(session_id);
+ }
+ else
+ {
+ gIMMgr->addSession(
+ payload["session_name"].asString(),
+ type,
+ session_id);
+
+ std::string url = gAgent.getRegion()->getCapability(
+ "ChatSessionRequest");
+
+ LLSD data;
+ data["method"] = "accept invitation";
+ data["session-id"] = session_id;
+ LLHTTPClient::post(
+ url,
+ data,
+ new LLViewerChatterBoxInvitationAcceptResponder(
+ session_id,
+ inv_type));
+ }
+ }
+ break;
+ case 2: // mute (also implies ignore, so this falls through to the "ignore" case below)
+ {
+ // mute the sender of this invite
+ if (!LLMuteList::getInstance()->isMuted(payload["caller_id"].asUUID()))
+ {
+ LLMute mute(payload["caller_id"].asUUID(), payload["caller_name"].asString(), LLMute::AGENT);
+ LLMuteList::getInstance()->add(mute);
+ }
+ }
+ /* FALLTHROUGH */
+
+ case 1: // decline
+ {
+ if (type == IM_SESSION_P2P_INVITE)
+ {
+ if(gVoiceClient)
+ {
+ std::string s = payload["session_handle"].asString();
+ gVoiceClient->declineInvite(s);
+ }
+ }
+ else
+ {
+ std::string url = gAgent.getRegion()->getCapability(
+ "ChatSessionRequest");
+
+ LLSD data;
+ data["method"] = "decline invitation";
+ data["session-id"] = session_id;
+ LLHTTPClient::post(
+ url,
+ data,
+ NULL);
+ }
+ }
+ gIMMgr->clearPendingAgentListUpdates(session_id);
+ gIMMgr->clearPendingInvitation(session_id);
+ break;
+ }
+
+ return false;
+}
//
// Public Static Member Functions
@@ -510,7 +666,7 @@ void LLIMMgr::addMessage(
}
}
-void LLIMMgr::addSystemMessage(const LLUUID& session_id, const std::string& message_name, const LLStringUtil::format_map_t& args)
+void LLIMMgr::addSystemMessage(const LLUUID& session_id, const std::string& message_name, const LLSD& args)
{
LLUIString message;
@@ -520,7 +676,7 @@ void LLIMMgr::addSystemMessage(const LLUUID& session_id, const std::string& mess
LLFloaterChat* floaterp = LLFloaterChat::getInstance();
message = floaterp->getString(message_name);
- message.setArgList(args);
+ message.setArgs(args);
LLChat chat(message);
chat.mSourceType = CHAT_SOURCE_SYSTEM;
@@ -532,7 +688,7 @@ void LLIMMgr::addSystemMessage(const LLUUID& session_id, const std::string& mess
if (floaterp)
{
message = floaterp->getString(message_name);
- message.setArgList(args);
+ message.setArgs(args);
gIMMgr->addMessage(session_id, LLUUID::null, SYSTEM_FROM, message.getString());
}
@@ -687,7 +843,7 @@ void LLIMMgr::removeSession(const LLUUID& session_id)
LLFloaterChatterBox::getInstance(LLSD())->removeFloater(floater);
//mTabContainer->removeTabPanel(floater);
- clearPendingInviation(session_id);
+ clearPendingInvitation(session_id);
clearPendingAgentListUpdates(session_id);
}
}
@@ -733,21 +889,21 @@ void LLIMMgr::inviteToSession(
ad_hoc_invite = TRUE;
}
- LLIMSessionInvite* invite = new LLIMSessionInvite(
- session_id,
- session_name,
- caller_id,
- caller_name,
- type,
- inv_type,
- session_handle,
- notify_box_type);
+ LLSD payload;
+ payload["session_id"] = session_id;
+ payload["session_name"] = session_name;
+ payload["caller_id"] = caller_id;
+ payload["caller_name"] = caller_name;
+ payload["type"] = type;
+ payload["inv_type"] = inv_type;
+ payload["session_handle"] = session_handle;
+ payload["notify_box_type"] = notify_box_type;
LLVoiceChannel* channelp = LLVoiceChannel::getChannelByID(session_id);
if (channelp && channelp->callStarted())
{
// you have already started a call to the other user, so just accept the invite
- inviteUserResponse(0, invite); // inviteUserResponse deletes
+ LLNotifications::instance().forceResponse(LLNotification::Params("VoiceInviteP2P").payload(payload), 0);
return;
}
@@ -761,7 +917,7 @@ void LLIMMgr::inviteToSession(
if (gSavedSettings.getBOOL("VoiceCallsFriendsOnly"))
{
// invite not from a friend, so decline
- inviteUserResponse(1, invite); // inviteUserResponse deletes
+ LLNotifications::instance().forceResponse(LLNotification::Params("VoiceInviteP2P").payload(payload), 1);
return;
}
}
@@ -771,230 +927,41 @@ void LLIMMgr::inviteToSession(
{
if (caller_name.empty())
{
- gCacheName->get(caller_id, FALSE, onInviteNameLookup, invite);
+ gCacheName->getName(caller_id, onInviteNameLookup, new LLSD(payload));
}
else
{
- LLStringUtil::format_map_t args;
- args["[NAME]"] = caller_name;
- args["[GROUP]"] = session_name;
+ LLSD args;
+ args["NAME"] = caller_name;
+ args["GROUP"] = session_name;
- LLNotifyBox::showXml(notify_box_type,
+ LLNotifications::instance().add(notify_box_type,
args,
- inviteUserResponse,
- (void*)invite); // inviteUserResponse deletes
+ payload,
+ &inviteUserResponse);
}
mPendingInvitations[session_id.asString()] = LLSD();
}
- else
- {
- delete invite;
- }
}
//static
void LLIMMgr::onInviteNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* userdata)
{
- LLIMSessionInvite* invite = (LLIMSessionInvite*)userdata;
+ LLSD payload = *(LLSD*)userdata;
+ delete (LLSD*)userdata;
- invite->mCallerName = first + " " + last;
- invite->mSessionName = invite->mCallerName;
+ payload["caller_name"] = first + " " + last;
+ payload["session_name"] = payload["caller_name"].asString();
- LLStringUtil::format_map_t args;
- args["[NAME]"] = invite->mCallerName;
+ LLSD args;
+ args["NAME"] = payload["caller_name"].asString();
- LLNotifyBox::showXml(
- invite->mNotifyBox,
+ LLNotifications::instance().add(
+ payload["notify_box_type"].asString(),
args,
- inviteUserResponse,
- (void*)invite);
-}
-
-class LLViewerChatterBoxInvitationAcceptResponder :
- public LLHTTPClient::Responder
-{
-public:
- LLViewerChatterBoxInvitationAcceptResponder(
- const LLUUID& session_id,
- LLIMMgr::EInvitationType invitation_type)
- {
- mSessionID = session_id;
- mInvitiationType = invitation_type;
- }
-
- void result(const LLSD& content)
- {
- if ( gIMMgr)
- {
- LLFloaterIMPanel* floaterp =
- gIMMgr->findFloaterBySession(mSessionID);
-
- if (floaterp)
- {
- //we've accepted our invitation
- //and received a list of agents that were
- //currently in the session when the reply was sent
- //to us. Now, it is possible that there were some agents
- //to slip in/out between when that message was sent to us
- //and now.
-
- //the agent list updates we've received have been
- //accurate from the time we were added to the session
- //but unfortunately, our base that we are receiving here
- //may not be the most up to date. It was accurate at
- //some point in time though.
- floaterp->setSpeakers(content);
-
- //we now have our base of users in the session
- //that was accurate at some point, but maybe not now
- //so now we apply all of the udpates we've received
- //in case of race conditions
- floaterp->updateSpeakersList(
- gIMMgr->getPendingAgentListUpdates(mSessionID));
-
- if ( mInvitiationType == LLIMMgr::INVITATION_TYPE_VOICE )
- {
- floaterp->requestAutoConnect();
- LLFloaterIMPanel::onClickStartCall(floaterp);
- // always open IM window when connecting to voice
- LLFloaterChatterBox::showInstance(TRUE);
- }
- else if ( mInvitiationType == LLIMMgr::INVITATION_TYPE_IMMEDIATE )
- {
- LLFloaterChatterBox::showInstance(TRUE);
- }
- }
-
- gIMMgr->clearPendingAgentListUpdates(mSessionID);
- gIMMgr->clearPendingInviation(mSessionID);
- }
- }
-
- void error(U32 statusNum, const std::string& reason)
- {
- //throw something back to the viewer here?
- if ( gIMMgr )
- {
- gIMMgr->clearPendingAgentListUpdates(mSessionID);
- gIMMgr->clearPendingInviation(mSessionID);
-
- LLFloaterIMPanel* floaterp =
- gIMMgr->findFloaterBySession(mSessionID);
-
- if ( floaterp )
- {
- if ( 404 == statusNum )
- {
- std::string error_string;
- error_string = "does not exist";
-
- floaterp->showSessionStartError(
- error_string);
- }
- }
- }
- }
-
-private:
- LLUUID mSessionID;
- LLIMMgr::EInvitationType mInvitiationType;
-};
-
-//static
-void LLIMMgr::inviteUserResponse(S32 option, void* user_data)
-{
- LLIMSessionInvite* invitep = (LLIMSessionInvite*)user_data;
-
- switch(option)
- {
- case 0: // accept
- {
- if (invitep->mType == IM_SESSION_P2P_INVITE)
- {
- // create a normal IM session
- invitep->mSessionID = gIMMgr->addP2PSession(
- invitep->mSessionName,
- invitep->mCallerID,
- invitep->mSessionHandle);
-
- LLFloaterIMPanel* im_floater =
- gIMMgr->findFloaterBySession(
- invitep->mSessionID);
- if (im_floater)
- {
- im_floater->requestAutoConnect();
- LLFloaterIMPanel::onClickStartCall(im_floater);
- // always open IM window when connecting to voice
- LLFloaterChatterBox::showInstance(invitep->mSessionID);
- }
-
- gIMMgr->clearPendingAgentListUpdates(invitep->mSessionID);
- gIMMgr->clearPendingInviation(invitep->mSessionID);
- }
- else
- {
- gIMMgr->addSession(
- invitep->mSessionName,
- invitep->mType,
- invitep->mSessionID);
-
- std::string url = gAgent.getRegion()->getCapability(
- "ChatSessionRequest");
-
- LLSD data;
- data["method"] = "accept invitation";
- data["session-id"] = invitep->mSessionID;
- LLHTTPClient::post(
- url,
- data,
- new LLViewerChatterBoxInvitationAcceptResponder(
- invitep->mSessionID,
- invitep->mInvType));
- }
- }
- break;
- case 2: // mute (also implies ignore, so this falls through to the "ignore" case below)
- {
- // mute the sender of this invite
- if (!LLMuteList::getInstance()->isMuted(invitep->mCallerID))
- {
- LLMute mute(invitep->mCallerID, invitep->mCallerName, LLMute::AGENT);
- LLMuteList::getInstance()->add(mute);
- }
- }
- /* FALLTHROUGH */
-
- case 1: // decline
- {
- if (invitep->mType == IM_SESSION_P2P_INVITE)
- {
- if(gVoiceClient)
- {
- gVoiceClient->declineInvite(invitep->mSessionHandle);
- }
- }
- else
- {
- std::string url = gAgent.getRegion()->getCapability(
- "ChatSessionRequest");
-
- LLSD data;
- data["method"] = "decline invitation";
- data["session-id"] = invitep->mSessionID;
- LLHTTPClient::post(
- url,
- data,
- NULL);
- }
- }
-
- gIMMgr->clearPendingAgentListUpdates(invitep->mSessionID);
- gIMMgr->clearPendingInviation(invitep->mSessionID);
- break;
- }
-
- delete invitep;
+ payload,
+ &inviteUserResponse);
}
void LLIMMgr::refresh()
@@ -1068,7 +1035,7 @@ BOOL LLIMMgr::hasSession(const LLUUID& session_id)
return (findFloaterBySession(session_id) != NULL);
}
-void LLIMMgr::clearPendingInviation(const LLUUID& session_id)
+void LLIMMgr::clearPendingInvitation(const LLUUID& session_id)
{
if ( mPendingInvitations.has(session_id.asString()) )
{
diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h
index da64cd3bab..175f47ebc1 100644
--- a/indra/newview/llimview.h
+++ b/indra/newview/llimview.h
@@ -68,7 +68,7 @@ public:
const LLVector3& position = LLVector3::zero,
bool link_name = false);
- void addSystemMessage(const LLUUID& session_id, const std::string& message_name, const LLStringUtil::format_map_t& args);
+ void addSystemMessage(const LLUUID& session_id, const std::string& message_name, const LLSD& args);
// This method returns TRUE if the local viewer has a session
// currently open keyed to the uuid. The uuid can be keyed by
@@ -157,7 +157,7 @@ public:
static LLUUID computeSessionID(EInstantMessage dialog, const LLUUID& other_participant_id);
- void clearPendingInviation(const LLUUID& session_id);
+ void clearPendingInvitation(const LLUUID& session_id);
LLSD getPendingAgentListUpdates(const LLUUID& session_id);
void addPendingAgentListUpdates(
@@ -169,8 +169,6 @@ public:
const std::set<LLHandle<LLFloater> >& getIMFloaterHandles() { return mFloaters; }
private:
- class LLIMSessionInvite;
-
// create a panel and update internal representation for
// consistency. Returns the pointer, caller (the class instance
// since it is a private method) is not responsible for deleting
@@ -197,7 +195,6 @@ private:
void processIMTypingCore(const LLIMInfo* im_info, BOOL typing);
- static void inviteUserResponse(S32 option, void* user_data);
static void onInviteNameLookup(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* userdata);
private:
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index a4b80ed7c1..3852755850 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -109,8 +109,8 @@ void wear_inventory_category_on_avatar_loop(LLWearable* wearable, void*);
void wear_inventory_category_on_avatar_step3(LLWearableHoldingPattern* holder, BOOL append);
void remove_inventory_category_from_avatar(LLInventoryCategory* category);
void remove_inventory_category_from_avatar_step2( BOOL proceed, void* userdata);
-void move_task_inventory_callback(S32 option, void* user_data);
-void confirm_replace_attachment_rez(S32 option, void* user_data);
+bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv*);
+bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& response);
std::string ICON_NAME[ICON_NAME_COUNT] =
{
@@ -1288,7 +1288,7 @@ void warn_move_inventory(LLViewerObject* object, LLMoveInv* move_inv)
{
dialog = "MoveInventoryFromObject";
}
- gViewerWindow->alertXml(dialog, move_task_inventory_callback, move_inv);
+ LLNotifications::instance().add(dialog, LLSD(), LLSD(), boost::bind(move_task_inventory_callback, _1, _2, move_inv));
}
// Move/copy all inventory items from the Contents folder of an in-world
@@ -1377,7 +1377,9 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
}
else
{
- move_task_inventory_callback(0, (void*)(move_inv));
+ LLNotification::Params params("MoveInventoryFromObject");
+ params.functor(boost::bind(move_task_inventory_callback, _1, _2, move_inv));
+ LLNotifications::instance().forceResponse(params, 0);
}
}
return accept;
@@ -2187,12 +2189,12 @@ void LLFolderBridge::modifyOutfit(BOOL append)
}
// helper stuff
-void move_task_inventory_callback(S32 option, void* user_data)
+bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv* move_inv)
{
- LLMoveInv* move_inv = (LLMoveInv*)user_data;
LLFloaterOpenObject::LLCatAndWear* cat_and_wear = (LLFloaterOpenObject::LLCatAndWear* )move_inv->mUserData;
LLViewerObject* object = gObjectList.findObject(move_inv->mObjectID);
-
+ S32 option = LLNotification::getSelectedOption(notification, response);
+
if(option == 0 && object)
{
if (cat_and_wear && cat_and_wear->mWear)
@@ -2223,6 +2225,7 @@ void move_task_inventory_callback(S32 option, void* user_data)
}
delete move_inv;
+ return false;
}
BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
@@ -2353,7 +2356,9 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
}
else
{
- move_task_inventory_callback(0, (void*)(move_inv));
+ LLNotification::Params params("MoveInventoryFromObject");
+ params.functor(boost::bind(move_task_inventory_callback, _1, _2, move_inv));
+ LLNotifications::instance().forceResponse(params, 0);
}
}
@@ -2648,23 +2653,28 @@ void open_landmark(LLViewerInventoryItem* inv_item,
}
}
-static void open_landmark_callback(S32 option, void* data)
+static bool open_landmark_callback(const LLSD& notification, const LLSD& response)
{
- LLUUID* asset_idp = (LLUUID*)data;
+ S32 option = LLNotification::getSelectedOption(notification, response);
+
+ LLUUID asset_id = notification["payload"]["asset_id"].asUUID();
if (option == 0)
{
// HACK: This is to demonstrate teleport on double click for landmarks
- gAgent.teleportViaLandmark( *asset_idp );
+ gAgent.teleportViaLandmark( asset_id );
// we now automatically track the landmark you're teleporting to
// because you'll probably arrive at a telehub instead
if( gFloaterWorldMap )
{
- gFloaterWorldMap->trackLandmark( *asset_idp );
+ gFloaterWorldMap->trackLandmark( asset_id );
}
}
- delete asset_idp;
+
+ return false;
}
+static LLNotificationFunctorRegistration open_landmark_callback_reg("TeleportFromLandmark", open_landmark_callback);
+
void LLLandmarkBridge::openItem()
{
@@ -2674,9 +2684,9 @@ void LLLandmarkBridge::openItem()
// Opening (double-clicking) a landmark immediately teleports,
// but warns you the first time.
// open_landmark(item, std::string(" ") + getPrefix() + item->getName(), FALSE);
- LLUUID* asset_idp = new LLUUID(item->getAssetUUID());
- LLAlertDialog::showXml("TeleportFromLandmark",
- open_landmark_callback, (void*)asset_idp);
+ LLSD payload;
+ payload["asset_id"] = item->getAssetUUID();
+ LLNotifications::instance().add("TeleportFromLandmark", LLSD(), payload);
}
}
@@ -3321,8 +3331,9 @@ std::string LLObjectBridge::getLabelSuffix() const
void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attachment)
{
- LLAttachmentRezAction* rez_action = new LLAttachmentRezAction;
- rez_action->mItemID = item->getUUID();
+ LLSD payload;
+ payload["item_id"] = item->getUUID();
+
S32 attach_pt = 0;
if (gAgent.getAvatarObject() && attachment)
{
@@ -3336,46 +3347,46 @@ void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attach
}
}
}
- rez_action->mAttachPt = attach_pt;
+
+ payload["attachment_point"] = attach_pt;
+
if (attachment && attachment->getObject())
{
- gViewerWindow->alertXml("ReplaceAttachment", confirm_replace_attachment_rez, (void*)rez_action);
+ LLNotifications::instance().add("ReplaceAttachment", LLSD(), payload, confirm_replace_attachment_rez);
}
else
{
- confirm_replace_attachment_rez(0/*YES*/, (void*)rez_action);
+ LLNotifications::instance().forceResponse(LLNotification::Params("ReplaceAttachment").payload(payload), 0/*YES*/);
}
}
-void confirm_replace_attachment_rez(S32 option, void* user_data)
+bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& response)
{
- LLAttachmentRezAction* rez_action = (LLAttachmentRezAction*)user_data;
+ S32 option = LLNotification::getSelectedOption(notification, response);
if (option == 0/*YES*/)
{
- if (rez_action)
+ LLViewerInventoryItem* itemp = gInventory.getItem(notification["payload"]["item_id"].asUUID());
+
+ if (itemp)
{
- LLViewerInventoryItem* itemp = gInventory.getItem(rez_action->mItemID);
-
- if (itemp)
- {
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessageFast(_PREHASH_RezSingleAttachmentFromInv);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_ObjectData);
- msg->addUUIDFast(_PREHASH_ItemID, itemp->getUUID());
- msg->addUUIDFast(_PREHASH_OwnerID, itemp->getPermissions().getOwner());
- msg->addU8Fast(_PREHASH_AttachmentPt, rez_action->mAttachPt);
- pack_permissions_slam(msg, itemp->getFlags(), itemp->getPermissions());
- msg->addStringFast(_PREHASH_Name, itemp->getName());
- msg->addStringFast(_PREHASH_Description, itemp->getDescription());
- msg->sendReliable(gAgent.getRegion()->getHost());
- }
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_RezSingleAttachmentFromInv);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_ObjectData);
+ msg->addUUIDFast(_PREHASH_ItemID, itemp->getUUID());
+ msg->addUUIDFast(_PREHASH_OwnerID, itemp->getPermissions().getOwner());
+ msg->addU8Fast(_PREHASH_AttachmentPt, notification["payload"]["attachment_point"].asInteger());
+ pack_permissions_slam(msg, itemp->getFlags(), itemp->getPermissions());
+ msg->addStringFast(_PREHASH_Name, itemp->getName());
+ msg->addStringFast(_PREHASH_Description, itemp->getDescription());
+ msg->sendReliable(gAgent.getRegion()->getHost());
}
}
- delete rez_action;
+ return false;
}
+static LLNotificationFunctorRegistration confirm_replace_attachment_rez_reg("ReplaceAttachment", confirm_replace_attachment_rez);
void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
@@ -3927,7 +3938,7 @@ void wear_inventory_category_on_avatar_step2( BOOL proceed, void* userdata )
if( !wearable_count && !obj_count && !gest_count)
{
- gViewerWindow->alertXml("CouldNotPutOnOutfit");
+ LLNotifications::instance().add("CouldNotPutOnOutfit");
delete wear_info;
return;
}
@@ -4334,7 +4345,7 @@ void LLWearableBridge::openItem()
{
if( isInTrash() )
{
- gViewerWindow->alertXml("CannotWearTrash");
+ LLNotifications::instance().add("CannotWearTrash");
}
else if(isAgentInventory())
{
@@ -4363,7 +4374,7 @@ void LLWearableBridge::openItem()
{
// *TODO: We should fetch the item details, and then do
// the operation above.
- gViewerWindow->alertXml("CannotWearInfoNotComplete");
+ LLNotifications::instance().add("CannotWearInfoNotComplete");
}
}
}
@@ -4464,7 +4475,7 @@ void LLWearableBridge::wearOnAvatar()
// destroy clothing items.
if (!gAgent.areWearablesLoaded())
{
- gViewerWindow->alertXml("CanNotChangeAppearanceUntilLoaded");
+ LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded");
return;
}
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index 064ace52f2..c0cda4c6a4 100644
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -92,7 +92,6 @@ class LLViewerInventoryItem;
class LLViewerInventoryCategory;
class LLMessageSystem;
class LLInventoryCollectFunctor;
-class LLAlertDialog;
class LLInventoryModel
{
diff --git a/indra/newview/lllandmarklist.cpp b/indra/newview/lllandmarklist.cpp
index 59b4d245ac..d98ee1894b 100644
--- a/indra/newview/lllandmarklist.cpp
+++ b/indra/newview/lllandmarklist.cpp
@@ -119,11 +119,11 @@ void LLLandmarkList::processGetAssetReply(
if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status )
{
- LLNotifyBox::showXml("LandmarkMissing");
+ LLNotifications::instance().add("LandmarkMissing");
}
else
{
- LLNotifyBox::showXml("UnableToLoadLandmark");
+ LLNotifications::instance().add("UnableToLoadLandmark");
}
gLandmarkList.mBadList.insert(uuid);
diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp
index 3ad26b703a..cc9be04cfc 100644
--- a/indra/newview/llmutelist.cpp
+++ b/indra/newview/llmutelist.cpp
@@ -66,7 +66,8 @@
#include "llfloaterchat.h"
#include "llimpanel.h"
#include "llimview.h"
-#include "llnotify.h"
+#include "lltrans.h"
+#include "llnotifications.h"
#include "lluistring.h"
#include "llviewerobject.h"
#include "llviewerobjectlist.h"
@@ -278,7 +279,7 @@ BOOL LLMuteList::add(const LLMute& mute, U32 flags)
if ((mute.mType == LLMute::AGENT)
&& isLinden(mute.mName) && (flags & LLMute::flagTextChat || flags == 0))
{
- gViewerWindow->alertXml("MuteLinden");
+ LLNotifications::instance().add("MuteLinden");
return FALSE;
}
@@ -480,35 +481,35 @@ void notify_automute_callback(const LLUUID& agent_id, const std::string& first_n
{
U32 temp_data = (U32) (uintptr_t) user_data;
LLMuteList::EAutoReason reason = (LLMuteList::EAutoReason)temp_data;
- LLUIString auto_message;
-
+
+ std::string auto_message;
switch (reason)
{
default:
case LLMuteList::AR_IM:
- auto_message = LLNotifyBox::getTemplateMessage("AutoUnmuteByIM");
+ auto_message = LLTrans::getString("AutoUnmuteByIM");
break;
case LLMuteList::AR_INVENTORY:
- auto_message = LLNotifyBox::getTemplateMessage("AutoUnmuteByInventory");
+ auto_message = LLTrans::getString("AutoUnmuteByInventory");
break;
case LLMuteList::AR_MONEY:
- auto_message = LLNotifyBox::getTemplateMessage("AutoUnmuteByMoney");
+ auto_message = LLTrans::getString("AutoUnmuteByMoney");
break;
}
- auto_message.setArg("[FIRST]", first_name);
- auto_message.setArg("[LAST]", last_name);
+ std::string message = LLNotification::format(auto_message,
+ LLSD().insert("FIRST", first_name).insert("LAST", last_name));
if (reason == LLMuteList::AR_IM)
{
LLFloaterIMPanel *timp = gIMMgr->findFloaterBySession(agent_id);
if (timp)
{
- timp->addHistoryLine(auto_message.getString());
+ timp->addHistoryLine(message);
}
}
- LLChat auto_chat(auto_message.getString());
+ LLChat auto_chat(message);
LLFloaterChat::addChat(auto_chat, FALSE, FALSE);
}
diff --git a/indra/newview/llnamelistctrl.cpp b/indra/newview/llnamelistctrl.cpp
index dfc327e329..5b4e956137 100644
--- a/indra/newview/llnamelistctrl.cpp
+++ b/indra/newview/llnamelistctrl.cpp
@@ -349,7 +349,7 @@ LLView* LLNameListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFacto
LLSD columns;
S32 index = 0;
- S32 total_static = 0;
+ //S32 total_static = 0;
LLXMLNodePtr child;
for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling())
{
@@ -383,7 +383,7 @@ LLView* LLNameListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFacto
LLFontGL::HAlign h_align = LLFontGL::LEFT;
h_align = LLView::selectFontHAlign(child);
- if(!columndynamicwidth) total_static += llmax(0, columnwidth);
+ //if(!columndynamicwidth) total_static += llmax(0, columnwidth);
columns[index]["name"] = columnname;
columns[index]["label"] = labelname;
@@ -394,7 +394,6 @@ LLView* LLNameListCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFacto
index++;
}
}
- name_list->setTotalStaticColumnWidth(total_static);
name_list->setColumnHeadings(columns);
diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp
index 9c8817da9a..3f4732692f 100644
--- a/indra/newview/llpanelavatar.cpp
+++ b/indra/newview/llpanelavatar.cpp
@@ -352,20 +352,24 @@ void LLPanelAvatarSecondLife::onDoubleClickGroup(void* data)
// static
void LLPanelAvatarSecondLife::onClickPublishHelp(void *)
{
- gViewerWindow->alertXml("ClickPublishHelpAvatar");
+ LLNotifications::instance().add("ClickPublishHelpAvatar");
}
// static
void LLPanelAvatarSecondLife::onClickPartnerHelp(void *)
{
- gViewerWindow->alertXml("ClickPartnerHelpAvatar", onClickPartnerHelpLoadURL, (void*) NULL);
+ LLNotifications::instance().add("ClickPartnerHelpAvatar", LLSD(), LLSD(), onClickPartnerHelpLoadURL);
}
// static
-void LLPanelAvatarSecondLife::onClickPartnerHelpLoadURL(S32 option, void* userdata)
+bool LLPanelAvatarSecondLife::onClickPartnerHelpLoadURL(const LLSD& notification, const LLSD& response)
{
- if (option == 0)
- LLWeb::loadURL("http://secondlife.com/partner");
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ if (option == 0)
+ {
+ LLWeb::loadURL("http://secondlife.com/partner");
+ }
+ return false;
}
// static
@@ -593,7 +597,7 @@ void LLPanelAvatarWeb::onCommitURL(LLUICtrl* ctrl, void* data)
// static
void LLPanelAvatarWeb::onClickWebProfileHelp(void *)
{
- gViewerWindow->alertXml("ClickWebProfileHelpAvatar");
+ LLNotifications::instance().add("ClickWebProfileHelpAvatar");
}
void LLPanelAvatarWeb::load(std::string url)
@@ -930,26 +934,25 @@ void LLPanelAvatarClassified::onClickNew(void* data)
{
LLPanelAvatarClassified* self = (LLPanelAvatarClassified*)data;
- gViewerWindow->alertXml("AddClassified",callbackNew,self);
+ LLNotifications::instance().add("AddClassified", LLSD(), LLSD(), boost::bind(&LLPanelAvatarClassified::callbackNew, self, _1, _2));
}
-// static
-void LLPanelAvatarClassified::callbackNew(S32 option, void* data)
+bool LLPanelAvatarClassified::callbackNew(const LLSD& notification, const LLSD& response)
{
- LLPanelAvatarClassified* self = (LLPanelAvatarClassified*)data;
-
+ S32 option = LLNotification::getSelectedOption(notification, response);
if (0 == option)
{
LLPanelClassified* panel_classified = new LLPanelClassified(false, false);
panel_classified->initNewClassified();
- LLTabContainer* tabs = self->getChild<LLTabContainer>("classified tab");
+ LLTabContainer* tabs = getChild<LLTabContainer>("classified tab");
if(tabs)
{
tabs->addTabPanel(panel_classified, panel_classified->getClassifiedName());
tabs->selectLastTab();
}
}
+ return false;
}
@@ -966,18 +969,17 @@ void LLPanelAvatarClassified::onClickDelete(void* data)
}
if (!panel_classified) return;
- LLStringUtil::format_map_t args;
- args["[NAME]"] = panel_classified->getClassifiedName();
- gViewerWindow->alertXml("DeleteClassified", args, callbackDelete, self);
+ LLSD args;
+ args["NAME"] = panel_classified->getClassifiedName();
+ LLNotifications::instance().add("DeleteClassified", args, LLSD(), boost::bind(&LLPanelAvatarClassified::callbackDelete, self, _1, _2));
}
-// static
-void LLPanelAvatarClassified::callbackDelete(S32 option, void* data)
+bool LLPanelAvatarClassified::callbackDelete(const LLSD& notification, const LLSD& response)
{
- LLPanelAvatarClassified* self = (LLPanelAvatarClassified*)data;
- LLTabContainer* tabs = self->getChild<LLTabContainer>("classified tab");
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ LLTabContainer* tabs = getChild<LLTabContainer>("classified tab");
LLPanelClassified* panel_classified=NULL;
if(tabs)
{
@@ -986,7 +988,7 @@ void LLPanelAvatarClassified::callbackDelete(S32 option, void* data)
LLMessageSystem* msg = gMessageSystem;
- if (!panel_classified) return;
+ if (!panel_classified) return false;
if (0 == option)
{
@@ -1005,6 +1007,7 @@ void LLPanelAvatarClassified::callbackDelete(S32 option, void* data)
delete panel_classified;
panel_classified = NULL;
}
+ return false;
}
@@ -1124,24 +1127,23 @@ void LLPanelAvatarPicks::onClickDelete(void* data)
if (!panel_pick) return;
- LLStringUtil::format_map_t args;
- args["[PICK]"] = panel_pick->getPickName();
+ LLSD args;
+ args["PICK"] = panel_pick->getPickName();
- gViewerWindow->alertXml("DeleteAvatarPick", args,
- callbackDelete,
- self);
+ LLNotifications::instance().add("DeleteAvatarPick", args, LLSD(),
+ boost::bind(&LLPanelAvatarPicks::callbackDelete, self, _1, _2));
}
// static
-void LLPanelAvatarPicks::callbackDelete(S32 option, void* data)
+bool LLPanelAvatarPicks::callbackDelete(const LLSD& notification, const LLSD& response)
{
- LLPanelAvatarPicks* self = (LLPanelAvatarPicks*)data;
- LLTabContainer* tabs = self->getChild<LLTabContainer>("picks tab");
- LLPanelPick* panel_pick = tabs?(LLPanelPick*)tabs->getCurrentPanel():NULL;
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ LLTabContainer* tabs = getChild<LLTabContainer>("picks tab");
+ LLPanelPick* panel_pick = tabs ? (LLPanelPick*)tabs->getCurrentPanel() : NULL;
LLMessageSystem* msg = gMessageSystem;
- if (!panel_pick) return;
+ if (!panel_pick) return false;
if (0 == option)
{
@@ -1177,6 +1179,7 @@ void LLPanelAvatarPicks::callbackDelete(S32 option, void* data)
delete panel_pick;
panel_pick = NULL;
}
+ return false;
}
@@ -1835,7 +1838,7 @@ void LLPanelAvatar::processAvatarPropertiesReply(LLMessageSystem *msg, void**)
args["[PAYMENTINFO]"] = self->mPanelSecondLife->getString(payment_text);
std::string age_text = age_verified ? "AgeVerified" : "NotAgeVerified";
// Do not display age verification status at this time
- //args["[AGEVERIFICATION]"] = self->mPanelSecondLife->getString(age_text);
+ //args["[[AGEVERIFICATION]]"] = self->mPanelSecondLife->getString(age_text);
args["[AGEVERIFICATION]"] = " ";
}
else
@@ -2187,85 +2190,93 @@ void LLPanelAvatar::onClickKick(void* userdata)
gFloaterView->getNewFloaterPosition(&left, &top);
LLRect rect(left, top, left+400, top-300);
- gViewerWindow->alertXmlEditText("KickUser", LLStringUtil::format_map_t(),
- NULL, NULL,
- LLPanelAvatar::finishKick, self);
+ LLSD payload;
+ payload["avatar_id"] = self->mAvatarID;
+ LLNotifications::instance().add("KickUser", LLSD(), payload, finishKick);
}
-// static
-void LLPanelAvatar::finishKick(S32 option, const std::string& text, void* userdata)
+//static
+bool LLPanelAvatar::finishKick(const LLSD& notification, const LLSD& response)
{
- LLPanelAvatar* self = (LLPanelAvatar*) userdata;
+ S32 option = LLNotification::getSelectedOption(notification, response);
if (option == 0)
{
+ LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID();
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_GodKickUser);
msg->nextBlockFast(_PREHASH_UserInfo);
msg->addUUIDFast(_PREHASH_GodID, gAgent.getID() );
msg->addUUIDFast(_PREHASH_GodSessionID, gAgent.getSessionID());
- msg->addUUIDFast(_PREHASH_AgentID, self->mAvatarID );
+ msg->addUUIDFast(_PREHASH_AgentID, avatar_id );
msg->addU32("KickFlags", KICK_FLAGS_DEFAULT );
- msg->addStringFast(_PREHASH_Reason, text );
+ msg->addStringFast(_PREHASH_Reason, response["message"].asString() );
gAgent.sendReliableMessage();
}
+ return false;
}
// static
void LLPanelAvatar::onClickFreeze(void* userdata)
{
- gViewerWindow->alertXmlEditText("FreezeUser", LLStringUtil::format_map_t(),
- NULL, NULL,
- LLPanelAvatar::finishFreeze, userdata);
+ LLPanelAvatar* self = (LLPanelAvatar*) userdata;
+ LLSD payload;
+ payload["avatar_id"] = self->mAvatarID;
+ LLNotifications::instance().add("FreezeUser", LLSD(), payload, LLPanelAvatar::finishFreeze);
}
// static
-void LLPanelAvatar::finishFreeze(S32 option, const std::string& text, void* userdata)
+bool LLPanelAvatar::finishFreeze(const LLSD& notification, const LLSD& response)
{
- LLPanelAvatar* self = (LLPanelAvatar*) userdata;
+ S32 option = LLNotification::getSelectedOption(notification, response);
if (option == 0)
{
+ LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID();
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_GodKickUser);
msg->nextBlockFast(_PREHASH_UserInfo);
msg->addUUIDFast(_PREHASH_GodID, gAgent.getID() );
msg->addUUIDFast(_PREHASH_GodSessionID, gAgent.getSessionID());
- msg->addUUIDFast(_PREHASH_AgentID, self->mAvatarID );
+ msg->addUUIDFast(_PREHASH_AgentID, avatar_id );
msg->addU32("KickFlags", KICK_FLAGS_FREEZE );
- msg->addStringFast(_PREHASH_Reason, text );
+ msg->addStringFast(_PREHASH_Reason, response["message"].asString() );
gAgent.sendReliableMessage();
}
+ return false;
}
// static
void LLPanelAvatar::onClickUnfreeze(void* userdata)
{
- gViewerWindow->alertXmlEditText("UnFreezeUser", LLStringUtil::format_map_t(),
- NULL, NULL,
- LLPanelAvatar::finishUnfreeze, userdata);
+ LLPanelAvatar* self = (LLPanelAvatar*) userdata;
+ LLSD payload;
+ payload["avatar_id"] = self->mAvatarID;
+ LLNotifications::instance().add("UnFreezeUser", LLSD(), payload, LLPanelAvatar::finishUnfreeze);
}
// static
-void LLPanelAvatar::finishUnfreeze(S32 option, const std::string& text, void* userdata)
+bool LLPanelAvatar::finishUnfreeze(const LLSD& notification, const LLSD& response)
{
- LLPanelAvatar* self = (LLPanelAvatar*) userdata;
-
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ std::string text = response["message"].asString();
if (option == 0)
{
+ LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID();
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_GodKickUser);
msg->nextBlockFast(_PREHASH_UserInfo);
msg->addUUIDFast(_PREHASH_GodID, gAgent.getID() );
msg->addUUIDFast(_PREHASH_GodSessionID, gAgent.getSessionID());
- msg->addUUIDFast(_PREHASH_AgentID, self->mAvatarID );
+ msg->addUUIDFast(_PREHASH_AgentID, avatar_id );
msg->addU32("KickFlags", KICK_FLAGS_UNFREEZE );
msg->addStringFast(_PREHASH_Reason, text );
gAgent.sendReliableMessage();
}
+ return false;
}
// static
diff --git a/indra/newview/llpanelavatar.h b/indra/newview/llpanelavatar.h
index 833b124389..b7f9c69687 100644
--- a/indra/newview/llpanelavatar.h
+++ b/indra/newview/llpanelavatar.h
@@ -117,7 +117,7 @@ public:
static void onDoubleClickGroup(void* userdata);
static void onClickPublishHelp(void *userdata);
static void onClickPartnerHelp(void *userdata);
- static void onClickPartnerHelpLoadURL(S32 option, void* userdata);
+ static bool onClickPartnerHelpLoadURL(const LLSD& notification, const LLSD& response);
static void onClickPartnerInfo(void *userdata);
// Clear out the controls anticipating new network data.
@@ -231,8 +231,8 @@ private:
static void onClickNew(void* data);
static void onClickDelete(void* data);
- static void callbackDelete(S32 option, void* data);
- static void callbackNew(S32 option, void* data);
+ bool callbackDelete(const LLSD& notification, const LLSD& response);
+ bool callbackNew(const LLSD& notification, const LLSD& response);
};
@@ -257,7 +257,7 @@ private:
static void onClickNew(void* data);
static void onClickDelete(void* data);
- static void callbackDelete(S32 option, void* data);
+ bool callbackDelete(const LLSD& notification, const LLSD& response);
};
@@ -325,9 +325,9 @@ public:
private:
void enableOKIfReady();
- static void finishKick(S32 option, const std::string& text, void* userdata);
- static void finishFreeze(S32 option, const std::string& text, void* userdata);
- static void finishUnfreeze(S32 option, const std::string& text, void* userdata);
+ static bool finishKick(const LLSD& notification, const LLSD& response);
+ static bool finishFreeze(const LLSD& notification, const LLSD& response);
+ static bool finishUnfreeze(const LLSD& notification, const LLSD& response);
static void showProfileCallback(S32 option, void *userdata);
diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp
index 64cc19e2fd..e50f2649af 100644
--- a/indra/newview/llpanelclassified.cpp
+++ b/indra/newview/llpanelclassified.cpp
@@ -317,12 +317,12 @@ BOOL LLPanelClassified::titleIsValid()
const std::string& name = mNameEditor->getText();
if (name.empty())
{
- gViewerWindow->alertXml("BlankClassifiedName");
+ LLNotifications::instance().add("BlankClassifiedName");
return FALSE;
}
if (!isalnum(name[0]))
{
- gViewerWindow->alertXml("ClassifiedMustBeAlphanumeric");
+ LLNotifications::instance().add("ClassifiedMustBeAlphanumeric");
return FALSE;
}
@@ -339,31 +339,24 @@ void LLPanelClassified::apply()
}
}
-
-// static
-void LLPanelClassified::saveCallback(S32 option, void* data)
+bool LLPanelClassified::saveCallback(const LLSD& notification, const LLSD& response)
{
- LLPanelClassified* self = (LLPanelClassified*)data;
+ S32 option = LLNotification::getSelectedOption(notification, response);
+
switch(option)
{
case 0: // Save
- self->sendClassifiedInfoUpdate();
+ sendClassifiedInfoUpdate();
// fall through to close
case 1: // Don't Save
{
- self->mForceClose = true;
+ mForceClose = true;
// Close containing floater
- LLView* view = self;
- while (view)
+ LLFloater* parent_floater = gFloaterView->getParentFloater(this);
+ if (parent_floater)
{
- LLFloater* floaterp = dynamic_cast<LLFloater*>(view);
- if (floaterp)
- {
- floaterp->close();
- break;
- }
- view = view->getParent();
+ parent_floater->close();
}
}
break;
@@ -373,16 +366,18 @@ void LLPanelClassified::saveCallback(S32 option, void* data)
LLAppViewer::instance()->abortQuit();
break;
}
+ return false;
}
+
BOOL LLPanelClassified::canClose()
{
if (mForceClose || !checkDirty())
return TRUE;
- LLStringUtil::format_map_t args;
- args["[NAME]"] = mNameEditor->getText();
- LLAlertDialog::showXml("ClassifiedSave", args, saveCallback, this);
+ LLSD args;
+ args["NAME"] = mNameEditor->getText();
+ LLNotifications::instance().add("ClassifiedSave", args, LLSD(), boost::bind(&LLPanelClassified::saveCallback, this, _1, _2));
return FALSE;
}
@@ -785,8 +780,11 @@ void LLPanelClassified::onClickUpdate(void* data)
// If user has not set mature, do not allow publish
if(self->mMatureCombo->getCurrentIndex() == DECLINE_TO_STATE)
{
- LLStringUtil::format_map_t args;
- gViewerWindow->alertXml("SetClassifiedMature", &callbackConfirmMature, self);
+ // Tell user about it
+ LLNotifications::instance().add("SetClassifiedMature",
+ LLSD(),
+ LLSD(),
+ boost::bind(&LLPanelClassified::confirmMature, self, _1, _2));
return;
}
@@ -794,16 +792,11 @@ void LLPanelClassified::onClickUpdate(void* data)
self->gotMature();
}
-// static
-void LLPanelClassified::callbackConfirmMature(S32 option, void* data)
-{
- LLPanelClassified* self = (LLPanelClassified*)data;
- self->confirmMature(option);
-}
-
-// invoked from callbackConfirmMature
-void LLPanelClassified::confirmMature(S32 option)
+// Callback from a dialog indicating response to mature notification
+bool LLPanelClassified::confirmMature(const LLSD& notification, const LLSD& response)
{
+ S32 option = LLNotification::getSelectedOption(notification, response);
+
// 0 == Yes
// 1 == No
// 2 == Cancel
@@ -816,11 +809,12 @@ void LLPanelClassified::confirmMature(S32 option)
mMatureCombo->setCurrentByIndex(NON_MATURE_CONTENT);
break;
default:
- return;
+ return false;
}
// If we got here it means they set a valid value
gotMature();
+ return false;
}
// Called after we have determined whether this classified has
@@ -830,7 +824,9 @@ void LLPanelClassified::gotMature()
// if already paid for, just do the update
if (mPaidFor)
{
- callbackConfirmPublish(0, this);
+ LLNotification::Params params("PublishClassified");
+ params.functor(boost::bind(&LLPanelClassified::confirmPublish, this, _1, _2));
+ LLNotifications::instance().forceResponse(params, 0);
}
else
{
@@ -850,11 +846,11 @@ void LLPanelClassified::callbackGotPriceForListing(S32 option, std::string text,
S32 price_for_listing = strtol(text.c_str(), NULL, 10);
if (price_for_listing < MINIMUM_PRICE_FOR_LISTING)
{
- LLStringUtil::format_map_t args;
+ LLSD args;
std::string price_text = llformat("%d", MINIMUM_PRICE_FOR_LISTING);
- args["[MIN_PRICE]"] = price_text;
+ args["MIN_PRICE"] = price_text;
- gViewerWindow->alertXml("MinClassifiedPrice", args);
+ LLNotifications::instance().add("MinClassifiedPrice", args);
return;
}
@@ -862,10 +858,10 @@ void LLPanelClassified::callbackGotPriceForListing(S32 option, std::string text,
// update send
self->mPriceForListing = price_for_listing;
- LLStringUtil::format_map_t args;
- args["[AMOUNT]"] = llformat("%d", price_for_listing);
- gViewerWindow->alertXml("PublishClassified", args, &callbackConfirmPublish, self);
-
+ LLSD args;
+ args["AMOUNT"] = llformat("%d", price_for_listing);
+ LLNotifications::instance().add("PublishClassified", args, LLSD(),
+ boost::bind(&LLPanelClassified::confirmPublish, self, _1, _2));
}
void LLPanelClassified::resetDirty()
@@ -889,10 +885,11 @@ void LLPanelClassified::resetDirty()
}
// invoked from callbackConfirmPublish
-void LLPanelClassified::confirmPublish(S32 option)
+bool LLPanelClassified::confirmPublish(const LLSD& notification, const LLSD& response)
{
+ S32 option = LLNotification::getSelectedOption(notification, response);
// Option 0 = publish
- if (option != 0) return;
+ if (option != 0) return false;
sendClassifiedInfoUpdate();
@@ -911,14 +908,9 @@ void LLPanelClassified::confirmPublish(S32 option)
}
resetDirty();
+ return false;
}
-// static
-void LLPanelClassified::callbackConfirmPublish(S32 option, void* data)
-{
- LLPanelClassified* self = (LLPanelClassified*)data;
- self->confirmPublish(option);
-}
// static
void LLPanelClassified::onClickTeleport(void* data)
diff --git a/indra/newview/llpanelclassified.h b/indra/newview/llpanelclassified.h
index ee84d89f43..f808eb9913 100644
--- a/indra/newview/llpanelclassified.h
+++ b/indra/newview/llpanelclassified.h
@@ -100,17 +100,15 @@ public:
static void processClassifiedInfoReply(LLMessageSystem* msg, void**);
// Confirmation dialogs flow in this order
- static void callbackConfirmMature(S32 option, void* data);
- void confirmMature(S32 option);
+ bool confirmMature(const LLSD& notification, const LLSD& response);
void gotMature();
static void callbackGotPriceForListing(S32 option, std::string text, void* data);
- static void callbackConfirmPublish(S32 option, void* data);
- void confirmPublish(S32 option);
+ bool confirmPublish(const LLSD& notification, const LLSD& response);
void sendClassifiedClickMessage(const std::string& type);
protected:
- static void saveCallback(S32 option, void* data);
+ bool saveCallback(const LLSD& notification, const LLSD& response);
static void onClickUpdate(void* data);
static void onClickTeleport(void* data);
diff --git a/indra/newview/llpanelgroup.cpp b/indra/newview/llpanelgroup.cpp
index 2d5f789141..6233740d53 100644
--- a/indra/newview/llpanelgroup.cpp
+++ b/indra/newview/llpanelgroup.cpp
@@ -45,6 +45,7 @@
#include "lluictrlfactory.h"
#include "llviewerwindow.h"
#include "llappviewer.h"
+#include "llnotifications.h"
// static
void* LLPanelGroupTab::createTab(void* data)
@@ -115,17 +116,12 @@ void LLPanelGroupTab::handleClickHelp()
std::string help_text( getHelpText() );
if ( !help_text.empty() )
{
- LLStringUtil::format_map_t args;
- args["[MESSAGE]"] = help_text;
- LLAlertDialog* dialogp = gViewerWindow->alertXml("GenericAlert", args);
- if (dialogp)
- {
- LLFloater* root_floater = gFloaterView->getParentFloater(this);;
- if (root_floater)
- {
- root_floater->addDependentFloater(dialogp);
- }
- }
+ LLSD args;
+ args["MESSAGE"] = help_text;
+ LLFloater* parent_floater = gFloaterView->getParentFloater(this);
+ LLNotification::Params params(parent_floater->contextualNotification("GenericAlert"));
+ params.substitutions(args);
+ LLNotifications::instance().add(params);
}
}
@@ -411,11 +407,11 @@ BOOL LLPanelGroup::attemptTransition()
mesg = mDefaultNeedsApplyMesg;
}
// Create a notify box, telling the user about the unapplied tab.
- LLStringUtil::format_map_t args;
- args["[NEEDS_APPLY_MESSAGE]"] = mesg;
- args["[WANT_APPLY_MESSAGE]"] = mWantApplyMesg;
- gViewerWindow->alertXml("PanelGroupApply", args,
- onNotifyCallback, (void*) this);
+ LLSD args;
+ args["NEEDS_APPLY_MESSAGE"] = mesg;
+ args["WANT_APPLY_MESSAGE"] = mWantApplyMesg;
+ LLNotifications::instance().add("PanelGroupApply", args, LLSD(),
+ boost::bind(&LLPanelGroup::handleNotifyCallback, this, _1, _2));
mShowingNotifyDialog = TRUE;
// We need to reselect the current tab, since it isn't finished.
@@ -465,18 +461,9 @@ void LLPanelGroup::transitionToTab()
}
}
-// static
-void LLPanelGroup::onNotifyCallback(S32 option, void* user_data)
-{
- LLPanelGroup* self = static_cast<LLPanelGroup*>(user_data);
- if (self)
- {
- self->handleNotifyCallback(option);
- }
-}
-
-void LLPanelGroup::handleNotifyCallback(S32 option)
+bool LLPanelGroup::handleNotifyCallback(const LLSD& notification, const LLSD& response)
{
+ S32 option = LLNotification::getSelectedOption(notification, response);
mShowingNotifyDialog = FALSE;
switch (option)
{
@@ -512,6 +499,7 @@ void LLPanelGroup::handleNotifyCallback(S32 option)
LLAppViewer::instance()->abortQuit();
break;
}
+ return false;
}
// static
@@ -568,9 +556,9 @@ bool LLPanelGroup::apply()
// Inform the user.
if ( !apply_mesg.empty() )
{
- LLStringUtil::format_map_t args;
- args["[MESSAGE]"] = apply_mesg;
- gViewerWindow->alertXml("GenericAlert", args);
+ LLSD args;
+ args["MESSAGE"] = apply_mesg;
+ LLNotifications::instance().add("GenericAlert", args);
}
return false;
@@ -638,7 +626,7 @@ void LLPanelGroup::showNotice(const std::string& subject,
// We need to clean up that inventory offer.
if (inventory_offer)
{
- inventory_offer_callback( IOR_DECLINE , inventory_offer);
+ inventory_offer->forceResponse(IOR_DECLINE);
}
return;
}
diff --git a/indra/newview/llpanelgroup.h b/indra/newview/llpanelgroup.h
index f27ef75843..946448a224 100644
--- a/indra/newview/llpanelgroup.h
+++ b/indra/newview/llpanelgroup.h
@@ -87,8 +87,7 @@ public:
void updateTabVisibility();
// Used by attemptTransition to query the user's response to a tab that needs to apply.
- static void onNotifyCallback(S32 option, void* user_data);
- void handleNotifyCallback(S32 option);
+ bool handleNotifyCallback(const LLSD& notification, const LLSD& response);
bool apply();
void refreshData();
diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp
index 044ad280fa..f6f262f2be 100644
--- a/indra/newview/llpanelgroupgeneral.cpp
+++ b/indra/newview/llpanelgroupgeneral.cpp
@@ -344,18 +344,18 @@ void LLPanelGroupGeneral::onClickJoin(void *userdata)
if (gdatap)
{
S32 cost = gdatap->mMembershipFee;
- LLStringUtil::format_map_t args;
- args["[COST]"] = llformat("%d", cost);
-
+ LLSD args;
+ args["COST"] = llformat("%d", cost);
+ LLSD payload;
+ payload["group_id"] = self->mGroupID;
+
if (can_afford_transaction(cost))
{
- gViewerWindow->alertXml("JoinGroupCanAfford", args,
- LLPanelGroupGeneral::joinDlgCB,
- self);
+ LLNotifications::instance().add("JoinGroupCanAfford", args, payload, LLPanelGroupGeneral::joinDlgCB);
}
else
{
- gViewerWindow->alertXml("JoinGroupCannotAfford", args);
+ LLNotifications::instance().add("JoinGroupCannotAfford", args, payload);
}
}
else
@@ -366,17 +366,18 @@ void LLPanelGroupGeneral::onClickJoin(void *userdata)
}
// static
-void LLPanelGroupGeneral::joinDlgCB(S32 which, void *userdata)
+bool LLPanelGroupGeneral::joinDlgCB(const LLSD& notification, const LLSD& response)
{
- LLPanelGroupGeneral* self = (LLPanelGroupGeneral*) userdata;
+ S32 option = LLNotification::getSelectedOption(notification, response);
- if (which == 1 || !self)
+ if (option == 1)
{
// user clicked cancel
- return;
+ return false;
}
- LLGroupMgr::getInstance()->sendGroupMemberJoin(self->mGroupID);
+ LLGroupMgr::getInstance()->sendGroupMemberJoin(notification["payload"]["group_id"].asUUID());
+ return false;
}
// static
@@ -444,9 +445,8 @@ bool LLPanelGroupGeneral::apply(std::string& mesg)
if(mComboMature &&
mComboMature->getCurrentIndex() == DECLINE_TO_STATE)
{
- LLStringUtil::format_map_t args;
- gViewerWindow->alertXml("SetGroupMature", &callbackConfirmMatureApply,
- new LLHandle<LLPanel>(getHandle()));
+ LLNotifications::instance().add("SetGroupMature", LLSD(), LLSD(),
+ boost::bind(&LLPanelGroupGeneral::confirmMatureApply, this, _1, _2));
return false;
}
@@ -464,10 +464,9 @@ bool LLPanelGroupGeneral::apply(std::string& mesg)
return false;
}
- LLStringUtil::format_map_t args;
- args["[MESSAGE]"] = mConfirmGroupCreateStr;
- gViewerWindow->alertXml("GenericAlertYesCancel", args,
- createGroupCallback, new LLHandle<LLPanel>(getHandle()) );
+ LLSD args;
+ args["MESSAGE"] = mConfirmGroupCreateStr;
+ LLNotifications::instance().add("GenericAlertYesCancel", args, LLSD(), boost::bind(&LLPanelGroupGeneral::createGroupCallback, this, _1, _2));
return false;
}
@@ -545,22 +544,10 @@ void LLPanelGroupGeneral::cancel()
notifyObservers();
}
-
-// static
-void LLPanelGroupGeneral::callbackConfirmMatureApply(S32 option, void* data)
-{
- LLHandle<LLPanel>* handlep = (LLHandle<LLPanel>*)data;
- LLPanelGroupGeneral* self = dynamic_cast<LLPanelGroupGeneral*>(handlep->get());
- delete handlep;
- if (self)
- {
- self->confirmMatureApply(option);
- }
-}
-
// invoked from callbackConfirmMature
-void LLPanelGroupGeneral::confirmMatureApply(S32 option)
+bool LLPanelGroupGeneral::confirmMatureApply(const LLSD& notification, const LLSD& response)
{
+ S32 option = LLNotification::getSelectedOption(notification, response);
// 0 == Yes
// 1 == No
// 2 == Cancel
@@ -573,39 +560,35 @@ void LLPanelGroupGeneral::confirmMatureApply(S32 option)
mComboMature->setCurrentByIndex(NON_MATURE_CONTENT);
break;
default:
- return;
+ return false;
}
// If we got here it means they set a valid value
std::string mesg = "";
apply(mesg);
+ return false;
}
// static
-void LLPanelGroupGeneral::createGroupCallback(S32 option, void* userdata)
+bool LLPanelGroupGeneral::createGroupCallback(const LLSD& notification, const LLSD& response)
{
- LLHandle<LLPanel> panel_handle = *(LLHandle<LLPanel>*)userdata;
- delete (LLHandle<LLPanel>*)userdata;
-
- LLPanelGroupGeneral* self = dynamic_cast<LLPanelGroupGeneral*>(panel_handle.get());
- if (!self) return;
-
+ S32 option = LLNotification::getSelectedOption(notification, response);
switch(option)
{
case 0:
{
// Yay! We are making a new group!
- U32 enrollment_fee = (self->mCtrlEnrollmentFee->get() ?
- (U32) self->mSpinEnrollmentFee->get() : 0);
+ U32 enrollment_fee = (mCtrlEnrollmentFee->get() ?
+ (U32) mSpinEnrollmentFee->get() : 0);
- LLGroupMgr::getInstance()->sendCreateGroupRequest(self->mGroupNameEditor->getText(),
- self->mEditCharter->getText(),
- self->mCtrlShowInGroupList->get(),
- self->mInsignia->getImageAssetID(),
+ LLGroupMgr::getInstance()->sendCreateGroupRequest(mGroupNameEditor->getText(),
+ mEditCharter->getText(),
+ mCtrlShowInGroupList->get(),
+ mInsignia->getImageAssetID(),
enrollment_fee,
- self->mCtrlOpenEnrollment->get(),
+ mCtrlOpenEnrollment->get(),
false,
- self->mComboMature->getCurrentIndex() == MATURE_CONTENT);
+ mComboMature->getCurrentIndex() == MATURE_CONTENT);
}
break;
@@ -613,6 +596,7 @@ void LLPanelGroupGeneral::createGroupCallback(S32 option, void* userdata)
default:
break;
}
+ return false;
}
static F32 sSDTime = 0.0f;
diff --git a/indra/newview/llpanelgroupgeneral.h b/indra/newview/llpanelgroupgeneral.h
index 982d0678dd..c38594ef0d 100644
--- a/indra/newview/llpanelgroupgeneral.h
+++ b/indra/newview/llpanelgroupgeneral.h
@@ -57,8 +57,7 @@ public:
virtual bool needsApply(std::string& mesg);
virtual bool apply(std::string& mesg);
virtual void cancel();
- static void createGroupCallback(S32 option, void* user_data);
- static void callbackConfirmMatureApply(S32 option, void* data);
+ bool createGroupCallback(const LLSD& notification, const LLSD& response);
virtual void update(LLGroupChange gc);
@@ -77,11 +76,11 @@ private:
static void onReceiveNotices(LLUICtrl* ctrl, void* data);
static void openProfile(void* data);
- static void joinDlgCB(S32 which, void *userdata);
+ static bool joinDlgCB(const LLSD& notification, const LLSD& response);
void updateMembers();
void updateChanged();
- void confirmMatureApply(S32 option);
+ bool confirmMatureApply(const LLSD& notification, const LLSD& response);
BOOL mPendingMemberUpdate;
BOOL mChanged;
diff --git a/indra/newview/llpanelgroupinvite.cpp b/indra/newview/llpanelgroupinvite.cpp
index c4af61587c..70440dd75a 100644
--- a/indra/newview/llpanelgroupinvite.cpp
+++ b/indra/newview/llpanelgroupinvite.cpp
@@ -66,7 +66,7 @@ public:
static void callbackAddUsers(const std::vector<std::string>& names,
const std::vector<LLUUID>& agent_ids,
void* user_data);
- static void inviteOwnerCallback(S32 option, void* userdata);
+ bool inviteOwnerCallback(const LLSD& notification, const LLSD& response);
public:
LLUUID mGroupID;
@@ -158,9 +158,9 @@ void LLPanelGroupInvite::impl::submitInvitations()
// owner role: display confirmation and wait for callback
if ((role_id == gdatap->mOwnerRole) && (!mConfirmedOwnerInvite))
{
- LLStringUtil::format_map_t args;
- args["[MESSAGE]"] = mOwnerWarning;
- gViewerWindow->alertXml("GenericAlertYesCancel", args, inviteOwnerCallback, this);
+ LLSD args;
+ args["MESSAGE"] = mOwnerWarning;
+ LLNotifications::instance().add("GenericAlertYesCancel", args, LLSD(), boost::bind(&LLPanelGroupInvite::impl::inviteOwnerCallback, this, _1, _2));
return; // we'll be called again if user confirms
}
}
@@ -180,24 +180,23 @@ void LLPanelGroupInvite::impl::submitInvitations()
(*mCloseCallback)(mCloseCallbackUserData);
}
-//static
-void LLPanelGroupInvite::impl::inviteOwnerCallback(S32 option, void* userdata)
+bool LLPanelGroupInvite::impl::inviteOwnerCallback(const LLSD& notification, const LLSD& response)
{
- LLPanelGroupInvite::impl* self = (LLPanelGroupInvite::impl*)userdata;
- if (!self) return;
+ S32 option = LLNotification::getSelectedOption(notification, response);
switch(option)
{
case 0:
// user confirmed that they really want a new group owner
- self->mConfirmedOwnerInvite = true;
- self->submitInvitations();
+ mConfirmedOwnerInvite = true;
+ submitInvitations();
break;
case 1:
// fall through
default:
break;
}
+ return false;
}
@@ -396,16 +395,14 @@ void LLPanelGroupInvite::addUsers(std::vector<LLUUID>& agent_ids)
if(dest && dest->isAvatar())
{
std::string fullname;
- LLStringUtil::format_map_t args;
+ LLSD args;
LLNameValue* nvfirst = dest->getNVPair("FirstName");
LLNameValue* nvlast = dest->getNVPair("LastName");
if(nvfirst && nvlast)
{
- args["[FIRST]"] = nvfirst->getString();
- args["[LAST]"] = nvlast->getString();
- fullname = nvfirst->getString();
- fullname += " ";
- fullname += nvlast->getString();
+ args["FIRST"] = std::string(nvfirst->getString());
+ args["LAST"] = std::string(nvlast->getString());
+ fullname = std::string(nvfirst->getString()) + " " + std::string(nvlast->getString());
}
if (!fullname.empty())
{
diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp
index 18fcc9d291..1b1a7e32a0 100644
--- a/indra/newview/llpanelgroupnotices.cpp
+++ b/indra/newview/llpanelgroupnotices.cpp
@@ -53,6 +53,7 @@
#include "roles_constants.h"
#include "llviewerwindow.h"
#include "llviewermessage.h"
+#include "llnotifications.h"
const S32 NOTICE_DATE_STRING_SIZE = 30;
@@ -195,7 +196,8 @@ LLPanelGroupNotices::~LLPanelGroupNotices()
if (mInventoryOffer)
{
// Cancel the inventory offer.
- inventory_offer_callback( IOR_DECLINE , mInventoryOffer);
+ mInventoryOffer->forceResponse(IOR_DECLINE);
+
mInventoryOffer = NULL;
}
}
@@ -345,7 +347,7 @@ void LLPanelGroupNotices::onClickOpenAttachment(void* data)
{
LLPanelGroupNotices* self = (LLPanelGroupNotices*)data;
- inventory_offer_callback( IOR_ACCEPT , self->mInventoryOffer);
+ self->mInventoryOffer->forceResponse(IOR_ACCEPT);
self->mInventoryOffer = NULL;
self->mBtnOpenAttachment->setEnabled(FALSE);
}
@@ -357,7 +359,7 @@ void LLPanelGroupNotices::onClickSendMessage(void* data)
if (self->mCreateSubject->getText().empty())
{
// Must supply a subject
- gViewerWindow->alertXml("MustSpecifyGroupNoticeSubject");
+ LLNotifications::instance().add("MustSpecifyGroupNoticeSubject");
return;
}
send_group_notice(
@@ -384,7 +386,7 @@ void LLPanelGroupNotices::onClickNewMessage(void* data)
if (self->mInventoryOffer)
{
- inventory_offer_callback( IOR_DECLINE , self->mInventoryOffer);
+ self->mInventoryOffer->forceResponse(IOR_DECLINE);
self->mInventoryOffer = NULL;
}
@@ -535,7 +537,7 @@ void LLPanelGroupNotices::showNotice(const std::string& subject,
if (mInventoryOffer)
{
// Cancel the inventory offer for the previously viewed notice
- inventory_offer_callback( IOR_DECLINE , mInventoryOffer);
+ mInventoryOffer->forceResponse(IOR_DECLINE);
mInventoryOffer = NULL;
}
diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp
index 4b48fb3510..6fb601bf56 100644
--- a/indra/newview/llpanelgrouproles.cpp
+++ b/indra/newview/llpanelgrouproles.cpp
@@ -237,11 +237,11 @@ BOOL LLPanelGroupRoles::attemptTransition()
mesg = mDefaultNeedsApplyMesg;
}
// Create a notify box, telling the user about the unapplied tab.
- LLStringUtil::format_map_t args;
- args["[NEEDS_APPLY_MESSAGE]"] = mesg;
- args["[WANT_APPLY_MESSAGE]"] = mWantApplyMesg;
- gViewerWindow->alertXml("PanelGroupApply", args,
- onNotifyCallback, (void*) this);
+ LLSD args;
+ args["NEEDS_APPLY_MESSAGE"] = mesg;
+ args["WANT_APPLY_MESSAGE"] = mWantApplyMesg;
+ LLNotifications::instance().add("PanelGroupApply", args, LLSD(),
+ boost::bind(&LLPanelGroupRoles::handleNotifyCallback, this, _1, _2));
mHasModal = TRUE;
// We need to reselect the current tab, since it isn't finished.
if (mSubTabContainer)
@@ -282,18 +282,9 @@ void LLPanelGroupRoles::transitionToTab()
}
}
-// static
-void LLPanelGroupRoles::onNotifyCallback(S32 option, void* user_data)
-{
- LLPanelGroupRoles* self = static_cast<LLPanelGroupRoles*>(user_data);
- if (self)
- {
- self->handleNotifyCallback(option);
- }
-}
-
-void LLPanelGroupRoles::handleNotifyCallback(S32 option)
+bool LLPanelGroupRoles::handleNotifyCallback(const LLSD& notification, const LLSD& response)
{
+ S32 option = LLNotification::getSelectedOption(notification, response);
mHasModal = FALSE;
switch (option)
{
@@ -307,9 +298,9 @@ void LLPanelGroupRoles::handleNotifyCallback(S32 option)
if ( !apply_mesg.empty() )
{
mHasModal = TRUE;
- LLStringUtil::format_map_t args;
- args["[MESSAGE]"] = apply_mesg;
- gViewerWindow->alertXml("GenericAlert", args, onModalClose, (void*) this);
+ LLSD args;
+ args["MESSAGE"] = apply_mesg;
+ LLNotifications::instance().add("GenericAlert", args, LLSD(), boost::bind(&LLPanelGroupRoles::onModalClose, this, _1, _2));
}
// Skip switching tabs.
break;
@@ -337,16 +328,13 @@ void LLPanelGroupRoles::handleNotifyCallback(S32 option)
// Do nothing. The user is canceling the action.
break;
}
+ return false;
}
-// static
-void LLPanelGroupRoles::onModalClose(S32 option, void* user_data)
+bool LLPanelGroupRoles::onModalClose(const LLSD& notification, const LLSD& response)
{
- LLPanelGroupRoles* self = static_cast<LLPanelGroupRoles*>(user_data);
- if (self)
- {
- self->mHasModal = FALSE;
- }
+ mHasModal = FALSE;
+ return false;
}
@@ -1375,16 +1363,16 @@ bool LLPanelGroupMembersSubTab::apply(std::string& mesg)
if ( mNumOwnerAdditions > 0 )
{
LLRoleData rd;
- LLStringUtil::format_map_t args;
+ LLSD args;
if ( gdatap->getRoleData(gdatap->mOwnerRole, rd) )
{
mHasModal = TRUE;
- args["[ROLE_NAME]"] = rd.mRoleName;
- gViewerWindow->alertXml("AddGroupOwnerWarning",
+ args["ROLE_NAME"] = rd.mRoleName;
+ LLNotifications::instance().add("AddGroupOwnerWarning",
args,
- addOwnerCB,
- this);
+ LLSD(),
+ boost::bind(&LLPanelGroupMembersSubTab::addOwnerCB, this, _1, _2));
}
else
{
@@ -1404,20 +1392,17 @@ bool LLPanelGroupMembersSubTab::apply(std::string& mesg)
return true;
}
-//static
-void LLPanelGroupMembersSubTab::addOwnerCB(S32 option, void* data)
+bool LLPanelGroupMembersSubTab::addOwnerCB(const LLSD& notification, const LLSD& response)
{
- LLPanelGroupMembersSubTab* self = (LLPanelGroupMembersSubTab*) data;
-
- if (!self) return;
-
- self->mHasModal = FALSE;
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ mHasModal = FALSE;
if (0 == option)
{
// User clicked "Yes"
- self->applyMemberChanges();
+ applyMemberChanges();
}
+ return false;
}
void LLPanelGroupMembersSubTab::applyMemberChanges()
@@ -2225,22 +2210,19 @@ void LLPanelGroupRolesSubTab::handleActionCheck(LLCheckBoxCtrl* check, bool forc
check->set(FALSE);
LLRoleData rd;
- LLStringUtil::format_map_t args;
+ LLSD args;
if ( gdatap->getRoleData(role_id, rd) )
{
- args["[ACTION_NAME]"] = rap->mDescription;
- args["[ROLE_NAME]"] = rd.mRoleName;
- struct ActionCBData* cb_data = new ActionCBData;
- cb_data->mSelf = this;
- cb_data->mCheck = check;
+ args["ACTION_NAME"] = rap->mDescription;
+ args["ROLE_NAME"] = rd.mRoleName;
mHasModal = TRUE;
std::string warning = "AssignDangerousActionWarning";
if (GP_ROLE_CHANGE_ACTIONS == power)
{
warning = "AssignDangerousAbilityWarning";
}
- gViewerWindow->alertXml(warning, args, addActionCB, cb_data);
+ LLNotifications::instance().add(warning, args, LLSD(), boost::bind(&LLPanelGroupRolesSubTab::addActionCB, this, _1, _2, check));
}
else
{
@@ -2262,22 +2244,21 @@ void LLPanelGroupRolesSubTab::handleActionCheck(LLCheckBoxCtrl* check, bool forc
notifyObservers();
}
-//static
-void LLPanelGroupRolesSubTab::addActionCB(S32 option, void* data)
+bool LLPanelGroupRolesSubTab::addActionCB(const LLSD& notification, const LLSD& response, LLCheckBoxCtrl* check)
{
- struct ActionCBData* cb_data = (struct ActionCBData*) data;
+ if (!check) return false;
- if (!cb_data || !cb_data->mSelf || !cb_data->mCheck) return;
-
- cb_data->mSelf->mHasModal = FALSE;
+ mHasModal = FALSE;
+ S32 option = LLNotification::getSelectedOption(notification, response);
if (0 == option)
{
// User clicked "Yes"
- cb_data->mCheck->set(TRUE);
+ check->set(TRUE);
const bool force_add = true;
- cb_data->mSelf->handleActionCheck(cb_data->mCheck, force_add);
+ handleActionCheck(check, force_add);
}
+ return false;
}
@@ -2413,9 +2394,9 @@ void LLPanelGroupRolesSubTab::handleDeleteRole()
if (role_item->getUUID().isNull() || role_item->getUUID() == gdatap->mOwnerRole)
{
- LLStringUtil::format_map_t args;
- args["[MESSAGE]"] = mRemoveEveryoneTxt;
- LLNotifyBox::showXml("GenericNotify", args);
+ LLSD args;
+ args["MESSAGE"] = mRemoveEveryoneTxt;
+ LLNotifications::instance().add("GenericNotify", args);
return;
}
diff --git a/indra/newview/llpanelgrouproles.h b/indra/newview/llpanelgrouproles.h
index f55d70f018..592e585f9e 100644
--- a/indra/newview/llpanelgrouproles.h
+++ b/indra/newview/llpanelgrouproles.h
@@ -73,9 +73,8 @@ public:
void transitionToTab();
// Used by attemptTransition to query the user's response to a tab that needs to apply.
- static void onNotifyCallback(S32 option, void* user_data);
- void handleNotifyCallback(S32 option);
- static void onModalClose(S32 option, void* user_data);
+ bool handleNotifyCallback(const LLSD& notification, const LLSD& response);
+ bool onModalClose(const LLSD& notification, const LLSD& response);
// Most of these messages are just passed on to the current sub-tab.
virtual std::string getHelpText() const;
@@ -188,7 +187,7 @@ public:
LLRoleMemberChangeType type);
void applyMemberChanges();
- static void addOwnerCB(S32 option, void* data);
+ bool addOwnerCB(const LLSD& notification, const LLSD& response);
virtual void activate();
virtual void deactivate();
@@ -250,7 +249,7 @@ public:
static void onActionCheck(LLUICtrl*, void*);
void handleActionCheck(LLCheckBoxCtrl*, bool force=false);
- static void addActionCB(S32 option, void* data);
+ bool addActionCB(const LLSD& notification, const LLSD& response, LLCheckBoxCtrl* check);
static void onPropertiesKey(LLLineEditor*, void*);
diff --git a/indra/newview/llpanelland.cpp b/indra/newview/llpanelland.cpp
index 11f88695c5..05381ae7d8 100644
--- a/indra/newview/llpanelland.cpp
+++ b/indra/newview/llpanelland.cpp
@@ -266,5 +266,5 @@ void LLPanelLandInfo::onClickAbout(void*)
void LLPanelLandInfo::onShowOwnersHelp(void* user_data)
{
- gViewerWindow->alertXml("ShowOwnersHelp");
+ LLNotifications::instance().add("ShowOwnersHelp");
}
diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index 20228ed306..929043e97d 100644
--- a/indra/newview/llpanellogin.cpp
+++ b/indra/newview/llpanellogin.cpp
@@ -899,16 +899,17 @@ void LLPanelLogin::onClickConnect(void *)
}
else
{
- gViewerWindow->alertXml("MustHaveAccountToLogIn",
- LLPanelLogin::newAccountAlertCallback);
+ LLNotifications::instance().add("MustHaveAccountToLogIn", LLSD(), LLSD(),
+ LLPanelLogin::newAccountAlertCallback);
}
}
}
// static
-void LLPanelLogin::newAccountAlertCallback(S32 option, void*)
+bool LLPanelLogin::newAccountAlertCallback(const LLSD& notification, const LLSD& response)
{
+ S32 option = LLNotification::getSelectedOption(notification, response);
if (0 == option)
{
llinfos << "Going to account creation URL" << llendl;
@@ -918,6 +919,7 @@ void LLPanelLogin::newAccountAlertCallback(S32 option, void*)
{
sInstance->setFocus(TRUE);
}
+ return false;
}
@@ -964,7 +966,7 @@ void LLPanelLogin::onPassKey(LLLineEditor* caller, void* user_data)
{
if (gKeyboard->getKeyDown(KEY_CAPSLOCK) && sCapslockDidNotification == FALSE)
{
- LLNotifyBox::showXml("CapsKeyOn");
+ LLNotifications::instance().add("CapsKeyOn");
sCapslockDidNotification = TRUE;
}
}
diff --git a/indra/newview/llpanellogin.h b/indra/newview/llpanellogin.h
index 9d7e386cda..1f803fa57c 100644
--- a/indra/newview/llpanellogin.h
+++ b/indra/newview/llpanellogin.h
@@ -82,7 +82,7 @@ public:
private:
static void onClickConnect(void*);
static void onClickNewAccount(void*);
- static void newAccountAlertCallback(S32 option, void*);
+ static bool newAccountAlertCallback(const LLSD& notification, const LLSD& response);
static void onClickQuit(void*);
static void onClickVersion(void*);
virtual void onNavigateComplete( const EventType& eventIn );
diff --git a/indra/newview/llpanelpermissions.cpp b/indra/newview/llpanelpermissions.cpp
index 8a75385984..b46e04d462 100644
--- a/indra/newview/llpanelpermissions.cpp
+++ b/indra/newview/llpanelpermissions.cpp
@@ -876,8 +876,9 @@ void LLPanelPermissions::cbGroupID(LLUUID group_id, void* userdata)
LLSelectMgr::getInstance()->sendGroup(group_id);
}
-void callback_deed_to_group(S32 option, void*)
+bool callback_deed_to_group(const LLSD& notification, const LLSD& response)
{
+ S32 option = LLNotification::getSelectedOption(notification, response);
if (0 == option)
{
LLUUID group_id;
@@ -888,12 +889,12 @@ void callback_deed_to_group(S32 option, void*)
// LLViewerStats::getInstance()->incStat(LLViewerStats::ST_RELEASE_COUNT);
}
}
+ return false;
}
void LLPanelPermissions::onClickDeedToGroup(void* data)
{
- gViewerWindow->alertXml( "DeedObjectToGroup",
- callback_deed_to_group, NULL);
+ LLNotifications::instance().add( "DeedObjectToGroup", LLSD(), LLSD(), callback_deed_to_group);
}
///----------------------------------------------------------------------------
@@ -1092,7 +1093,7 @@ void LLPanelPermissions::onCommitClickAction(LLUICtrl* ctrl, void*)
LLSelectMgr::getInstance()->selectGetSaleInfo(sale_info);
if (!sale_info.isForSale())
{
- gViewerWindow->alertXml("CantSetBuyObject");
+ LLNotifications::instance().add("CantSetBuyObject");
// Set click action back to its old value
U8 click_action = 0;
@@ -1110,7 +1111,7 @@ void LLPanelPermissions::onCommitClickAction(LLUICtrl* ctrl, void*)
if (!can_pay)
{
// Warn, but do it anyway.
- gViewerWindow->alertXml("ClickActionNotPayable");
+ LLNotifications::instance().add("ClickActionNotPayable");
}
}
LLSelectMgr::getInstance()->selectionSetClickAction(click_action);
diff --git a/indra/newview/llpanelpick.cpp b/indra/newview/llpanelpick.cpp
index 9bd118fa1d..2420d8d424 100644
--- a/indra/newview/llpanelpick.cpp
+++ b/indra/newview/llpanelpick.cpp
@@ -476,7 +476,7 @@ void LLPanelPick::onClickSet(void* data)
// is the location and nothing else
if ( gAgent.getRegion ()->getName () != self->mSimName )
{
- gViewerWindow->alertXml("SetPickLocation");
+ LLNotifications::instance().add("SetPickLocation");
};
self->mLocationEditor->setText(location_text);
diff --git a/indra/newview/llpanelplace.cpp b/indra/newview/llpanelplace.cpp
index 4ae253360a..100fa3209d 100644
--- a/indra/newview/llpanelplace.cpp
+++ b/indra/newview/llpanelplace.cpp
@@ -416,24 +416,24 @@ void LLPanelPlace::onClickLandmark(void* data)
void LLPanelPlace::onClickAuction(void* data)
{
LLPanelPlace* self = (LLPanelPlace*)data;
+ LLSD payload;
+ payload["auction_id"] = self->mAuctionID;
- gViewerWindow->alertXml("GoToAuctionPage",
- callbackAuctionWebPage,
- self);
+ LLNotifications::instance().add("GoToAuctionPage", LLSD(), payload, callbackAuctionWebPage);
}
// static
-void LLPanelPlace::callbackAuctionWebPage(S32 option, void* data)
+bool LLPanelPlace::callbackAuctionWebPage(const LLSD& notification, const LLSD& response)
{
- LLPanelPlace* self = (LLPanelPlace*)data;
-
+ S32 option = LLNotification::getSelectedOption(notification, response);
if (0 == option)
{
std::string url;
- url = AUCTION_URL + llformat( "%010d", self->mAuctionID);
+ url = AUCTION_URL + llformat("%010d", response["auction_id"].asInteger());
llinfos << "Loading auction page " << url << llendl;
LLWeb::loadURL(url);
}
+ return false;
}
diff --git a/indra/newview/llpanelplace.h b/indra/newview/llpanelplace.h
index 7a09f5cca6..db47889546 100644
--- a/indra/newview/llpanelplace.h
+++ b/indra/newview/llpanelplace.h
@@ -83,7 +83,7 @@ protected:
static void onClickAuction(void* data);
// Go to auction web page if user clicked OK
- static void callbackAuctionWebPage(S32 option, void* data);
+ static bool callbackAuctionWebPage(const LLSD& notification, const LLSD& response);
protected:
LLUUID mParcelID;
diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp
index 7661f9acd6..7e465a88bc 100644
--- a/indra/newview/llpreviewgesture.cpp
+++ b/indra/newview/llpreviewgesture.cpp
@@ -284,9 +284,8 @@ BOOL LLPreviewGesture::canClose()
else
{
// Bring up view-modal dialog: Save changes? Yes, No, Cancel
- gViewerWindow->alertXml("SaveChanges",
- handleSaveChangesDialog,
- this );
+ LLNotifications::instance().add("SaveChanges", LLSD(), LLSD(),
+ boost::bind(&LLPreviewGesture::handleSaveChangesDialog, this, _1, _2) );
return FALSE;
}
}
@@ -320,22 +319,21 @@ void LLPreviewGesture::setMinimized(BOOL minimize)
}
-// static
-void LLPreviewGesture::handleSaveChangesDialog(S32 option, void* data)
+bool LLPreviewGesture::handleSaveChangesDialog(const LLSD& notification, const LLSD& response)
{
- LLPreviewGesture* self = (LLPreviewGesture*)data;
+ S32 option = LLNotification::getSelectedOption(notification, response);
switch(option)
{
case 0: // "Yes"
- gGestureManager.stopGesture(self->mPreviewGesture);
- self->mCloseAfterSave = TRUE;
- onClickSave(data);
+ gGestureManager.stopGesture(mPreviewGesture);
+ mCloseAfterSave = TRUE;
+ onClickSave(this);
break;
case 1: // "No"
- gGestureManager.stopGesture(self->mPreviewGesture);
- self->mDirty = FALSE; // Force the dirty flag because user has clicked NO on confirm save dialog...
- self->close();
+ gGestureManager.stopGesture(mPreviewGesture);
+ mDirty = FALSE; // Force the dirty flag because user has clicked NO on confirm save dialog...
+ close();
break;
case 2: // "Cancel"
@@ -344,6 +342,7 @@ void LLPreviewGesture::handleSaveChangesDialog(S32 option, void* data)
LLAppViewer::instance()->abortQuit();
break;
}
+ return false;
}
@@ -1114,14 +1113,14 @@ void LLPreviewGesture::saveIfNeeded()
if (dp.getCurrentSize() > 1000)
{
- gViewerWindow->alertXml("GestureSaveFailedTooManySteps");
+ LLNotifications::instance().add("GestureSaveFailedTooManySteps");
delete gesture;
gesture = NULL;
}
else if (!ok)
{
- gViewerWindow->alertXml("GestureSaveFailedTryAgain");
+ LLNotifications::instance().add("GestureSaveFailedTryAgain");
delete gesture;
gesture = NULL;
}
@@ -1260,7 +1259,7 @@ void LLPreviewGesture::onSaveComplete(const LLUUID& asset_uuid, void* user_data,
}
else
{
- gViewerWindow->alertXml("GestureSaveFailedObjectNotFound");
+ LLNotifications::instance().add("GestureSaveFailedObjectNotFound");
}
}
@@ -1274,9 +1273,9 @@ void LLPreviewGesture::onSaveComplete(const LLUUID& asset_uuid, void* user_data,
else
{
llwarns << "Problem saving gesture: " << status << llendl;
- LLStringUtil::format_map_t args;
- args["[REASON]"] = std::string(LLAssetStorage::getErrorString(status));
- gViewerWindow->alertXml("GestureSaveFailedReason",args);
+ LLSD args;
+ args["REASON"] = std::string(LLAssetStorage::getErrorString(status));
+ LLNotifications::instance().add("GestureSaveFailedReason", args);
}
delete info;
info = NULL;
diff --git a/indra/newview/llpreviewgesture.h b/indra/newview/llpreviewgesture.h
index 3b07608134..bbe9486bfd 100644
--- a/indra/newview/llpreviewgesture.h
+++ b/indra/newview/llpreviewgesture.h
@@ -101,7 +101,7 @@ protected:
void* user_data,
S32 status, LLExtStat ext_status);
- static void handleSaveChangesDialog(S32 option, void* userdata);
+ bool handleSaveChangesDialog(const LLSD& notification, const LLSD& response);
// Write UI back into gesture
LLMultiGesture* createGesture();
diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp
index 61ebe6cbbc..ef61270069 100644
--- a/indra/newview/llpreviewnotecard.cpp
+++ b/indra/newview/llpreviewnotecard.cpp
@@ -229,9 +229,7 @@ BOOL LLPreviewNotecard::canClose()
else
{
// Bring up view-modal dialog: Save changes? Yes, No, Cancel
- gViewerWindow->alertXml("SaveChanges",
- &LLPreviewNotecard::handleSaveChangesDialog,
- this);
+ LLNotifications::instance().add("SaveChanges", LLSD(), LLSD(), boost::bind(&LLPreviewNotecard::handleSaveChangesDialog,this, _1, _2));
return FALSE;
}
@@ -403,15 +401,15 @@ void LLPreviewNotecard::onLoadComplete(LLVFS *vfs,
if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status ||
LL_ERR_FILE_EMPTY == status)
{
- LLNotifyBox::showXml("NotecardMissing");
+ LLNotifications::instance().add("NotecardMissing");
}
else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status)
{
- LLNotifyBox::showXml("NotecardNoPermissions");
+ LLNotifications::instance().add("NotecardNoPermissions");
}
else
{
- LLNotifyBox::showXml("UnableToLoadNotecard");
+ LLNotifications::instance().add("UnableToLoadNotecard");
}
llwarns << "Problem loading notecard: " << status << llendl;
@@ -578,7 +576,7 @@ void LLPreviewNotecard::onSaveComplete(const LLUUID& asset_uuid, void* user_data
}
else
{
- gViewerWindow->alertXml("SaveNotecardFailObjectNotFound");
+ LLNotifications::instance().add("SaveNotecardFailObjectNotFound");
}
}
// Perform item copy to inventory
@@ -601,9 +599,9 @@ void LLPreviewNotecard::onSaveComplete(const LLUUID& asset_uuid, void* user_data
else
{
llwarns << "Problem saving notecard: " << status << llendl;
- LLStringUtil::format_map_t args;
- args["[REASON]"] = std::string(LLAssetStorage::getErrorString(status));
- gViewerWindow->alertXml("SaveNotecardFailReason",args);
+ LLSD args;
+ args["REASON"] = std::string(LLAssetStorage::getErrorString(status));
+ LLNotifications::instance().add("SaveNotecardFailReason", args);
}
std::string uuid_string;
@@ -614,20 +612,19 @@ void LLPreviewNotecard::onSaveComplete(const LLUUID& asset_uuid, void* user_data
delete info;
}
-// static
-void LLPreviewNotecard::handleSaveChangesDialog(S32 option, void* userdata)
+bool LLPreviewNotecard::handleSaveChangesDialog(const LLSD& notification, const LLSD& response)
{
- LLPreviewNotecard* self = (LLPreviewNotecard*)userdata;
+ S32 option = LLNotification::getSelectedOption(notification, response);
switch(option)
{
case 0: // "Yes"
- self->mCloseAfterSave = TRUE;
- LLPreviewNotecard::onClickSave((void*)self);
+ mCloseAfterSave = TRUE;
+ LLPreviewNotecard::onClickSave((void*)this);
break;
case 1: // "No"
- self->mForceClose = TRUE;
- self->close();
+ mForceClose = TRUE;
+ close();
break;
case 2: // "Cancel"
@@ -636,6 +633,7 @@ void LLPreviewNotecard::handleSaveChangesDialog(S32 option, void* userdata)
LLAppViewer::instance()->abortQuit();
break;
}
+ return false;
}
void LLPreviewNotecard::reshape(S32 width, S32 height, BOOL called_from_parent)
diff --git a/indra/newview/llpreviewnotecard.h b/indra/newview/llpreviewnotecard.h
index 1c801abf59..7175a764ec 100644
--- a/indra/newview/llpreviewnotecard.h
+++ b/indra/newview/llpreviewnotecard.h
@@ -101,7 +101,7 @@ protected:
void* user_data,
S32 status, LLExtStat ext_status);
- static void handleSaveChangesDialog(S32 option, void* userdata);
+ bool handleSaveChangesDialog(const LLSD& notification, const LLSD& response);
virtual const char *getTitleName() const { return "Note"; }
diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp
index 2717c44415..42363079a4 100644
--- a/indra/newview/llpreviewscript.cpp
+++ b/indra/newview/llpreviewscript.cpp
@@ -608,27 +608,26 @@ BOOL LLScriptEdCore::canClose()
else
{
// Bring up view-modal dialog: Save changes? Yes, No, Cancel
- gViewerWindow->alertXml("SaveChanges", LLScriptEdCore::handleSaveChangesDialog, this);
+ LLNotifications::instance().add("SaveChanges", LLSD(), LLSD(), boost::bind(&LLScriptEdCore::handleSaveChangesDialog, this, _1, _2));
return FALSE;
}
}
-// static
-void LLScriptEdCore::handleSaveChangesDialog( S32 option, void* userdata )
+bool LLScriptEdCore::handleSaveChangesDialog(const LLSD& notification, const LLSD& response )
{
- LLScriptEdCore* self = (LLScriptEdCore*) userdata;
+ S32 option = LLNotification::getSelectedOption(notification, response);
switch( option )
{
case 0: // "Yes"
// close after saving
- LLScriptEdCore::doSave( self, TRUE );
+ LLScriptEdCore::doSave( this, TRUE );
break;
case 1: // "No"
- self->mForceClose = TRUE;
+ mForceClose = TRUE;
// This will close immediately because mForceClose is true, so we won't
// infinite loop with these dialogs. JC
- ((LLFloater*) self->getParent())->close();
+ ((LLFloater*) getParent())->close();
break;
case 2: // "Cancel"
@@ -637,29 +636,32 @@ void LLScriptEdCore::handleSaveChangesDialog( S32 option, void* userdata )
LLAppViewer::instance()->abortQuit();
break;
}
+ return false;
}
// static
-void LLScriptEdCore::onHelpWebDialog(S32 option, void* userdata)
+bool LLScriptEdCore::onHelpWebDialog(const LLSD& notification, const LLSD& response)
{
- LLScriptEdCore* corep = (LLScriptEdCore*)userdata;
+ S32 option = LLNotification::getSelectedOption(notification, response);
switch(option)
{
case 0:
- LLWeb::loadURL(corep->mHelpURL);
+ LLWeb::loadURL(notification["payload"]["help_url"]);
break;
default:
break;
}
+ return false;
}
// static
void LLScriptEdCore::onBtnHelp(void* userdata)
{
- gViewerWindow->alertXml("WebLaunchLSLGuide",
- onHelpWebDialog,
- userdata);
+ LLScriptEdCore* corep = (LLScriptEdCore*)userdata;
+ LLSD payload;
+ payload["help_url"] = corep->mHelpURL;
+ LLNotifications::instance().add("WebLaunchLSLGuide", LLSD(), payload, onHelpWebDialog);
}
// static
@@ -818,8 +820,7 @@ void LLScriptEdCore::onBtnUndoChanges( void* userdata )
LLScriptEdCore* self = (LLScriptEdCore*) userdata;
if( !self->mEditor->tryToRevertToPristineState() )
{
- gViewerWindow->alertXml("ScriptCannotUndo",
- LLScriptEdCore::handleReloadFromServerDialog, self);
+ LLNotifications::instance().add("ScriptCannotUndo", LLSD(), LLSD(), boost::bind(&LLScriptEdCore::handleReloadFromServerDialog, self, _1, _2));
}
}
@@ -965,17 +966,16 @@ void LLScriptEdCore::onErrorList(LLUICtrl*, void* user_data)
}
}
-// static
-void LLScriptEdCore::handleReloadFromServerDialog( S32 option, void* userdata )
+bool LLScriptEdCore::handleReloadFromServerDialog(const LLSD& notification, const LLSD& response )
{
- LLScriptEdCore* self = (LLScriptEdCore*) userdata;
+ S32 option = LLNotification::getSelectedOption(notification, response);
switch( option )
{
case 0: // "Yes"
- if( self->mLoadCallback )
+ if( mLoadCallback )
{
- self->mEditor->setText( self->getString("loading") );
- self->mLoadCallback( self->mUserdata );
+ mEditor->setText( getString("loading") );
+ mLoadCallback( mUserdata );
}
break;
@@ -986,6 +986,7 @@ void LLScriptEdCore::handleReloadFromServerDialog( S32 option, void* userdata )
llassert(0);
break;
}
+ return false;
}
void LLScriptEdCore::selectFirstError()
@@ -1444,9 +1445,9 @@ void LLPreviewLSL::onSaveComplete(const LLUUID& asset_uuid, void* user_data, S32
else
{
llwarns << "Problem saving script: " << status << llendl;
- LLStringUtil::format_map_t args;
- args["[REASON]"] = std::string(LLAssetStorage::getErrorString(status));
- gViewerWindow->alertXml("SaveScriptFailReason", args);
+ LLSD args;
+ args["REASON"] = std::string(LLAssetStorage::getErrorString(status));
+ LLNotifications::instance().add("SaveScriptFailReason", args);
}
delete info;
}
@@ -1482,9 +1483,9 @@ void LLPreviewLSL::onSaveBytecodeComplete(const LLUUID& asset_uuid, void* user_d
else
{
llwarns << "Problem saving LSL Bytecode (Preview)" << llendl;
- LLStringUtil::format_map_t args;
- args["[REASON]"] = std::string(LLAssetStorage::getErrorString(status));
- gViewerWindow->alertXml("SaveBytecodeFailReason", args);
+ LLSD args;
+ args["REASON"] = std::string(LLAssetStorage::getErrorString(status));
+ LLNotifications::instance().add("SaveBytecodeFailReason", args);
}
delete instance_uuid;
}
@@ -1530,15 +1531,15 @@ void LLPreviewLSL::onLoadComplete( LLVFS *vfs, const LLUUID& asset_uuid, LLAsset
if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status ||
LL_ERR_FILE_EMPTY == status)
{
- LLNotifyBox::showXml("ScriptMissing");
+ LLNotifications::instance().add("ScriptMissing");
}
else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status)
{
- LLNotifyBox::showXml("ScriptNoPermissions");
+ LLNotifications::instance().add("ScriptNoPermissions");
}
else
{
- LLNotifyBox::showXml("UnableToLoadScript");
+ LLNotifications::instance().add("UnableToLoadScript");
}
preview->mAssetStatus = PREVIEW_ASSET_ERROR;
@@ -1846,15 +1847,15 @@ void LLLiveLSLEditor::onLoadComplete(LLVFS *vfs, const LLUUID& asset_id,
if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status ||
LL_ERR_FILE_EMPTY == status)
{
- LLNotifyBox::showXml("ScriptMissing");
+ LLNotifications::instance().add("ScriptMissing");
}
else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status)
{
- LLNotifyBox::showXml("ScriptNoPermissions");
+ LLNotifications::instance().add("ScriptNoPermissions");
}
else
{
- LLNotifyBox::showXml("UnableToLoadScript");
+ LLNotifications::instance().add("UnableToLoadScript");
}
instance->mAssetStatus = PREVIEW_ASSET_ERROR;
}
@@ -1941,7 +1942,7 @@ void LLLiveLSLEditor::onRunningCheckboxClicked( LLUICtrl*, void* userdata )
else
{
runningCheckbox->set(!running);
- gViewerWindow->alertXml("CouldNotStartStopScript");
+ LLNotifications::instance().add("CouldNotStartStopScript");
}
}
@@ -1964,7 +1965,7 @@ void LLLiveLSLEditor::onReset(void *userdata)
}
else
{
- gViewerWindow->alertXml("CouldNotStartStopScript");
+ LLNotifications::instance().add("CouldNotStartStopScript");
}
}
@@ -2058,7 +2059,7 @@ void LLLiveLSLEditor::saveIfNeeded()
LLViewerObject* object = gObjectList.findObject(mObjectID);
if(!object)
{
- gViewerWindow->alertXml("SaveScriptFailObjectNotFound");
+ LLNotifications::instance().add("SaveScriptFailObjectNotFound");
return;
}
@@ -2066,7 +2067,7 @@ void LLLiveLSLEditor::saveIfNeeded()
{
// $NOTE: While the error message may not be exactly correct,
// it's pretty close.
- gViewerWindow->alertXml("SaveScriptFailObjectNotFound");
+ LLNotifications::instance().add("SaveScriptFailObjectNotFound");
return;
}
@@ -2268,9 +2269,9 @@ void LLLiveLSLEditor::onSaveTextComplete(const LLUUID& asset_uuid, void* user_da
if (status)
{
llwarns << "Unable to save text for a script." << llendl;
- LLStringUtil::format_map_t args;
- args["[REASON]"] = std::string(LLAssetStorage::getErrorString(status));
- gViewerWindow->alertXml("CompileQueueSaveText", args);
+ LLSD args;
+ args["REASON"] = std::string(LLAssetStorage::getErrorString(status));
+ LLNotifications::instance().add("CompileQueueSaveText", args);
}
else
{
@@ -2329,9 +2330,9 @@ void LLLiveLSLEditor::onSaveBytecodeComplete(const LLUUID& asset_uuid, void* use
llinfos << "Problem saving LSL Bytecode (Live Editor)" << llendl;
llwarns << "Unable to save a compiled script." << llendl;
- LLStringUtil::format_map_t args;
- args["[REASON]"] = std::string(LLAssetStorage::getErrorString(status));
- gViewerWindow->alertXml("CompileQueueSaveBytecode", args);
+ LLSD args;
+ args["REASON"] = std::string(LLAssetStorage::getErrorString(status));
+ LLNotifications::instance().add("CompileQueueSaveBytecode", args);
}
std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,asset_uuid.asString());
diff --git a/indra/newview/llpreviewscript.h b/indra/newview/llpreviewscript.h
index c0af06f480..c84d5e6d8f 100644
--- a/indra/newview/llpreviewscript.h
+++ b/indra/newview/llpreviewscript.h
@@ -80,10 +80,10 @@ public:
BOOL canClose();
- static void handleSaveChangesDialog(S32 option, void* userdata);
- static void handleReloadFromServerDialog(S32 option, void* userdata);
+ bool handleSaveChangesDialog(const LLSD& notification, const LLSD& response);
+ bool handleReloadFromServerDialog(const LLSD& notification, const LLSD& response);
- static void onHelpWebDialog(S32 option, void* userdata);
+ static bool onHelpWebDialog(const LLSD& notification, const LLSD& response);
static void onBtnHelp(void* userdata);
static void onBtnDynamicHelp(void* userdata);
static void onCheckLock(LLUICtrl*, void*);
diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp
index 79b8313352..fefa6d40d7 100644
--- a/indra/newview/llpreviewtexture.cpp
+++ b/indra/newview/llpreviewtexture.cpp
@@ -349,15 +349,15 @@ void LLPreviewTexture::onFileLoadedForSave(BOOL success,
LLPointer<LLImageTGA> image_tga = new LLImageTGA;
if( !image_tga->encode( src ) )
{
- LLStringUtil::format_map_t args;
- args["[FILE]"] = self->mSaveFileName;
- gViewerWindow->alertXml("CannotEncodeFile", args);
+ LLSD args;
+ args["FILE"] = self->mSaveFileName;
+ LLNotifications::instance().add("CannotEncodeFile", args);
}
else if( !image_tga->save( self->mSaveFileName ) )
{
- LLStringUtil::format_map_t args;
- args["[FILE]"] = self->mSaveFileName;
- gViewerWindow->alertXml("CannotWriteFile", args);
+ LLSD args;
+ args["FILE"] = self->mSaveFileName;
+ LLNotifications::instance().add("CannotWriteFile", args);
}
else
{
@@ -370,7 +370,7 @@ void LLPreviewTexture::onFileLoadedForSave(BOOL success,
if( self && !success )
{
- gViewerWindow->alertXml("CannotDownloadFile");
+ LLNotifications::instance().add("CannotDownloadFile");
}
}
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index 81decdf40a..ae4be6173b 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -2695,7 +2695,8 @@ void LLSelectMgr::selectDelete()
return;
}
- LLObjectSelectionHandle* selection_handlep = new LLObjectSelectionHandle(getSelection());
+ LLNotification::Params params("ConfirmObjectDeleteLock");
+ params.functor(boost::bind(&LLSelectMgr::confirmDelete, _1, _2, getSelection()));
if(locked_but_deleteable_object ||
no_copy_but_deleteable_object ||
@@ -2711,72 +2712,55 @@ void LLSelectMgr::selectDelete()
if(locked_but_deleteable_object && !no_copy_but_deleteable_object && all_owned_by_you)
{
//Locked only
- gViewerWindow->alertXml( "ConfirmObjectDeleteLock",
- &LLSelectMgr::confirmDelete,
- selection_handlep);
+ params.name("ConfirmObjectDeleteLock");
}
else if(!locked_but_deleteable_object && no_copy_but_deleteable_object && all_owned_by_you)
{
//No Copy only
- gViewerWindow->alertXml( "ConfirmObjectDeleteNoCopy",
- &LLSelectMgr::confirmDelete,
- selection_handlep);
+ params.name("ConfirmObjectDeleteNoCopy");
}
else if(!locked_but_deleteable_object && !no_copy_but_deleteable_object && !all_owned_by_you)
{
//not owned only
- gViewerWindow->alertXml( "ConfirmObjectDeleteNoOwn",
- &LLSelectMgr::confirmDelete,
- selection_handlep);
+ params.name("ConfirmObjectDeleteNoOwn");
}
else if(locked_but_deleteable_object && no_copy_but_deleteable_object && all_owned_by_you)
{
//locked and no copy
- gViewerWindow->alertXml( "ConfirmObjectDeleteLockNoCopy",
- &LLSelectMgr::confirmDelete,
- selection_handlep);
+ params.name("ConfirmObjectDeleteLockNoCopy");
}
else if(locked_but_deleteable_object && !no_copy_but_deleteable_object && !all_owned_by_you)
{
//locked and not owned
- gViewerWindow->alertXml( "ConfirmObjectDeleteLockNoOwn",
- &LLSelectMgr::confirmDelete,
- selection_handlep);
+ params.name("ConfirmObjectDeleteLockNoOwn");
}
else if(!locked_but_deleteable_object && no_copy_but_deleteable_object && !all_owned_by_you)
{
//no copy and not owned
- gViewerWindow->alertXml( "ConfirmObjectDeleteNoCopyNoOwn",
- &LLSelectMgr::confirmDelete,
- selection_handlep);
+ params.name("ConfirmObjectDeleteNoCopyNoOwn");
}
else
{
//locked, no copy and not owned
- gViewerWindow->alertXml( "ConfirmObjectDeleteLockNoCopyNoOwn",
- &LLSelectMgr::confirmDelete,
- selection_handlep);
+ params.name("ConfirmObjectDeleteLockNoCopyNoOwn");
}
-
-
+ LLNotifications::instance().add(params);
}
else
{
- confirmDelete(0, (void*)selection_handlep);
+ LLNotifications::instance().forceResponse(params, 0);
}
}
// static
-void LLSelectMgr::confirmDelete(S32 option, void* data)
+bool LLSelectMgr::confirmDelete(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle handle)
{
- LLObjectSelectionHandle handle = *(LLObjectSelectionHandle*)data;
- delete (LLObjectSelectionHandle*)data;
-
+ S32 option = LLNotification::getSelectedOption(notification, response);
if (!handle->getObjectCount())
{
llwarns << "Nothing to delete!" << llendl;
- return;
+ return false;
}
switch(option)
@@ -2815,6 +2799,7 @@ void LLSelectMgr::confirmDelete(S32 option, void* data)
default:
break;
}
+ return false;
}
diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h
index f210fdb9d3..27bcb5a582 100644
--- a/indra/newview/llselectmgr.h
+++ b/indra/newview/llselectmgr.h
@@ -683,7 +683,7 @@ private:
static void packHingeHead(void *user_data);
static void packPermissionsHead(void* user_data);
static void packGodlikeHead(void* user_data);
- static void confirmDelete(S32 option, void* data);
+ static bool confirmDelete(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle handle);
private:
LLPointer<LLViewerImage> mSilhouetteImagep;
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 9a6454be33..1dc1ddd451 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -235,18 +235,17 @@ std::string load_password_from_disk();
void save_password_to_disk(const char* hashed_password);
bool is_hex_string(U8* str, S32 len);
void show_first_run_dialog();
-void first_run_dialog_callback(S32 option, void* userdata);
+bool first_run_dialog_callback(const LLSD& notification, const LLSD& response);
void set_startup_status(const F32 frac, const std::string& string, const std::string& msg);
-void login_alert_status(S32 option, void* user_data);
+bool login_alert_status(const LLSD& notification, const LLSD& response);
void update_app(BOOL mandatory, const std::string& message);
-void update_dialog_callback(S32 option, void *userdata);
+bool update_dialog_callback(const LLSD& notification, const LLSD& response);
void login_packet_failed(void**, S32 result);
void use_circuit_callback(void**, S32 result);
void register_viewer_callbacks(LLMessageSystem* msg);
void init_stat_view();
void asset_callback_nothing(LLVFS*, const LLUUID&, LLAssetType::EType, void*, S32);
-void dialog_choose_gender_first_start();
-void callback_choose_gender(S32 option, void* userdata);
+bool callback_choose_gender(const LLSD& notification, const LLSD& response);
void init_start_screen(S32 location_id);
void release_start_screen();
void reset_login();
@@ -387,16 +386,16 @@ bool idle_startup()
if (LLFeatureManager::getInstance()->isSafe())
{
- gViewerWindow->alertXml("DisplaySetToSafe");
+ LLNotifications::instance().add("DisplaySetToSafe");
}
else if ((gSavedSettings.getS32("LastFeatureVersion") < LLFeatureManager::getInstance()->getVersion()) &&
(gSavedSettings.getS32("LastFeatureVersion") != 0))
{
- gViewerWindow->alertXml("DisplaySetToRecommended");
+ LLNotifications::instance().add("DisplaySetToRecommended");
}
else if (!gViewerWindow->getInitAlert().empty())
{
- gViewerWindow->alertXml(gViewerWindow->getInitAlert());
+ LLNotifications::instance().add(gViewerWindow->getInitAlert());
}
gSavedSettings.setS32("LastFeatureVersion", LLFeatureManager::getInstance()->getVersion());
@@ -419,10 +418,11 @@ bool idle_startup()
}
if (!xml_ok)
{
- // *TODO:translate (maybe - very unlikely error message)
- // Note: alerts.xml may be invalid - if this gets translated it will need to be in the code
- std::string bad_xui_msg = "An error occured while updating Second Life. Please download the latest version from www.secondlife.com.";
- LLAppViewer::instance()->earlyExit(bad_xui_msg);
+ // If XML is bad, there's a good possibility that notifications.xml is ALSO bad.
+ // If that's so, then we'll get a fatal error on attempting to load it,
+ // which will display a nontranslatable error message that says so.
+ // Otherwise, we'll display a reasonable error message that IS translatable.
+ LLAppViewer::instance()->earlyExit("BadInstallation");
}
//
// Statistics stuff
@@ -440,9 +440,9 @@ bool idle_startup()
if (ll_init_ares() == NULL || !gAres->isInitialized())
{
- LL_WARNS("AppInit") << "Could not start address resolution system" << LL_ENDL;
- std::string msg = LLTrans::getString("LoginFailedNoNetwork");
- LLAppViewer::instance()->earlyExit(msg);
+ std::string diagnostic = "Could not start address resolution system";
+ LL_WARNS("AppInit") << diagnostic << LL_ENDL;
+ LLAppViewer::instance()->earlyExit("LoginFailedNoNetwork", LLSD().insert("DIAGNOSTIC", diagnostic));
}
//
@@ -500,9 +500,9 @@ bool idle_startup()
circuit_heartbeat_interval,
circuit_timeout))
{
- std::string msg = LLTrans::getString("LoginFailedNoNetwork");
- msg.append(llformat(" Error: %d", gMessageSystem->getErrorCode()));
- LLAppViewer::instance()->earlyExit(msg);
+ std::string diagnostic = llformat(" Error: %d", gMessageSystem->getErrorCode());
+ LL_WARNS("AppInit") << diagnostic << LL_ENDL;
+ LLAppViewer::instance()->earlyExit("LoginFailedNoNetwork", LLSD().insert("DIAGNOSTIC", diagnostic));
}
#if LL_WINDOWS
@@ -525,7 +525,7 @@ bool idle_startup()
}
else
{
- LLAppViewer::instance()->earlyExit("Message Template " + message_template_path + " not found.");
+ LLAppViewer::instance()->earlyExit("MessageTemplateNotFound", LLSD().insert("PATH", message_template_path));
}
if(gMessageSystem && gMessageSystem->isOK())
@@ -1551,9 +1551,9 @@ bool idle_startup()
exit(0);
}
// Bounce back to the login screen.
- LLStringUtil::format_map_t args;
- args["[ERROR_MESSAGE]"] = emsg.str();
- gViewerWindow->alertXml("ErrorMessage", args, login_alert_done);
+ LLSD args;
+ args["ERROR_MESSAGE"] = emsg.str();
+ LLNotifications::instance().add("ErrorMessage", args, LLSD(), login_alert_done);
reset_login();
gSavedSettings.setBOOL("AutoLogin", FALSE);
show_connect_box = true;
@@ -1571,9 +1571,9 @@ bool idle_startup()
exit(0);
}
// Bounce back to the login screen.
- LLStringUtil::format_map_t args;
- args["[ERROR_MESSAGE]"] = emsg.str();
- gViewerWindow->alertXml("ErrorMessage", args, login_alert_done);
+ LLSD args;
+ args["ERROR_MESSAGE"] = emsg.str();
+ LLNotifications::instance().add("ErrorMessage", args, LLSD(), login_alert_done);
reset_login();
gSavedSettings.setBOOL("AutoLogin", FALSE);
show_connect_box = true;
@@ -2300,23 +2300,23 @@ bool idle_startup()
// location is not your expected location. So, if this is
// your first login, then you do not have an expectation,
// thus, do not show this alert.
- LLStringUtil::format_map_t args;
+ LLSD args;
if (url_ok)
{
- args["[TYPE]"] = "desired";
- args["[HELP]"] = "";
+ args["TYPE"] = "desired";
+ args["HELP"] = "";
}
else if (gSavedSettings.getBOOL("LoginLastLocation"))
{
- args["[TYPE]"] = "last";
- args["[HELP]"] = "";
+ args["TYPE"] = "last";
+ args["HELP"] = "";
}
else
{
- args["[TYPE]"] = "home";
- args["[HELP]"] = "You may want to set a new home location.";
+ args["TYPE"] = "home";
+ args["HELP"] = "You may want to set a new home location.";
}
- gViewerWindow->alertXml("AvatarMoved", args);
+ LLNotifications::instance().add("AvatarMoved", args);
}
else
{
@@ -2411,16 +2411,15 @@ bool idle_startup()
// initial outfit, but if the load hasn't started
// already then something is wrong so fall back
// to generic outfits. JC
- gViewerWindow->alertXml("WelcomeChooseSex",
- callback_choose_gender, NULL);
+ LLNotifications::instance().add("WelcomeChooseSex", LLSD(), LLSD(),
+ callback_choose_gender);
LLStartUp::setStartupState( STATE_CLEANUP );
return TRUE;
}
if (wearables_time > MAX_WEARABLES_TIME)
{
- // It's taken too long to load, show the world
- gViewerWindow->alertXml("ClothingLoading");
+ LLNotifications::instance().add("ClothingLoading");
LLViewerStats::getInstance()->incStat(LLViewerStats::ST_WEARABLES_TOO_LONG);
LLStartUp::setStartupState( STATE_CLEANUP );
return TRUE;
@@ -2440,7 +2439,7 @@ bool idle_startup()
else
{
// OK to just get the wearables
- if ( gAgent.getWearablesLoaded() )
+ if ( gAgent.areWearablesLoaded() )
{
// We have our clothing, proceed.
//llinfos << "wearables loaded" << llendl;
@@ -2722,11 +2721,12 @@ bool is_hex_string(U8* str, S32 len)
void show_first_run_dialog()
{
- gViewerWindow->alertXml("FirstRun", first_run_dialog_callback, NULL);
+ LLNotifications::instance().add("FirstRun", LLSD(), LLSD(), first_run_dialog_callback);
}
-void first_run_dialog_callback(S32 option, void* userdata)
+bool first_run_dialog_callback(const LLSD& notification, const LLSD& response)
{
+ S32 option = LLNotification::getSelectedOption(notification, response);
if (0 == option)
{
LL_DEBUGS("AppInit") << "First run dialog cancelling" << LL_ENDL;
@@ -2734,6 +2734,7 @@ void first_run_dialog_callback(S32 option, void* userdata)
}
LLPanelLogin::giveFocus();
+ return false;
}
@@ -2746,8 +2747,9 @@ void set_startup_status(const F32 frac, const std::string& string, const std::st
gViewerWindow->setProgressMessage(msg);
}
-void login_alert_status(S32 option, void* user_data)
+bool login_alert_status(const LLSD& notification, const LLSD& response)
{
+ S32 option = LLNotification::getSelectedOption(notification, response);
// Buttons
switch( option )
{
@@ -2766,6 +2768,7 @@ void login_alert_status(S32 option, void* user_data)
}
LLPanelLogin::giveFocus();
+ return false;
}
void update_app(BOOL mandatory, const std::string& auth_msg)
@@ -2781,67 +2784,66 @@ void update_app(BOOL mandatory, const std::string& auth_msg)
{
msg = "(" + auth_msg + ") \n";
}
- LLStringUtil::format_map_t args;
- args["[MESSAGE]"] = msg;
-
- // represent a bool as a null/non-null pointer
- void *mandatoryp = mandatory ? &mandatory : NULL;
+ LLSD args;
+ args["MESSAGE"] = msg;
+
+ LLSD payload;
+ payload["mandatory"] = mandatory;
+
+/*
+ We're constructing one of the following 6 strings here:
+ "DownloadWindowsMandatory"
+ "DownloadWindowsReleaseForDownload"
+ "DownloadWindows"
+ "DownloadMacMandatory"
+ "DownloadMacReleaseForDownload"
+ "DownloadMac"
+
+ I've called them out explicitly in this comment so that they can be grepped for.
+
+ Also, we assume that if we're not Windows we're Mac. If we ever intend to support
+ Linux with autoupdate, this should be an explicit #elif LL_DARWIN, but
+ we'd rather deliver the wrong message than no message, so until Linux is supported
+ we'll leave it alone.
+ */
+ std::string notification_name = "Download";
+
#if LL_WINDOWS
- if (mandatory)
- {
- gViewerWindow->alertXml("DownloadWindowsMandatory", args,
- update_dialog_callback,
- mandatoryp);
- }
- else
- {
-#if LL_RELEASE_FOR_DOWNLOAD
- gViewerWindow->alertXml("DownloadWindowsReleaseForDownload", args,
- update_dialog_callback,
- mandatoryp);
+ notification_name += "Windows";
#else
- gViewerWindow->alertXml("DownloadWindows", args,
- update_dialog_callback,
- mandatoryp);
+ notification_name += "Mac";
#endif
- }
-#else
+
if (mandatory)
{
- gViewerWindow->alertXml("DownloadMacMandatory", args,
- update_dialog_callback,
- mandatoryp);
+ notification_name += "Mandatory";
}
else
{
#if LL_RELEASE_FOR_DOWNLOAD
- gViewerWindow->alertXml("DownloadMacReleaseForDownload", args,
- update_dialog_callback,
- mandatoryp);
-#else
- gViewerWindow->alertXml("DownloadMac", args,
- update_dialog_callback,
- mandatoryp);
+ notification_name += "ReleaseForDownload";
#endif
}
-#endif
-
+
+ LLNotifications::instance().add(notification_name, args, payload, update_dialog_callback);
+
}
-
-void update_dialog_callback(S32 option, void *userdata)
+bool update_dialog_callback(const LLSD& notification, const LLSD& response)
{
- bool mandatory = userdata != NULL;
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ std::string update_exe_path;
+ bool mandatory = notification["payload"]["mandatory"].asBoolean();
#if !LL_RELEASE_FOR_DOWNLOAD
if (option == 2)
{
LLStartUp::setStartupState( STATE_LOGIN_AUTH_INIT );
- return;
+ return false;
}
#endif
-
+
if (option == 1)
{
// ...user doesn't want to do it
@@ -2855,7 +2857,7 @@ void update_dialog_callback(S32 option, void *userdata)
{
LLStartUp::setStartupState( STATE_LOGIN_AUTH_INIT );
}
- return;
+ return false;
}
LLSD query_map = LLSD::emptyMap();
@@ -2890,7 +2892,7 @@ void update_dialog_callback(S32 option, void *userdata)
// We're hosed, bail
LL_WARNS("AppInit") << "LLDir::getTempFilename() failed" << LL_ENDL;
LLAppViewer::instance()->forceQuit();
- return;
+ return false;
}
LLAppViewer::sUpdaterInfo->mUpdateExePath += ".exe";
@@ -2911,7 +2913,7 @@ void update_dialog_callback(S32 option, void *userdata)
LL_WARNS("AppInit") << "Unable to copy the updater!" << LL_ENDL;
LLAppViewer::instance()->forceQuit();
- return;
+ return false;
}
// if a sim name was passed in via command line parameter (typically through a SLURL)
@@ -2955,6 +2957,7 @@ void update_dialog_callback(S32 option, void *userdata)
LLStringUtil::null, OSMB_OK);
#endif
LLAppViewer::instance()->forceQuit();
+ return false;
}
void use_circuit_callback(void**, S32 result)
@@ -2968,8 +2971,7 @@ void use_circuit_callback(void**, S32 result)
{
// Make sure user knows something bad happened. JC
LL_WARNS("AppInit") << "Backing up to login screen!" << LL_ENDL;
- gViewerWindow->alertXml("LoginPacketNeverReceived",
- login_alert_status, NULL);
+ LLNotifications::instance().add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status);
reset_login();
}
else
@@ -3753,8 +3755,9 @@ const S32 OPT_CLOSED_WINDOW = -1;
const S32 OPT_MALE = 0;
const S32 OPT_FEMALE = 1;
-void callback_choose_gender(S32 option, void* userdata)
-{
+bool callback_choose_gender(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotification::getSelectedOption(notification, response);
switch(option)
{
case OPT_MALE:
@@ -3767,6 +3770,7 @@ void callback_choose_gender(S32 option, void* userdata)
LLStartUp::loadInitialOutfit( FEMALE_OUTFIT_FOLDER, "female" );
break;
}
+ return false;
}
void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name,
@@ -3809,8 +3813,8 @@ void LLStartUp::loadInitialOutfit( const std::string& outfit_folder_name,
// This is really misnamed -- it means we have started loading
// an outfit/shape that will give the avatar a gender eventually. JC
gAgent.setGenderChosen(TRUE);
+
}
-
// Loads a bitmap to display during load
// location_id = 0 => last position
@@ -3990,9 +3994,10 @@ bool LLStartUp::dispatchURL()
return false;
}
-void login_alert_done(S32 option, void* user_data)
+bool login_alert_done(const LLSD& notification, const LLSD& response)
{
LLPanelLogin::giveFocus();
+ return false;
}
diff --git a/indra/newview/llstartup.h b/indra/newview/llstartup.h
index 1639ed55b6..f89642aa2a 100644
--- a/indra/newview/llstartup.h
+++ b/indra/newview/llstartup.h
@@ -38,7 +38,7 @@
bool idle_startup();
std::string load_password_from_disk();
void release_start_screen();
-void login_alert_done(S32 option, void* user_data);
+bool login_alert_done(const LLSD& notification, const LLSD& response);
// constants, variables, & enumerations
extern std::string SCREEN_HOME_FILENAME;
diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp
index 278f7ea9d1..8b274a045b 100644
--- a/indra/newview/llstatusbar.cpp
+++ b/indra/newview/llstatusbar.cpp
@@ -767,7 +767,7 @@ static void onClickBuyCurrency(void* data)
static void onClickHealth(void* )
{
- LLNotifyBox::showXml("NotSafe");
+ LLNotifications::instance().add("NotSafe");
}
static void onClickScriptDebug(void*)
@@ -777,22 +777,22 @@ static void onClickScriptDebug(void*)
static void onClickFly(void* )
{
- LLNotifyBox::showXml("NoFly");
+ LLNotifications::instance().add("NoFly");
}
static void onClickPush(void* )
{
- LLNotifyBox::showXml("PushRestricted");
+ LLNotifications::instance().add("PushRestricted");
}
static void onClickVoice(void* )
{
- LLNotifyBox::showXml("NoVoice");
+ LLNotifications::instance().add("NoVoice");
}
static void onClickBuild(void*)
{
- LLNotifyBox::showXml("NoBuild");
+ LLNotifications::instance().add("NoBuild");
}
static void onClickScripts(void*)
@@ -800,15 +800,15 @@ static void onClickScripts(void*)
LLViewerRegion* region = gAgent.getRegion();
if(region && region->getRegionFlags() & REGION_FLAGS_ESTATE_SKIP_SCRIPTS)
{
- LLNotifyBox::showXml("ScriptsStopped");
+ LLNotifications::instance().add("ScriptsStopped");
}
else if(region && region->getRegionFlags() & REGION_FLAGS_SKIP_SCRIPTS)
{
- LLNotifyBox::showXml("ScriptsNotRunning");
+ LLNotifications::instance().add("ScriptsNotRunning");
}
else
{
- LLNotifyBox::showXml("NoOutsideScripts");
+ LLNotifications::instance().add("NoOutsideScripts");
}
}
diff --git a/indra/newview/lltoolbar.cpp b/indra/newview/lltoolbar.cpp
index d7db0f85d9..b9235a489a 100644
--- a/indra/newview/lltoolbar.cpp
+++ b/indra/newview/lltoolbar.cpp
@@ -307,7 +307,10 @@ void LLToolBar::refresh()
}
gSavedSettings.setBOOL("BuildBtnState", build_mode);
- updateCommunicateList();
+ if (isInVisibleChain())
+ {
+ updateCommunicateList();
+ }
}
void LLToolBar::updateCommunicateList()
@@ -444,7 +447,7 @@ void LLToolBar::onClickChat(void* user_data)
// static
void LLToolBar::onClickAppearance(void*)
{
- if (gAgent.getWearablesLoaded())
+ if (gAgent.areWearablesLoaded())
{
gAgent.changeCameraToCustomizeAvatar();
}
diff --git a/indra/newview/lltoolbrush.cpp b/indra/newview/lltoolbrush.cpp
index 6bdd4e7767..92233c0d9f 100644
--- a/indra/newview/lltoolbrush.cpp
+++ b/indra/newview/lltoolbrush.cpp
@@ -648,9 +648,9 @@ void LLToolBrushLand::alertNoTerraform(LLViewerRegion* regionp)
{
if (!regionp) return;
- LLStringUtil::format_map_t args;
- args["[REGION]"] = regionp->getName();
- gViewerWindow->alertXml("RegionNoTerraforming", args);
+ LLSD args;
+ args["REGION"] = regionp->getName();
+ LLNotifications::instance().add("RegionNoTerraforming", args);
}
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index 25b58e1409..7459a23bef 100644
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -1052,9 +1052,9 @@ BOOL LLToolDragAndDrop::handleDropTextureProtections(LLViewerObject* hit_obj,
if (hit_obj->isInventoryDirty())
{
hit_obj->fetchInventoryFromServer();
- LLStringUtil::format_map_t args;
- args["[ERROR_MESSAGE]"] = "Unable to add texture.\nPlease wait a few seconds and try again.";
- gViewerWindow->alertXml("ErrorMessage", args);
+ LLSD args;
+ args["ERROR_MESSAGE"] = "Unable to add texture.\nPlease wait a few seconds and try again.";
+ LLNotifications::instance().add("ErrorMessage", args);
return FALSE;
}
if (hit_obj->getInventoryItemByAsset(item->getAssetUUID()))
@@ -1505,45 +1505,42 @@ void LLToolDragAndDrop::giveInventory(const LLUUID& to_agent,
else
{
// ask if the agent is sure.
- LLGiveInventoryInfo* info = new LLGiveInventoryInfo(to_agent,
- item->getUUID(),
- im_session_id);
-
- gViewerWindow->alertXml("CannotCopyWarning",
- &LLToolDragAndDrop::handleCopyProtectedItem,
- (void*)info);
+ LLSD payload;
+ payload["agent_id"] = to_agent;
+ payload["item_id"] = item->getUUID();
+ LLNotifications::instance().add("CannotCopyWarning", LLSD(), payload,
+ &LLToolDragAndDrop::handleCopyProtectedItem);
}
}
-
// static
-void LLToolDragAndDrop::handleCopyProtectedItem(S32 option, void* data)
+bool LLToolDragAndDrop::handleCopyProtectedItem(const LLSD& notification, const LLSD& response)
{
- LLGiveInventoryInfo* info = (LLGiveInventoryInfo*)data;
+ S32 option = LLNotification::getSelectedOption(notification, response);
LLInventoryItem* item = NULL;
switch(option)
{
case 0: // "Yes"
- item = gInventory.getItem(info->mInventoryObjectID);
+ item = gInventory.getItem(notification["payload"]["item_id"].asUUID());
if(item)
{
- LLToolDragAndDrop::commitGiveInventoryItem(info->mToAgentID,
- item,
- info->mIMSessionID);
+ LLToolDragAndDrop::commitGiveInventoryItem(notification["payload"]["agent_id"].asUUID(),
+ item);
// delete it for now - it will be deleted on the server
// quickly enough.
- gInventory.deleteObject(info->mInventoryObjectID);
+ gInventory.deleteObject(notification["payload"]["item_id"].asUUID());
gInventory.notifyObservers();
}
else
{
- gViewerWindow->alertXml("CannotGiveItem");
+ LLNotifications::instance().add("CannotGiveItem");
}
break;
default: // no, cancel, whatever, who cares, not yes.
- gViewerWindow->alertXml("TransactionCancelled");
+ LLNotifications::instance().add("TransactionCancelled");
break;
}
+ return false;
}
// static
@@ -1592,7 +1589,7 @@ void LLToolDragAndDrop::commitGiveInventoryItem(const LLUUID& to_agent,
// If this item was given by drag-and-drop into an IM panel, log this action in the IM panel chat.
if (im_session_id != LLUUID::null)
{
- LLStringUtil::format_map_t args;
+ LLSD args;
gIMMgr->addSystemMessage(im_session_id, "inventory_item_offered", args);
}
@@ -1632,18 +1629,18 @@ void LLToolDragAndDrop::giveInventoryCategory(const LLUUID& to_agent,
}
if(!complete)
{
- LLNotifyBox::showXml("IncompleteInventory");
+ LLNotifications::instance().add("IncompleteInventory");
return;
}
count = items.count() + cats.count();
if(count > MAX_ITEMS)
{
- gViewerWindow->alertXml("TooManyItems");
+ LLNotifications::instance().add("TooManyItems");
return;
}
else if(count == 0)
{
- gViewerWindow->alertXml("NoItems");
+ LLNotifications::instance().add("NoItems");
return;
}
else
@@ -1656,29 +1653,29 @@ void LLToolDragAndDrop::giveInventoryCategory(const LLUUID& to_agent,
{
LLGiveInventoryInfo* info = NULL;
info = new LLGiveInventoryInfo(to_agent, cat->getUUID());
- LLStringUtil::format_map_t args;
- args["[COUNT]"] = llformat("%d",giveable.countNoCopy());
- gViewerWindow->alertXml("CannotCopyCountItems", args,
- &LLToolDragAndDrop::handleCopyProtectedCategory,
- (void*)info);
-
+ LLSD args;
+ args["COUNT"] = llformat("%d",giveable.countNoCopy());
+ LLSD payload;
+ payload["agent_id"] = to_agent;
+ payload["folder_id"] = cat->getUUID();
+ LLNotifications::instance().add("CannotCopyCountItems", args, payload, &LLToolDragAndDrop::handleCopyProtectedCategory);
}
}
}
// static
-void LLToolDragAndDrop::handleCopyProtectedCategory(S32 option, void* data)
+bool LLToolDragAndDrop::handleCopyProtectedCategory(const LLSD& notification, const LLSD& response)
{
- LLGiveInventoryInfo* info = (LLGiveInventoryInfo*)data;
+ S32 option = LLNotification::getSelectedOption(notification, response);
LLInventoryCategory* cat = NULL;
switch(option)
{
case 0: // "Yes"
- cat = gInventory.getCategory(info->mInventoryObjectID);
+ cat = gInventory.getCategory(notification["payload"]["folder_id"].asUUID());
if(cat)
{
- LLToolDragAndDrop::commitGiveInventoryCategory(info->mToAgentID,
+ LLToolDragAndDrop::commitGiveInventoryCategory(notification["payload"]["agent_id"].asUUID(),
cat);
LLViewerInventoryCategory::cat_array_t cats;
LLViewerInventoryItem::item_array_t items;
@@ -1697,14 +1694,15 @@ void LLToolDragAndDrop::handleCopyProtectedCategory(S32 option, void* data)
}
else
{
- gViewerWindow->alertXml("CannotGiveCategory");
+ LLNotifications::instance().add("CannotGiveCategory");
}
break;
default: // no, cancel, whatever, who cares, not yes.
- gViewerWindow->alertXml("TransactionCancelled");
+ LLNotifications::instance().add("TransactionCancelled");
break;
}
+ return false;
}
// static
@@ -1731,12 +1729,12 @@ void LLToolDragAndDrop::commitGiveInventoryCategory(const LLUUID& to_agent,
S32 count = items.count() + cats.count();
if(count > MAX_ITEMS)
{
- gViewerWindow->alertXml("TooManyItems");
+ LLNotifications::instance().add("TooManyItems");
return;
}
else if(count == 0)
{
- gViewerWindow->alertXml("NoItems");
+ LLNotifications::instance().add("NoItems");
return;
}
else
@@ -2299,7 +2297,7 @@ EAcceptance LLToolDragAndDrop::dad3dWearItem(
// destroy clothing items.
if (!gAgent.areWearablesLoaded())
{
- gViewerWindow->alertXml("CanNotChangeAppearanceUntilLoaded");
+ LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded");
return ACCEPT_NO;
}
@@ -2394,7 +2392,7 @@ EAcceptance LLToolDragAndDrop::dad3dWearCategory(
// destroy clothing items.
if (!gAgent.areWearablesLoaded())
{
- gViewerWindow->alertXml("CanNotChangeAppearanceUntilLoaded");
+ LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded");
return ACCEPT_NO;
}
}
diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h
index 627ef86c38..462e57b390 100644
--- a/indra/newview/lltooldraganddrop.h
+++ b/indra/newview/lltooldraganddrop.h
@@ -209,13 +209,13 @@ protected:
// give inventory item functionality
- static void handleCopyProtectedItem(S32 option, void* data);
+ static bool handleCopyProtectedItem(const LLSD& notification, const LLSD& response);
static void commitGiveInventoryItem(const LLUUID& to_agent,
LLInventoryItem* item,
const LLUUID &im_session_id = LLUUID::null);
// give inventory category functionality
- static void handleCopyProtectedCategory(S32 option, void* data);
+ static bool handleCopyProtectedCategory(const LLSD& notification, const LLSD& response);
static void commitGiveInventoryCategory(const LLUUID& to_agent,
LLInventoryCategory* cat);
public:
diff --git a/indra/newview/llurldispatcher.cpp b/indra/newview/llurldispatcher.cpp
index 477146a473..3f6227ee56 100644
--- a/indra/newview/llurldispatcher.cpp
+++ b/indra/newview/llurldispatcher.cpp
@@ -43,7 +43,6 @@
#include "llpanellogin.h"
#include "llstartup.h" // gStartupState
#include "llurlsimstring.h"
-#include "llviewerwindow.h" // alertXml()
#include "llweb.h"
#include "llworldmap.h"
@@ -147,8 +146,8 @@ bool LLURLDispatcherImpl::dispatchCore(const std::string& url,
/*
// Inform the user we can't handle this
std::map<std::string, std::string> args;
- args["[SLURL]"] = url;
- gViewerWindow->alertXml("BadURL", args);
+ args["SLURL"] = url;
+ r;
*/
return false;
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index c28ed7c435..e52b3a9b83 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -403,7 +403,7 @@ void LLViewerInventoryCategory::updateServer(BOOL is_new) const
// communicate that change with the server.
if(LLAssetType::AT_NONE != mPreferredType)
{
- LLNotifyBox::showXml("CannotModifyProtectedCategories");
+ LLNotifications::instance().add("CannotModifyProtectedCategories");
return;
}
@@ -427,7 +427,7 @@ void LLViewerInventoryCategory::removeFromServer( void )
// communicate that change with the server.
if(LLAssetType::AT_NONE != mPreferredType)
{
- LLNotifyBox::showXml("CannotRemoveProtectedCategories");
+ LLNotifications::instance().add("CannotRemoveProtectedCategories");
return;
}
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index c8ad7fad97..5131b77a7c 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -1,3 +1,4 @@
+
/**
* @file llviewermenu.cpp
* @brief Builds menus out of items.
@@ -309,7 +310,7 @@ BOOL is_selection_buy_not_take();
S32 selection_price();
BOOL enable_take();
void handle_take();
-void confirm_take(S32 option, void* data);
+bool confirm_take(const LLSD& notification, const LLSD& response);
BOOL enable_buy(void*);
void handle_buy(void *);
void handle_buy_object(LLSaleInfo sale_info);
@@ -999,6 +1000,7 @@ void init_debug_world_menu(LLMenuGL* menu)
void handle_export_menus_to_xml(void*)
{
+
LLFilePicker& picker = LLFilePicker::instance();
if(!picker.getSaveFile(LLFilePicker::FFSAVE_XML))
{
@@ -2122,9 +2124,10 @@ class LLGoToObject : public view_listener_t
//---------------------------------------------------------------------------
// Parcel freeze, eject, etc.
//---------------------------------------------------------------------------
-void callback_freeze(S32 option, void* data)
+bool callback_freeze(const LLSD& notification, const LLSD& response)
{
- LLUUID* avatar_id = (LLUUID*) data;
+ LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID();
+ S32 option = LLNotification::getSelectedOption(notification, response);
if (0 == option || 1 == option)
{
@@ -2136,7 +2139,7 @@ void callback_freeze(S32 option, void* data)
}
LLMessageSystem* msg = gMessageSystem;
- LLViewerObject* avatar = gObjectList.findObject(*avatar_id);
+ LLViewerObject* avatar = gObjectList.findObject(avatar_id);
if (avatar)
{
@@ -2145,16 +2148,15 @@ void callback_freeze(S32 option, void* data)
msg->addUUID("AgentID", gAgent.getID());
msg->addUUID("SessionID", gAgent.getSessionID());
msg->nextBlock("Data");
- msg->addUUID("TargetID", *avatar_id );
+ msg->addUUID("TargetID", avatar_id );
msg->addU32("Flags", flags );
msg->sendReliable( avatar->getRegion()->getHost() );
}
}
-
- delete avatar_id;
- avatar_id = NULL;
+ return false;
}
+
class LLAvatarFreeze : public view_listener_t
{
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
@@ -2162,23 +2164,25 @@ class LLAvatarFreeze : public view_listener_t
LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
if( avatar )
{
- LLUUID* avatar_id = new LLUUID( avatar->getID() );
std::string fullname = avatar->getFullname();
+ LLSD payload;
+ payload["avatar_id"] = avatar->getID();
if (!fullname.empty())
{
- LLStringUtil::format_map_t args;
- args["[AVATAR_NAME]"] = fullname;
- gViewerWindow->alertXml("FreezeAvatarFullname",
+ LLSD args;
+ args["AVATAR_NAME"] = fullname;
+ LLNotifications::instance().add("FreezeAvatarFullname",
args,
- callback_freeze,
- (void*)avatar_id);
+ payload,
+ callback_freeze);
}
else
{
- gViewerWindow->alertXml("FreezeAvatar",
- callback_freeze,
- (void*)avatar_id);
+ LLNotifications::instance().add("FreezeAvatar",
+ LLSD(),
+ payload,
+ callback_freeze);
}
}
return true;
@@ -2224,26 +2228,16 @@ class LLAvatarDebug : public view_listener_t
}
};
-struct MenuCallbackData
+bool callback_eject(const LLSD& notification, const LLSD& response)
{
- bool ban_enabled;
- LLUUID avatar_id;
-};
-
-void callback_eject(S32 option, void* data)
-{
- MenuCallbackData *callback_data = (MenuCallbackData*)data;
- if (!callback_data)
- {
- return;
- }
+ S32 option = LLNotification::getSelectedOption(notification, response);
if (2 == option)
{
- // Cancle button.
- return;
+ // Cancel button.
+ return false;
}
- LLUUID avatar_id = callback_data->avatar_id;
- bool ban_enabled = callback_data->ban_enabled;
+ LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID();
+ bool ban_enabled = notification["payload"]["ban_enabled"].asBoolean();
if (0 == option)
{
@@ -2285,10 +2279,7 @@ void callback_eject(S32 option, void* data)
msg->sendReliable( avatar->getRegion()->getHost() );
}
}
-
-
- delete callback_data;
- callback_data = NULL;
+ return false;
}
class LLAvatarEject : public view_listener_t
@@ -2298,8 +2289,8 @@ class LLAvatarEject : public view_listener_t
LLVOAvatar* avatar = find_avatar_from_object( LLSelectMgr::getInstance()->getSelection()->getPrimaryObject() );
if( avatar )
{
- MenuCallbackData *data = new MenuCallbackData;
- (*data).avatar_id = avatar->getID();
+ LLSD payload;
+ payload["avatar_id"] = avatar->getID();
std::string fullname = avatar->getFullname();
const LLVector3d& pos = avatar->getPositionGlobal();
@@ -2307,40 +2298,42 @@ class LLAvatarEject : public view_listener_t
if (LLViewerParcelMgr::getInstance()->isParcelOwnedByAgent(parcel,GP_LAND_MANAGE_BANNED))
{
- (*data).ban_enabled = true;
+ payload["ban_enabled"] = true;
if (!fullname.empty())
{
- LLStringUtil::format_map_t args;
- args["[AVATAR_NAME]"] = fullname;
- gViewerWindow->alertXml("EjectAvatarFullname",
- args,
- callback_eject,
- (void*)data);
+ LLSD args;
+ args["AVATAR_NAME"] = fullname;
+ LLNotifications::instance().add("EjectAvatarFullname",
+ args,
+ payload,
+ callback_eject);
}
else
{
- gViewerWindow->alertXml("EjectAvatar",
- callback_eject,
- (void*)data);
+ LLNotifications::instance().add("EjectAvatarFullname",
+ LLSD(),
+ payload,
+ callback_eject);
}
}
else
{
- (*data).ban_enabled = false;
+ payload["ban_enabled"] = false;
if (!fullname.empty())
{
- LLStringUtil::format_map_t args;
- args["[AVATAR_NAME]"] = fullname;
- gViewerWindow->alertXml("EjectAvatarFullnameNoBan",
- args,
- callback_eject,
- (void*)data);
+ LLSD args;
+ args["AVATAR_NAME"] = fullname;
+ LLNotifications::instance().add("EjectAvatarFullnameNoBan",
+ args,
+ payload,
+ callback_eject);
}
else
{
- gViewerWindow->alertXml("EjectAvatarNoBan",
- callback_eject,
- (void*)data);
+ LLNotifications::instance().add("EjectAvatarNoBan",
+ LLSD(),
+ payload,
+ callback_eject);
}
}
}
@@ -2387,13 +2380,16 @@ class LLAvatarGiveCard : public view_listener_t
if(dest && dest->isAvatar())
{
bool found_name = false;
- LLStringUtil::format_map_t args;
+ LLSD args;
+ LLSD old_args;
LLNameValue* nvfirst = dest->getNVPair("FirstName");
LLNameValue* nvlast = dest->getNVPair("LastName");
if(nvfirst && nvlast)
{
- args["[FIRST]"] = nvfirst->getString();
- args["[LAST]"] = nvlast->getString();
+ args["FIRST"] = nvfirst->getString();
+ args["LAST"] = nvlast->getString();
+ old_args["FIRST"] = nvfirst->getString();
+ old_args["LAST"] = nvlast->getString();
found_name = true;
}
LLViewerRegion* region = dest->getRegion();
@@ -2415,11 +2411,11 @@ class LLAvatarGiveCard : public view_listener_t
transaction_id.generate();
msg->addUUIDFast(_PREHASH_TransactionID, transaction_id);
msg->sendReliable(dest_host);
- LLNotifyBox::showXml("OfferedCard", args);
+ LLNotifications::instance().add("OfferedCard", args);
}
else
{
- gViewerWindow->alertXml("CantOfferCallingCard", args);
+ LLNotifications::instance().add("CantOfferCallingCard", old_args);
}
}
return true;
@@ -2436,8 +2432,9 @@ void login_done(S32 which, void *user)
}
-void callback_leave_group(S32 option, void *userdata)
+bool callback_leave_group(const LLSD& notification, const LLSD& response)
{
+ S32 option = LLNotification::getSelectedOption(notification, response);
if (option == 0)
{
LLMessageSystem *msg = gMessageSystem;
@@ -2450,15 +2447,16 @@ void callback_leave_group(S32 option, void *userdata)
msg->addUUIDFast(_PREHASH_GroupID, gAgent.mGroupID );
gAgent.sendReliableMessage();
}
+ return false;
}
void handle_leave_group(void *)
{
if (gAgent.getGroupID() != LLUUID::null)
{
- LLStringUtil::format_map_t args;
- args["[GROUP]"] = gAgent.mGroupName;
- gViewerWindow->alertXml("GroupLeaveConfirmMember", args, callback_leave_group);
+ LLSD args;
+ args["GROUP"] = gAgent.mGroupName;
+ LLNotifications::instance().add("GroupLeaveConfirmMember", args, LLSD(), callback_leave_group);
}
}
@@ -2521,7 +2519,7 @@ void handle_buy_object(LLSaleInfo sale_info)
{
if(!LLSelectMgr::getInstance()->selectGetAllRootsValid())
{
- LLNotifyBox::showXml("UnableToBuyWhileDownloading");
+ LLNotifications::instance().add("UnableToBuyWhileDownloading");
return;
}
@@ -2530,7 +2528,7 @@ void handle_buy_object(LLSaleInfo sale_info)
BOOL owners_identical = LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name);
if (!owners_identical)
{
- LLNotifyBox::showXml("CannotBuyObjectsFromDifferentOwners");
+ LLNotifications::instance().add("CannotBuyObjectsFromDifferentOwners");
return;
}
@@ -2540,7 +2538,7 @@ void handle_buy_object(LLSaleInfo sale_info)
valid &= LLSelectMgr::getInstance()->selectGetAggregatePermissions(ag_perm);
if(!valid || !sale_info.isForSale() || !perm.allowTransferTo(gAgent.getID()))
{
- LLNotifyBox::showXml("ObjectNotForSale");
+ LLNotifications::instance().add("ObjectNotForSale");
return;
}
@@ -2686,22 +2684,22 @@ void set_god_level(U8 god_level)
// inventory in items may change in god mode
gObjectList.dirtyAllObjectInventory();
- if(gViewerWindow)
- {
- gViewerWindow->setMenuBackgroundColor(god_level > GOD_NOT,
+ if(gViewerWindow)
+ {
+ gViewerWindow->setMenuBackgroundColor(god_level > GOD_NOT,
LLViewerLogin::getInstance()->isInProductionGrid());
- }
-
- LLStringUtil::format_map_t args;
+ }
+
+ LLSD args;
if(god_level > GOD_NOT)
{
- args["[LEVEL]"] = llformat("%d",(S32)god_level);
- LLNotifyBox::showXml("EnteringGodMode", args);
+ args["LEVEL"] = llformat("%d",(S32)god_level);
+ LLNotifications::instance().add("EnteringGodMode", args);
}
else
{
- args["[LEVEL]"] = llformat("%d",(S32)old_god_level);
- LLNotifyBox::showXml("LeavingGodMode", args);
+ args["LEVEL"] = llformat("%d",(S32)old_god_level);
+ LLNotifications::instance().add("LeavingGodMode", args);
}
@@ -2826,13 +2824,13 @@ void request_friendship(const LLUUID& dest_id)
if(dest && dest->isAvatar())
{
std::string fullname;
- LLStringUtil::format_map_t args;
+ LLSD args;
LLNameValue* nvfirst = dest->getNVPair("FirstName");
LLNameValue* nvlast = dest->getNVPair("LastName");
if(nvfirst && nvlast)
{
- args["[FIRST]"] = nvfirst->getString();
- args["[LAST]"] = nvlast->getString();
+ args["FIRST"] = nvfirst->getString();
+ args["LAST"] = nvlast->getString();
fullname = nvfirst->getString();
fullname += " ";
fullname += nvlast->getString();
@@ -2843,7 +2841,7 @@ void request_friendship(const LLUUID& dest_id)
}
else
{
- gViewerWindow->alertXml("CantOfferFriendship");
+ LLNotifications::instance().add("CantOfferFriendship");
}
}
}
@@ -2853,12 +2851,8 @@ class LLEditEnableCustomizeAvatar : public view_listener_t
{
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
{
- LLVOAvatar* avatar = gAgent.getAvatarObject();
-
- bool enabled = ((avatar && avatar->isFullyLoaded()) &&
- (gAgent.getWearablesLoaded()));
-
- gMenuHolder->findControl(userdata["control"].asString())->setValue(enabled);
+ bool new_value = gAgent.areWearablesLoaded();
+ gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
return true;
}
};
@@ -3184,7 +3178,7 @@ void disabled_duplicate(void*)
{
if (LLSelectMgr::getInstance()->getSelection()->getPrimaryObject())
{
- LLNotifyBox::showXml("CopyFailed");
+ LLNotifications::instance().add("CopyFailed");
}
}
@@ -3317,7 +3311,7 @@ void handle_claim_public_land(void*)
{
if (LLViewerParcelMgr::getInstance()->getSelectionRegion() != gAgent.getRegion())
{
- LLNotifyBox::showXml("ClaimPublicLand");
+ LLNotifications::instance().add("ClaimPublicLand");
return;
}
@@ -3550,7 +3544,7 @@ void derez_objects(EDeRezDestination dest, const LLUUID& dest_id)
}
else if(!error.empty())
{
- gViewerWindow->alertXml(error);
+ LLNotifications::instance().add(error);
}
}
@@ -3577,16 +3571,13 @@ class LLObjectReturn : public view_listener_t
mObjectSelection = LLSelectMgr::getInstance()->getEditSelection();
- gViewerWindow->alertXml("ReturnToOwner",
- onReturnToOwner,
- (void*)this);
+ LLNotifications::instance().add("ReturnToOwner", LLSD(), LLSD(), boost::bind(&LLObjectReturn::onReturnToOwner, this, _1, _2));
return true;
}
- static void onReturnToOwner(S32 option, void* data)
+ bool onReturnToOwner(const LLSD& notification, const LLSD& response)
{
- LLObjectReturn* object_return = (LLObjectReturn*)data;
-
+ S32 option = LLNotification::getSelectedOption(notification, response);
if (0 == option)
{
// Ignore category ID for this derez destination.
@@ -3594,7 +3585,8 @@ class LLObjectReturn : public view_listener_t
}
// drop reference to current selection
- object_return->mObjectSelection = NULL;
+ mObjectSelection = NULL;
+ return false;
}
protected:
@@ -3731,48 +3723,46 @@ void handle_take()
{
category_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_OBJECT);
}
- LLUUID* cat_id = new LLUUID(category_id);
+ LLSD payload;
+ payload["folder_id"] = category_id;
+
+ LLNotification::Params params("ConfirmObjectTakeLock");
+ params.payload(payload)
+ .functor(confirm_take);
+
if(locked_but_takeable_object ||
!you_own_everything)
{
if(locked_but_takeable_object && you_own_everything)
{
- gViewerWindow->alertXml("ConfirmObjectTakeLock",
- confirm_take,
- (void*)cat_id);
+ params.name("ConfirmObjectTakeLock");
}
else if(!locked_but_takeable_object && !you_own_everything)
{
- gViewerWindow->alertXml("ConfirmObjectTakeNoOwn",
- confirm_take,
- (void*)cat_id);
+ params.name("ConfirmObjectTakeNoOwn");
}
else
{
- gViewerWindow->alertXml("ConfirmObjectTakeLockNoOwn",
- confirm_take,
- (void*)cat_id);
+ params.name("ConfirmObjectTakeLockNoOwn");
}
-
-
+
+ LLNotifications::instance().add(params);
}
-
else
{
- confirm_take(0, (void*)cat_id);
+ LLNotifications::instance().forceResponse(params, 0);
}
}
-void confirm_take(S32 option, void* data)
+bool confirm_take(const LLSD& notification, const LLSD& response)
{
- LLUUID* cat_id = (LLUUID*)data;
- if(!cat_id) return;
+ S32 option = LLNotification::getSelectedOption(notification, response);
if(enable_take() && (option == 0))
{
- derez_objects(DRD_TAKE_INTO_AGENT_INVENTORY, *cat_id);
+ derez_objects(DRD_TAKE_INTO_AGENT_INVENTORY, notification["payload"]["folder_id"].asUUID());
}
- delete cat_id;
+ return false;
}
// You can take an item when it is public and transferrable, or when
@@ -3934,13 +3924,15 @@ S32 selection_price()
return total_price;
}
-void callback_show_buy_currency(S32 option, void*)
+bool callback_show_buy_currency(const LLSD& notification, const LLSD& response)
{
+ S32 option = LLNotification::getSelectedOption(notification, response);
if (0 == option)
{
llinfos << "Loading page " << BUY_CURRENCY_URL << llendl;
LLWeb::loadURL(BUY_CURRENCY_URL);
}
+ return false;
}
@@ -3955,14 +3947,13 @@ void show_buy_currency(const char* extra)
}
mesg << "Go to " << BUY_CURRENCY_URL << "\nfor information on purchasing currency?";
- LLStringUtil::format_map_t args;
+ LLSD args;
if (extra != NULL)
{
- args["[EXTRA]"] = extra;
+ args["EXTRA"] = extra;
}
- args["[URL]"] = BUY_CURRENCY_URL;
- gViewerWindow->alertXml("PromptGoToCurrencyPage", args,
- callback_show_buy_currency);
+ args["URL"] = BUY_CURRENCY_URL;
+ LLNotifications::instance().add("PromptGoToCurrencyPage", args, LLSD(), callback_show_buy_currency);
}
void handle_buy_currency(void*)
@@ -4142,29 +4133,29 @@ class LLToolsLink : public view_listener_t
{
if(!LLSelectMgr::getInstance()->selectGetAllRootsValid())
{
- LLNotifyBox::showXml("UnableToLinkWhileDownloading");
+ LLNotifications::instance().add("UnableToLinkWhileDownloading");
return true;
}
S32 object_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount();
if (object_count > MAX_CHILDREN_PER_TASK + 1)
{
- LLStringUtil::format_map_t args;
- args["[COUNT]"] = llformat("%d", object_count);
+ LLSD args;
+ args["COUNT"] = llformat("%d", object_count);
int max = MAX_CHILDREN_PER_TASK+1;
- args["[MAX]"] = llformat("%d", max);
- gViewerWindow->alertXml("UnableToLinkObjects", args);
+ args["MAX"] = llformat("%d", max);
+ LLNotifications::instance().add("UnableToLinkObjects", args);
return true;
}
if(LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() < 2)
{
- gViewerWindow->alertXml("CannotLinkIncompleteSet");
+ LLNotifications::instance().add("CannotLinkIncompleteSet");
return true;
}
if(!LLSelectMgr::getInstance()->selectGetRootsModify())
{
- gViewerWindow->alertXml("CannotLinkModify");
+ LLNotifications::instance().add("CannotLinkModify");
return true;
}
LLUUID owner_id;
@@ -4174,7 +4165,7 @@ class LLToolsLink : public view_listener_t
// we don't actually care if you're the owner, but novices are
// the most likely to be stumped by this one, so offer the
// easiest and most likely solution.
- gViewerWindow->alertXml("CannotLinkDifferentOwners");
+ LLNotifications::instance().add("CannotLinkDifferentOwners");
return true;
}
LLSelectMgr::getInstance()->sendLink();
@@ -4738,7 +4729,7 @@ class LLWorldSetBusy : public view_listener_t
else
{
gAgent.setBusy();
- gViewerWindow->alertXml("BusyModeSet");
+ LLNotifications::instance().add("BusyModeSet");
}
return true;
}
@@ -4764,7 +4755,7 @@ class LLWorldCreateLandmark : public view_listener_t
if (!agent_parcel->getAllowLandmark()
&& !LLViewerParcelMgr::isParcelOwnedByAgent(agent_parcel, GP_LAND_ALLOW_LANDMARK))
{
- gViewerWindow->alertXml("CannotCreateLandmarkNotOwner");
+ LLNotifications::instance().add("CannotCreateLandmarkNotOwner");
return true;
}
@@ -4871,16 +4862,14 @@ class LLAvatarAddFriend : public view_listener_t
}
};
-void complete_give_money(S32 option, void* user_data)
+bool complete_give_money(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle handle)
{
+ S32 option = LLNotification::getSelectedOption(notification, response);
if (option == 0)
{
gAgent.clearBusy();
}
- LLObjectSelectionHandle handle(*(LLObjectSelectionHandle*)user_data);
- delete (LLObjectSelectionHandle*)user_data;
-
LLViewerObject* objectp = handle->getPrimaryObject();
// Show avatar's name if paying attachment
@@ -4906,19 +4895,22 @@ void complete_give_money(S32 option, void* user_data)
LLFloaterPay::payViaObject(&give_money, objectp->getID());
}
}
+ return false;
}
bool handle_give_money_dialog()
{
- LLObjectSelectionHandle* handlep = new LLObjectSelectionHandle(LLSelectMgr::getInstance()->getSelection());
+ LLNotification::Params params("BusyModePay");
+ params.functor(boost::bind(complete_give_money, _1, _2, LLSelectMgr::getInstance()->getSelection()));
+
if (gAgent.getBusy())
{
// warn users of being in busy mode during a transaction
- gViewerWindow->alertXml("BusyModePay", complete_give_money, handlep);
+ LLNotifications::instance().add(params);
}
else
{
- complete_give_money(1, handlep);
+ LLNotifications::instance().forceResponse(params, 1);
}
return true;
}
@@ -5069,7 +5061,7 @@ class LLShowFloater : public view_listener_t
}
else if (floater_name == "appearance")
{
- if (gAgent.getWearablesLoaded())
+ if (gAgent.areWearablesLoaded())
{
gAgent.changeCameraToCustomizeAvatar();
}
@@ -5272,14 +5264,14 @@ class LLFloaterVisible : public view_listener_t
}
};
-void callback_show_url(S32 option, void* data)
+bool callback_show_url(const LLSD& notification, const LLSD& response)
{
- std::string* urlp = (std::string*)data;
+ S32 option = LLNotification::getSelectedOption(notification, response);
if (0 == option)
{
- LLWeb::loadURL(*urlp);
+ LLWeb::loadURL(notification["payload"]["url"].asString());
}
- delete urlp;
+ return false;
}
class LLPromptShowURL : public view_listener_t
@@ -5292,15 +5284,16 @@ class LLPromptShowURL : public view_listener_t
{
std::string alert = param.substr(0, offset);
std::string url = param.substr(offset+1);
- std::string* url_copy = new std::string(url);
if(gSavedSettings.getBOOL("UseExternalBrowser"))
{
- gViewerWindow->alertXml(alert, callback_show_url, url_copy);
+ LLSD payload;
+ payload["url"] = url;
+ LLNotifications::instance().add(alert, LLSD(), payload, callback_show_url);
}
else
{
- callback_show_url(0, url_copy);
+ LLWeb::loadURL(url);
}
}
else
@@ -5311,6 +5304,39 @@ class LLPromptShowURL : public view_listener_t
}
};
+bool callback_show_file(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ if (0 == option)
+ {
+ LLWeb::loadURL(notification["payload"]["url"]);
+ }
+ return false;
+}
+
+class LLPromptShowFile : public view_listener_t
+{
+ bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
+ {
+ std::string param = userdata.asString();
+ std::string::size_type offset = param.find(",");
+ if (offset != param.npos)
+ {
+ std::string alert = param.substr(0, offset);
+ std::string file = param.substr(offset+1);
+
+ LLSD payload;
+ payload["url"] = file;
+ LLNotifications::instance().add(alert, LLSD(), payload, callback_show_file);
+ }
+ else
+ {
+ llinfos << "PromptShowFile invalid parameters! Expecting \"ALERT,FILE\"." << llendl;
+ }
+ return true;
+ }
+};
+
class LLShowAgentProfile : public view_listener_t
{
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
@@ -5940,11 +5966,11 @@ void queue_actions(LLFloaterScriptQueue* q, const std::string& noscriptmsg, cons
{
if ( !func.scripted )
{
- gViewerWindow->alertXml(noscriptmsg);
+ LLNotifications::instance().add(noscriptmsg);
}
else if ( !func.modifiable )
{
- gViewerWindow->alertXml(nomodmsg);
+ LLNotifications::instance().add(nomodmsg);
}
else
{
@@ -6933,7 +6959,7 @@ void handle_save_to_xml(void*)
LLFloater* frontmost = gFloaterView->getFrontmost();
if (!frontmost)
{
- gViewerWindow->alertXml("NoFrontmostFloater");
+ LLNotifications::instance().add("NoFrontmostFloater");
return;
}
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index 33c21b4061..5f42aff526 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -178,9 +178,9 @@ const std::string upload_pick(void* data)
std::string short_name = gDirUtilp->getBaseFileName(filename);
// No extension
- LLStringUtil::format_map_t args;
- args["[FILE]"] = short_name;
- gViewerWindow->alertXml("NoFileExtension", args);
+ LLSD args;
+ args["FILE"] = short_name;
+ LLNotifications::instance().add("NoFileExtension", args);
return std::string();
}
else
@@ -220,11 +220,11 @@ const std::string upload_pick(void* data)
{
//should only get here if the extension exists
//but is invalid
- LLStringUtil::format_map_t args;
- args["[EXTENSION]"] = ext;
- args["[VALIDS]"] = valid_extensions;
- gViewerWindow->alertXml("InvalidFileExtension", args);
- return std::string();
+ LLSD args;
+ args["EXTENSION"] = ext;
+ args["VALIDS"] = valid_extensions;
+ LLNotifications::instance().add("InvalidFileExtension", args);
+ return NULL;
}
}//end else (non-null extension)
@@ -239,9 +239,9 @@ const std::string upload_pick(void* data)
if (check_for_invalid_wav_formats(filename,error_msg))
{
llinfos << error_msg << ": " << filename << llendl;
- LLStringUtil::format_map_t args;
- args["[FILE]"] = filename;
- gViewerWindow->alertXml( error_msg, args );
+ LLSD args;
+ args["FILE"] = filename;
+ LLNotifications::instance().add( error_msg, args );
return std::string();
}
}//end if a wave/sound file
@@ -337,10 +337,10 @@ class LLFileUploadBulk : public view_listener_t
}
};
-void upload_error(const std::string& error_message, const std::string& label, const std::string& filename, const LLStringUtil::format_map_t args)
+void upload_error(const std::string& error_message, const std::string& label, const std::string& filename, const LLSD& args)
{
llwarns << error_message << llendl;
- gViewerWindow->alertXml(label, args);
+ LLNotifications::instance().add(label, args);
if(LLFile::remove(filename) == -1)
{
lldebugs << "unable to remove temp file" << llendl;
@@ -531,10 +531,9 @@ void upload_new_resource(const std::string& src_filename, std::string name,
LLTransactionID tid;
LLAssetID uuid;
- LLStringUtil::format_map_t args;
+ LLSD args;
std::string exten = gDirUtilp->getExtension(src_filename);
-
LLAssetType::EType asset_type = LLAssetType::AT_NONE;
std::string error_message;
@@ -548,7 +547,7 @@ void upload_new_resource(const std::string& src_filename, std::string name,
error_message = llformat(
"No file extension for the file: '%s'\nPlease make sure the file has a correct file extension",
short_name.c_str());
- args["[FILE]"] = short_name;
+ args["FILE"] = short_name;
upload_error(error_message, "NofileExtension", filename, args);
return;
}
@@ -560,9 +559,9 @@ void upload_new_resource(const std::string& src_filename, std::string name,
IMG_CODEC_BMP ))
{
error_message = llformat( "Problem with file %s:\n\n%s\n",
- src_filename.c_str(), LLImage::getLastError().c_str());
- args["[FILE]"] = src_filename;
- args["[ERROR]"] = LLImage::getLastError();
+ src_filename.c_str(), LLImage::getLastError().c_str());
+ args["FILE"] = src_filename;
+ args["ERROR"] = LLImage::getLastError();
upload_error(error_message, "ProblemWithFile", filename, args);
return;
}
@@ -576,8 +575,8 @@ void upload_new_resource(const std::string& src_filename, std::string name,
{
error_message = llformat("Problem with file %s:\n\n%s\n",
src_filename.c_str(), LLImage::getLastError().c_str());
- args["[FILE]"] = src_filename;
- args["[ERROR]"] = LLImage::getLastError();
+ args["FILE"] = src_filename;
+ args["ERROR"] = LLImage::getLastError();
upload_error(error_message, "ProblemWithFile", filename, args);
return;
}
@@ -591,8 +590,8 @@ void upload_new_resource(const std::string& src_filename, std::string name,
{
error_message = llformat("Problem with file %s:\n\n%s\n",
src_filename.c_str(), LLImage::getLastError().c_str());
- args["[FILE]"] = src_filename;
- args["[ERROR]"] = LLImage::getLastError();
+ args["FILE"] = src_filename;
+ args["ERROR"] = LLImage::getLastError();
upload_error(error_message, "ProblemWithFile", filename, args);
return;
}
@@ -606,8 +605,8 @@ void upload_new_resource(const std::string& src_filename, std::string name,
{
error_message = llformat("Problem with file %s:\n\n%s\n",
src_filename.c_str(), LLImage::getLastError().c_str());
- args["[FILE]"] = src_filename;
- args["[ERROR]"] = LLImage::getLastError();
+ args["FILE"] = src_filename;
+ args["ERROR"] = LLImage::getLastError();
upload_error(error_message, "ProblemWithFile", filename, args);
return;
}
@@ -627,13 +626,13 @@ void upload_new_resource(const std::string& src_filename, std::string name,
{
case LLVORBISENC_DEST_OPEN_ERR:
error_message = llformat( "Couldn't open temporary compressed sound file for writing: %s\n", filename.c_str());
- args["[FILE]"] = filename;
+ args["FILE"] = filename;
upload_error(error_message, "CannotOpenTemporarySoundFile", filename, args);
break;
default:
error_message = llformat("Unknown vorbis encode failure on: %s\n", src_filename.c_str());
- args["[FILE]"] = src_filename;
+ args["FILE"] = src_filename;
upload_error(error_message, "UnknownVorbisEncodeFailure", filename, args);
break;
}
@@ -675,7 +674,7 @@ void upload_new_resource(const std::string& src_filename, std::string name,
{
fclose(in);
error_message = llformat("corrupt resource file: %s", src_filename.c_str());
- args["[FILE]"] = src_filename;
+ args["FILE"] = src_filename;
upload_error(error_message, "CorruptResourceFile", filename, args);
return;
}
@@ -703,7 +702,7 @@ void upload_new_resource(const std::string& src_filename, std::string name,
{
fclose(in);
error_message = llformat("unknown linden resource file version in file: %s", src_filename.c_str());
- args["[FILE]"] = src_filename;
+ args["FILE"] = src_filename;
upload_error(error_message, "UnknownResourceFileVersion", filename, args);
return;
}
@@ -745,7 +744,7 @@ void upload_new_resource(const std::string& src_filename, std::string name,
{
fclose(in);
error_message = llformat( "Unable to create output file: %s", filename.c_str());
- args["[FILE]"] = filename;
+ args["FILE"] = filename;
upload_error(error_message, "UnableToCreateOutputFile", filename, args);
return;
}
@@ -815,9 +814,9 @@ void upload_new_resource(const std::string& src_filename, std::string name,
else
{
llwarns << error_message << llendl;
- LLStringUtil::format_map_t args;
- args["[ERROR_MESSAGE]"] = error_message;
- gViewerWindow->alertXml("ErrorMessage", args);
+ LLSD args;
+ args["ERROR_MESSAGE"] = error_message;
+ LLNotifications::instance().add("ErrorMessage", args);
if(LLFile::remove(filename) == -1)
{
lldebugs << "unable to remove temp file" << llendl;
@@ -900,10 +899,10 @@ void upload_done_callback(const LLUUID& uuid, void* user_data, S32 result, LLExt
}
else // if(result >= 0)
{
- LLStringUtil::format_map_t args;
- args["[FILE]"] = LLInventoryType::lookupHumanReadable(data->mInventoryType);
- args["[REASON]"] = std::string(LLAssetStorage::getErrorString(result));
- gViewerWindow->alertXml("CannotUploadReason", args);
+ LLSD args;
+ args["FILE"] = LLInventoryType::lookupHumanReadable(data->mInventoryType);
+ args["REASON"] = std::string(LLAssetStorage::getErrorString(result));
+ LLNotifications::instance().add("CannotUploadReason", args);
}
LLUploadDialog::modalUploadFinished();
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index e38ef27cf1..daab3a7847 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -96,6 +96,7 @@
#include "llmenugl.h"
#include "llmutelist.h"
#include "llnetmap.h"
+#include "llnotifications.h"
#include "llnotify.h"
#include "llpanelgrouplandmoney.h"
#include "llselectmgr.h"
@@ -157,7 +158,6 @@ extern BOOL gDebugClicks;
// function prototypes
void open_offer(const std::vector<LLUUID>& items, const std::string& from_name);
-void friendship_offer_callback(S32 option, void* user_data);
bool check_offer_throttle(const std::string& from_name, bool check_only);
void callbackCacheEstateOwnerName(const LLUUID& id,
const std::string& first, const std::string& last,
@@ -184,14 +184,66 @@ const std::string SCRIPT_QUESTIONS[SCRIPT_PERMISSION_EOF] =
"ControlYourCamera"
};
-struct LLFriendshipOffer
+const BOOL SCRIPT_QUESTION_IS_CAUTION[SCRIPT_PERMISSION_EOF] =
{
- LLUUID mFromID;
- LLUUID mTransactionID;
- BOOL mOnline;
- LLHost mHost;
+ TRUE, // ScriptTakeMoney,
+ FALSE, // ActOnControlInputs
+ FALSE, // RemapControlInputs
+ FALSE, // AnimateYourAvatar
+ FALSE, // AttachToYourAvatar
+ FALSE, // ReleaseOwnership,
+ FALSE, // LinkAndDelink,
+ FALSE, // AddAndRemoveJoints
+ FALSE, // ChangePermissions
+ FALSE, // TrackYourCamera,
+ FALSE // ControlYourCamera
};
+bool friendship_offer_callback(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ LLUUID fid;
+ LLMessageSystem* msg = gMessageSystem;
+ const LLSD& payload = notification["payload"];
+ switch(option)
+ {
+ case 0:
+ // accept
+ LLAvatarTracker::formFriendship(payload["from_id"]);
+
+ fid = gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD);
+
+ // This will also trigger an onlinenotification if the user is online
+ msg->newMessageFast(_PREHASH_AcceptFriendship);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_TransactionBlock);
+ msg->addUUIDFast(_PREHASH_TransactionID, payload["session_id"]);
+ msg->nextBlockFast(_PREHASH_FolderData);
+ msg->addUUIDFast(_PREHASH_FolderID, fid);
+ msg->sendReliable(LLHost(payload["sender"].asString()));
+ break;
+ case 1:
+ // decline
+ msg->newMessageFast(_PREHASH_DeclineFriendship);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_TransactionBlock);
+ msg->addUUIDFast(_PREHASH_TransactionID, payload["session_id"]);
+ msg->sendReliable(LLHost(payload["sender"].asString()));
+ break;
+ default:
+ // close button probably, possibly timed out
+ break;
+ }
+
+ return false;
+}
+static LLNotificationFunctorRegistration friendship_offer_callback_reg("OfferFriendship", friendship_offer_callback);
+static LLNotificationFunctorRegistration friendship_offer_callback_reg_nm("OfferFriendshipNoMessage", friendship_offer_callback);
+
//const char BUSY_AUTO_RESPONSE[] = "The Resident you messaged is in 'busy mode' which means they have "
// "requested not to be disturbed. Your message will still be shown in their IM "
// "panel for later viewing.";
@@ -563,34 +615,31 @@ void send_sound_trigger(const LLUUID& sound_id, F32 gain)
gAgent.sendMessage();
}
-struct LLJoinGroupData
-{
- LLUUID mGroupID;
- LLUUID mTransactionID;
- std::string mName;
- std::string mMessage;
- S32 mFee;
-};
-
-void join_group_callback(S32 option, void* user_data)
+bool join_group_response(const LLSD& notification, const LLSD& response)
{
- LLJoinGroupData* data = (LLJoinGroupData*)user_data;
+ S32 option = LLNotification::getSelectedOption(notification, response);
BOOL delete_context_data = TRUE;
bool accept_invite = false;
- if (option == 2 && data && !data->mGroupID.isNull())
+ LLUUID group_id = notification["payload"]["group_id"].asUUID();
+ LLUUID transaction_id = notification["payload"]["transaction_id"].asUUID();
+ std::string name = notification["payload"]["name"].asString();
+ std::string message = notification["payload"]["message"].asString();
+ S32 fee = notification["payload"]["fee"].asInteger();
+
+ if (option == 2 && !group_id.isNull())
{
- LLFloaterGroupInfo::showFromUUID(data->mGroupID);
- LLStringUtil::format_map_t args;
- args["[MESSAGE]"] = data->mMessage;
- LLNotifyBox::showXml("JoinGroup", args, &join_group_callback, data);
- return;
+ LLFloaterGroupInfo::showFromUUID(group_id);
+ LLSD args;
+ args["MESSAGE"] = message;
+ LLNotifications::instance().add("JoinGroup", args, notification["payload"]);
+ return false;
}
- if(option == 0 && data && !data->mGroupID.isNull())
+ if(option == 0 && !group_id.isNull())
{
// check for promotion or demotion.
S32 max_groups = MAX_AGENT_GROUPS;
- if(gAgent.isInGroup(data->mGroupID)) ++max_groups;
+ if(gAgent.isInGroup(group_id)) ++max_groups;
if(gAgent.mGroups.count() < max_groups)
{
@@ -599,10 +648,10 @@ void join_group_callback(S32 option, void* user_data)
else
{
delete_context_data = FALSE;
- LLStringUtil::format_map_t args;
- args["[NAME]"] = data->mName;
- args["[INVITE]"] = data->mMessage;
- LLAlertDialog::showXml("JoinedTooManyGroupsMember", args, join_group_callback, (void*)data);
+ LLSD args;
+ args["NAME"] = name;
+ args["INVITE"] = message;
+ LLNotifications::instance().add("JoinedTooManyGroupsMember", args, notification["payload"]);
}
}
@@ -610,45 +659,44 @@ void join_group_callback(S32 option, void* user_data)
{
// If there is a fee to join this group, make
// sure the user is sure they want to join.
- if (data->mFee > 0)
+ if (fee > 0)
{
delete_context_data = FALSE;
- LLStringUtil::format_map_t args;
- args["[COST]"] = llformat("%d", data->mFee);
- // Set the fee to 0, so that we don't keep
+ LLSD args;
+ args["COST"] = llformat("%d", fee);
+ // Set the fee for next time to 0, so that we don't keep
// asking about a fee.
- data->mFee = 0;
- gViewerWindow->alertXml("JoinGroupCanAfford",
+ LLSD next_payload = notification["payload"];
+ next_payload["fee"] = 0;
+ LLNotifications::instance().add("JoinGroupCanAfford",
args,
- join_group_callback,
- (void*)data);
+ next_payload);
}
else
{
- send_improved_im(data->mGroupID,
+ send_improved_im(group_id,
std::string("name"),
std::string("message"),
IM_ONLINE,
IM_GROUP_INVITATION_ACCEPT,
- data->mTransactionID);
+ transaction_id);
}
}
- else if (data)
+ else
{
- send_improved_im(data->mGroupID,
+ send_improved_im(group_id,
std::string("name"),
std::string("message"),
IM_ONLINE,
IM_GROUP_INVITATION_DECLINE,
- data->mTransactionID);
+ transaction_id);
}
- if(delete_context_data)
- {
- delete data;
- data = NULL;
- }
+ return false;
}
+static LLNotificationFunctorRegistration jgr_1("JoinGroup", join_group_response);
+static LLNotificationFunctorRegistration jgr_2("JoinedTooManyGroupsMember", join_group_response);
+static LLNotificationFunctorRegistration jgr_3("JoinGroupCanAfford", join_group_response);
//-----------------------------------------------------------------------------
@@ -930,9 +978,15 @@ void inventory_offer_mute_callback(const LLUUID& blocked_id,
{
public:
OfferMatcher(const LLUUID& to_block) : blocked_id(to_block) {}
- BOOL matches(LLNotifyBox::notify_callback_t callback, void* cb_data) const
+ BOOL matches(const LLNotificationPtr notification) const
{
- return callback == inventory_offer_callback && ((LLOfferInfo*)cb_data)->mFromID == blocked_id;
+ if(notification->getName() == "ObjectGiveItem"
+ || notification->getName() == "ObjectGiveItemUnknownUser"
+ || notification->getName() == "UserGiveItem")
+ {
+ return (notification->getPayload()["from_id"].asUUID() == blocked_id);
+ }
+ return FALSE;
}
private:
const LLUUID& blocked_id;
@@ -940,12 +994,43 @@ void inventory_offer_mute_callback(const LLUUID& blocked_id,
gNotifyBoxView->purgeMessagesMatching(OfferMatcher(blocked_id));
}
-void inventory_offer_callback(S32 button, void* user_data)
+LLOfferInfo::LLOfferInfo(const LLSD& sd)
+{
+ mIM = (EInstantMessage)sd["im_type"].asInteger();
+ mFromID = sd["from_id"].asUUID();
+ mFromGroup = sd["from_group"].asBoolean();
+ mFromObject = sd["from_object"].asBoolean();
+ mTransactionID = sd["transaction_id"].asUUID();
+ mFolderID = sd["folder_id"].asUUID();
+ mObjectID = sd["object_id"].asUUID();
+ mType = LLAssetType::lookup(sd["type"].asString().c_str());
+ mFromName = sd["from_name"].asString();
+ mDesc = sd["description"].asString();
+ mHost = LLHost(sd["sender"].asString());
+}
+
+LLSD LLOfferInfo::asLLSD()
+{
+ LLSD sd;
+ sd["im_type"] = mIM;
+ sd["from_id"] = mFromID;
+ sd["from_group"] = mFromGroup;
+ sd["from_object"] = mFromObject;
+ sd["transaction_id"] = mTransactionID;
+ sd["folder_id"] = mFolderID;
+ sd["object_id"] = mObjectID;
+ sd["type"] = LLAssetType::lookup(mType);
+ sd["from_name"] = mFromName;
+ sd["description"] = mDesc;
+ sd["sender"] = mHost.getIPandPort();
+ return sd;
+}
+
+bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& response)
{
LLChat chat;
std::string log_message;
- LLOfferInfo* info = (LLOfferInfo*)user_data;
- if(!info) return;
+ S32 button = LLNotification::getSelectedOption(notification, response);
// For muting, we need to add the mute, then decline the offer.
// This must be done here because:
@@ -954,7 +1039,7 @@ void inventory_offer_callback(S32 button, void* user_data)
// * we can't build two messages at once. JC
if (2 == button)
{
- gCacheName->get(info->mFromID, info->mFromGroup, inventory_offer_mute_callback, user_data);
+ gCacheName->get(mFromID, mFromGroup, inventory_offer_mute_callback, this);
}
LLMessageSystem* msg = gMessageSystem;
@@ -964,9 +1049,9 @@ void inventory_offer_callback(S32 button, void* user_data)
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
msg->nextBlockFast(_PREHASH_MessageBlock);
msg->addBOOLFast(_PREHASH_FromGroup, FALSE);
- msg->addUUIDFast(_PREHASH_ToAgentID, info->mFromID);
+ msg->addUUIDFast(_PREHASH_ToAgentID, mFromID);
msg->addU8Fast(_PREHASH_Offline, IM_ONLINE);
- msg->addUUIDFast(_PREHASH_ID, info->mTransactionID);
+ msg->addUUIDFast(_PREHASH_ID, mTransactionID);
msg->addU32Fast(_PREHASH_Timestamp, NO_TIMESTAMP); // no timestamp necessary
std::string name;
gAgent.buildFullname(name);
@@ -977,50 +1062,50 @@ void inventory_offer_callback(S32 button, void* user_data)
msg->addVector3Fast(_PREHASH_Position, gAgent.getPositionAgent());
LLInventoryObserver* opener = NULL;
LLViewerInventoryCategory* catp = NULL;
- catp = (LLViewerInventoryCategory*)gInventory.getCategory(info->mObjectID);
+ catp = (LLViewerInventoryCategory*)gInventory.getCategory(mObjectID);
LLViewerInventoryItem* itemp = NULL;
if(!catp)
{
- itemp = (LLViewerInventoryItem*)gInventory.getItem(info->mObjectID);
+ itemp = (LLViewerInventoryItem*)gInventory.getItem(mObjectID);
}
// *TODO:translate
std::string from_string; // Used in the pop-up.
std::string chatHistory_string; // Used in chat history.
- if (info->mFromObject == TRUE)
+ if (mFromObject == TRUE)
{
- if (info->mFromGroup)
+ if (mFromGroup)
{
std::string group_name;
- if (gCacheName->getGroupName(info->mFromID, group_name))
+ if (gCacheName->getGroupName(mFromID, group_name))
{
- from_string = std::string("An object named '") + info->mFromName + "' owned by the group '" + group_name + "'";
- chatHistory_string = info->mFromName + " owned by the group '" + group_name + "'";
+ from_string = std::string("An object named '") + mFromName + "' owned by the group '" + group_name + "'";
+ chatHistory_string = mFromName + " owned by the group '" + group_name + "'";
}
else
{
- from_string = std::string("An object named '") + info->mFromName + "' owned by an unknown group";
- chatHistory_string = info->mFromName + " owned by an unknown group";
+ from_string = std::string("An object named '") + mFromName + "' owned by an unknown group";
+ chatHistory_string = mFromName + " owned by an unknown group";
}
}
else
{
std::string first_name, last_name;
- if (gCacheName->getName(info->mFromID, first_name, last_name))
+ if (gCacheName->getName(mFromID, first_name, last_name))
{
- from_string = std::string("An object named '") + info->mFromName + "' owned by " + first_name + " " + last_name;
- chatHistory_string = info->mFromName + " owned by " + first_name + " " + last_name;
+ from_string = std::string("An object named '") + mFromName + "' owned by " + first_name + " " + last_name;
+ chatHistory_string = mFromName + " owned by " + first_name + " " + last_name;
}
else
{
- from_string = std::string("An object named '") + info->mFromName + "' owned by an unknown user";
- chatHistory_string = info->mFromName + " owned by an unknown user";
+ from_string = std::string("An object named '") + mFromName + "' owned by an unknown user";
+ chatHistory_string = mFromName + " owned by an unknown user";
}
}
}
else
{
- from_string = chatHistory_string = info->mFromName;
+ from_string = chatHistory_string = mFromName;
}
bool busy=FALSE;
@@ -1033,24 +1118,24 @@ void inventory_offer_callback(S32 button, void* user_data)
// group_notice_inventory is 1 greater than the offer integer value.
// Generates IM_INVENTORY_ACCEPTED, IM_TASK_INVENTORY_ACCEPTED,
// or IM_GROUP_NOTICE_INVENTORY_ACCEPTED
- msg->addU8Fast(_PREHASH_Dialog, (U8)(info->mIM + 1));
- msg->addBinaryDataFast(_PREHASH_BinaryBucket, &(info->mFolderID.mData),
- sizeof(info->mFolderID.mData));
+ msg->addU8Fast(_PREHASH_Dialog, (U8)(mIM + 1));
+ msg->addBinaryDataFast(_PREHASH_BinaryBucket, &(mFolderID.mData),
+ sizeof(mFolderID.mData));
// send the message
- msg->sendReliable(info->mHost);
+ msg->sendReliable(mHost);
//don't spam them if they are getting flooded
- if (check_offer_throttle(info->mFromName, true))
+ if (check_offer_throttle(mFromName, true))
{
- log_message = chatHistory_string + " gave you " + info->mDesc + ".";
+ log_message = chatHistory_string + " gave you " + mDesc + ".";
chat.mText = log_message;
LLFloaterChat::addChatHistory(chat);
}
// we will want to open this item when it comes back.
- LL_DEBUGS("Messaging") << "Initializing an opener for tid: " << info->mTransactionID
+ LL_DEBUGS("Messaging") << "Initializing an opener for tid: " << mTransactionID
<< LL_ENDL;
- switch (info->mIM)
+ switch (mIM)
{
case IM_INVENTORY_OFFERED:
{
@@ -1058,7 +1143,7 @@ void inventory_offer_callback(S32 button, void* user_data)
// end has already copied the items into your inventory,
// so we can fetch it out of our inventory.
LLInventoryFetchObserver::item_ref_t items;
- items.push_back(info->mObjectID);
+ items.push_back(mObjectID);
LLOpenAgentOffer* open_agent_offer = new LLOpenAgentOffer(from_string);
open_agent_offer->fetchItems(items);
if(catp || (itemp && itemp->isComplete()))
@@ -1084,7 +1169,7 @@ void inventory_offer_callback(S32 button, void* user_data)
default:
LL_WARNS("Messaging") << "inventory_offer_callback: unknown offer type" << LL_ENDL;
break;
- } // end switch (info->mIM)
+ } // end switch (mIM)
break;
case IOR_BUSY:
@@ -1100,14 +1185,14 @@ void inventory_offer_callback(S32 button, void* user_data)
// or IM_GROUP_NOTICE_INVENTORY_DECLINED
default:
// close button probably (or any of the fall-throughs from above)
- msg->addU8Fast(_PREHASH_Dialog, (U8)(info->mIM + 2));
+ msg->addU8Fast(_PREHASH_Dialog, (U8)(mIM + 2));
msg->addBinaryDataFast(_PREHASH_BinaryBucket, EMPTY_BINARY_BUCKET, EMPTY_BINARY_BUCKET_SIZE);
// send the message
- msg->sendReliable(info->mHost);
+ msg->sendReliable(mHost);
- log_message = "You decline " + info->mDesc + " from " + info->mFromName + ".";
+ log_message = "You decline " + mDesc + " from " + mFromName + ".";
chat.mText = log_message;
- if( LLMuteList::getInstance()->isMuted(info->mFromID ) && ! LLMuteList::getInstance()->isLinden(info->mFromName) ) // muting for SL-42269
+ if( LLMuteList::getInstance()->isMuted(mFromID ) && ! LLMuteList::getInstance()->isLinden(mFromName) ) // muting for SL-42269
{
chat.mMuted = TRUE;
}
@@ -1116,13 +1201,13 @@ void inventory_offer_callback(S32 button, void* user_data)
// If it's from an agent, we have to fetch the item to throw
// it away. If it's from a task or group, just denying the
// request will suffice to discard the item.
- if(IM_INVENTORY_OFFERED == info->mIM)
+ if(IM_INVENTORY_OFFERED == mIM)
{
LLInventoryFetchComboObserver::folder_ref_t folders;
LLInventoryFetchComboObserver::item_ref_t items;
- items.push_back(info->mObjectID);
+ items.push_back(mObjectID);
LLDiscardAgentOffer* discard_agent_offer;
- discard_agent_offer = new LLDiscardAgentOffer(info->mFolderID, info->mObjectID);
+ discard_agent_offer = new LLDiscardAgentOffer(mFolderID, mObjectID);
discard_agent_offer->fetch(folders, items);
if(catp || (itemp && itemp->isComplete()))
{
@@ -1134,9 +1219,9 @@ void inventory_offer_callback(S32 button, void* user_data)
}
}
- if (busy && (!info->mFromGroup && !info->mFromObject))
+ if (busy && (!mFromGroup && !mFromObject))
{
- busy_message(msg,info->mFromID);
+ busy_message(msg,mFromID);
}
break;
}
@@ -1146,12 +1231,12 @@ void inventory_offer_callback(S32 button, void* user_data)
gInventory.addObserver(opener);
}
- delete info;
- info = NULL;
-
// Allow these to stack up, but once you deal with one, reset the
// position.
gFloaterView->resetStartingFloaterPosition();
+
+ delete this;
+ return false;
}
@@ -1161,14 +1246,14 @@ void inventory_offer_handler(LLOfferInfo* info, BOOL from_task)
//accepting it. SEE SL-39554
if (gAgent.getBusy())
{
- inventory_offer_callback(IOR_BUSY, info);
+ info->forceResponse(IOR_BUSY);
return;
}
//If muted, don't even go through the messaging stuff. Just curtail the offer here.
if (LLMuteList::getInstance()->isMuted(info->mFromID, info->mFromName))
{
- inventory_offer_callback(IOR_MUTE, info);
+ info->forceResponse(IOR_MUTE);
return;
}
@@ -1180,7 +1265,7 @@ void inventory_offer_handler(LLOfferInfo* info, BOOL from_task)
{
// For certain types, just accept the items into the inventory,
// and possibly open them on receipt depending upon "ShowNewInventory".
- inventory_offer_callback(IOR_ACCEPT, info);
+ info->forceResponse(IOR_ACCEPT);
return;
}
@@ -1192,23 +1277,25 @@ void inventory_offer_handler(LLOfferInfo* info, BOOL from_task)
LLStringUtil::truncate(msg, indx);
}
- LLStringUtil::format_map_t args;
+ LLSD args;
args["[OBJECTNAME]"] = msg;
+ LLSD payload;
+
// must protect against a NULL return from lookupHumanReadable()
std::string typestr = ll_safe_string(LLAssetType::lookupHumanReadable(info->mType));
if (!typestr.empty())
{
- args["[OBJECTTYPE]"] = typestr;
+ args["OBJECTTYPE"] = typestr;
}
else
{
LL_WARNS("Messaging") << "LLAssetType::lookupHumanReadable() returned NULL - probably bad asset type: " << info->mType << LL_ENDL;
- args["[OBJECTTYPE]"] = "";
+ args["OBJECTTYPE"] = "";
// This seems safest, rather than propagating bogosity
LL_WARNS("Messaging") << "Forcing an inventory-decline for probably-bad asset type." << LL_ENDL;
- inventory_offer_callback(IOR_DECLINE, info);
+ info->forceResponse(IOR_DECLINE);
return;
}
@@ -1220,8 +1307,8 @@ void inventory_offer_handler(LLOfferInfo* info, BOOL from_task)
std::string group_name;
if (gCacheName->getGroupName(info->mFromID, group_name))
{
- args["[FIRST]"] = group_name;
- args["[LAST]"] = "";
+ args["FIRST"] = group_name;
+ args["LAST"] = "";
name_found = TRUE;
}
}
@@ -1230,95 +1317,100 @@ void inventory_offer_handler(LLOfferInfo* info, BOOL from_task)
std::string first_name, last_name;
if (gCacheName->getName(info->mFromID, first_name, last_name))
{
- args["[FIRST]"] = first_name;
- args["[LAST]"] = last_name;
+ args["FIRST"] = first_name;
+ args["LAST"] = last_name;
name_found = TRUE;
}
}
+
+ payload["from_id"] = info->mFromID;
+ args["OBJECTFROMNAME"] = info->mFromName;
+ args["NAME"] = info->mFromName;
+
+ LLNotification::Params p("ObjectGiveItem");
+ p.substitutions(args).payload(payload).functor(boost::bind(&LLOfferInfo::inventory_offer_callback, info, _1, _2));
+
if (from_task)
{
- args["[OBJECTFROMNAME]"] = info->mFromName;
- LLNotifyBox::showXml(name_found ? "ObjectGiveItem" : "ObjectGiveItemUnknownUser",
- args, &inventory_offer_callback, (void*)info);
+ p.name = name_found ? "ObjectGiveItem" : "ObjectGiveItemUnknownUser";
}
else
{
- // *TODO:translate -> [FIRST] [LAST]
- args["[NAME]"] = info->mFromName;
- LLNotifyBox::showXml("UserGiveItem", args,
- &inventory_offer_callback, (void*)info);
+ p.name = "UserGiveItem";
}
+
+ LLNotifications::instance().add(p);
}
-void group_vote_callback(S32 option, void *userdata)
+bool group_vote_callback(const LLSD& notification, const LLSD& response)
{
- LLUUID *group_id = (LLUUID *)userdata;
- if (!group_id) return;
-
+ LLUUID group_id = notification["payload"]["group_id"].asUUID();
+ S32 option = LLNotification::getSelectedOption(notification, response);
switch(option)
{
case 0:
// Vote Now
// Open up the voting tab
- LLFloaterGroupInfo::showFromUUID(*group_id, "voting_tab");
+ LLFloaterGroupInfo::showFromUUID(group_id, "voting_tab");
break;
default:
// Vote Later or
// close button
break;
}
- delete group_id;
- group_id = NULL;
+ return false;
}
+static LLNotificationFunctorRegistration group_vote_callback_reg("GroupVote", group_vote_callback);
-struct LLLureInfo
+bool lure_callback(const LLSD& notification, const LLSD& response)
{
- LLLureInfo(const LLUUID& from, const LLUUID& lure_id, BOOL godlike) :
- mFromID(from),
- mLureID(lure_id),
- mGodlike(godlike)
- {}
-
- LLUUID mFromID;
- LLUUID mLureID;
- BOOL mGodlike;
-};
+ S32 option = 0;
+ if (response.isInteger())
+ {
+ option = response.asInteger();
+ }
+ else
+ {
+ option = LLNotification::getSelectedOption(notification, response);
+ }
+
+ LLUUID from_id = notification["payload"]["from_id"].asUUID();
+ LLUUID lure_id = notification["payload"]["lure_id"].asUUID();
+ BOOL godlike = notification["payload"]["godlike"].asBoolean();
-void lure_callback(S32 option, void* user_data)
-{
- LLLureInfo* info = (LLLureInfo*)user_data;
- if(!info) return;
switch(option)
{
case 0:
{
// accept
- gAgent.teleportViaLure(info->mLureID, info->mGodlike);
+ gAgent.teleportViaLure(lure_id, godlike);
}
break;
case 1:
default:
// decline
- send_simple_im(info->mFromID,
+ send_simple_im(from_id,
LLStringUtil::null,
IM_LURE_DECLINED,
- info->mLureID);
+ lure_id);
break;
}
- delete info;
- info = NULL;
+ return false;
}
+static LLNotificationFunctorRegistration lure_callback_reg("TeleportOffered", lure_callback);
-void goto_url_callback(S32 option, void* user_data)
+bool goto_url_callback(const LLSD& notification, const LLSD& response)
{
- char* url = (char*)user_data;
+ std::string url = notification["payload"]["url"].asString();
+ S32 option = LLNotification::getSelectedOption(notification, response);
if(1 == option)
{
LLWeb::loadURL(url);
}
- delete[] url;
+ return false;
}
+static LLNotificationFunctorRegistration goto_url_callback_reg("GotoURL", goto_url_callback);
void process_improved_im(LLMessageSystem *msg, void **user_data)
{
@@ -1332,7 +1424,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
U8 offline;
U8 d = 0;
LLUUID session_id;
- U32 t;
+ U32 timestamp;
std::string name;
std::string message;
U32 parent_estate_id = 0;
@@ -1350,7 +1442,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
msg->getU8Fast( _PREHASH_MessageBlock, _PREHASH_Offline, offline);
msg->getU8Fast( _PREHASH_MessageBlock, _PREHASH_Dialog, d);
msg->getUUIDFast(_PREHASH_MessageBlock, _PREHASH_ID, session_id);
- msg->getU32Fast( _PREHASH_MessageBlock, _PREHASH_Timestamp, t);
+ msg->getU32Fast( _PREHASH_MessageBlock, _PREHASH_Timestamp, timestamp);
//msg->getData("MessageBlock", "Count", &count);
msg->getStringFast(_PREHASH_MessageBlock, _PREHASH_FromAgentName, name);
msg->getStringFast(_PREHASH_MessageBlock, _PREHASH_Message, message);
@@ -1360,7 +1452,6 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
msg->getBinaryDataFast( _PREHASH_MessageBlock, _PREHASH_BinaryBucket, binary_bucket, 0, 0, MTUBYTES);
binary_bucket_size = msg->getSizeFast(_PREHASH_MessageBlock, _PREHASH_BinaryBucket);
EInstantMessage dialog = (EInstantMessage)d;
- time_t timestamp = (time_t)t;
BOOL is_busy = gAgent.getBusy();
BOOL is_muted = LLMuteList::getInstance()->isMuted(from_id, name, LLMute::flagTextChat);
@@ -1389,18 +1480,18 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
message_offset = 3;
}
- LLStringUtil::format_map_t args;
+ LLSD args;
switch(dialog)
{
case IM_CONSOLE_AND_CHAT_HISTORY:
// These are used for system messages, hence don't need the name,
// as it is always "Second Life".
// *TODO:translate
- args["[MESSAGE]"] = message;
+ args["MESSAGE"] = message;
// Note: don't put the message in the IM history, even though was sent
// via the IM mechanism.
- LLNotifyBox::showXml("SystemMessageTip",args);
+ LLNotifications::instance().add("SystemMessageTip",args);
break;
case IM_NOTHING_SPECIAL:
@@ -1470,9 +1561,9 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
else if (to_id.isNull())
{
// Message to everyone from GOD
- args["[NAME]"] = name;
- args["[MESSAGE]"] = message;
- LLNotifyBox::showXml("GodMessage", args);
+ args["NAME"] = name;
+ args["MESSAGE"] = message;
+ LLNotifications::instance().add("GodMessage", args);
// Treat like a system message and put in chat history.
// Claim to be from a local agent so it doesn't go into
@@ -1541,8 +1632,8 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
{
// This is a block, modeless dialog.
//*TODO:translate
- args["[MESSAGE]"] = message;
- LLNotifyBox::showXml("SystemMessage", args);
+ args["MESSAGE"] = message;
+ LLNotifications::instance().add("SystemMessage", args);
}
break;
case IM_GROUP_NOTICE:
@@ -1579,9 +1670,11 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
// If there is inventory, give the user the inventory offer.
LLOfferInfo* info = NULL;
+
if (has_inventory)
{
info = new LLOfferInfo;
+
info->mIM = IM_GROUP_NOTICE;
info->mFromID = from_id;
info->mFromGroup = from_group;
@@ -1610,13 +1703,26 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
std::string subj(*iter++);
std::string mes(*iter++);
- if (IM_GROUP_NOTICE == dialog)
+ // Send the notification down the new path.
+ // For requested notices, we don't want to send the popups.
+ if (dialog != IM_GROUP_NOTICE_REQUESTED)
{
- subj += "\n";
- mes = "\n\n" + mes;
- LLGroupNotifyBox::show(subj,mes,name,group_id,t,has_inventory,item_name,info);
+ LLSD payload;
+ payload["subject"] = subj;
+ payload["message"] = mes;
+ payload["sender_name"] = name;
+ payload["group_id"] = group_id;
+ payload["inventory_name"] = item_name;
+ payload["inventory_offer"] = info ? info->asLLSD() : LLSD();
+
+ LLSD args;
+ args["SUBJECT"] = subj;
+ args["MESSAGE"] = mes;
+ LLNotifications::instance().add(LLNotification::Params("GroupNotice").substitutions(args).payload(payload).timestamp(timestamp));
}
- else if (IM_GROUP_NOTICE_REQUESTED == dialog)
+
+ // Also send down the old path for now.
+ if (IM_GROUP_NOTICE_REQUESTED == dialog)
{
LLFloaterGroupInfo::showNotice(subj,mes,group_id,has_inventory,item_name,info);
}
@@ -1628,7 +1734,6 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
if ((is_busy || is_muted))
{
LLMessageSystem *msg = gMessageSystem;
- join_group_callback(1, NULL);
busy_message(msg,from_id);
}
else
@@ -1651,18 +1756,16 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
invite_bucket = (struct invite_bucket_t*) &binary_bucket[0];
S32 membership_fee = ntohl(invite_bucket->membership_fee);
- LLJoinGroupData* userdata = new LLJoinGroupData;
- userdata->mTransactionID = session_id;
- userdata->mGroupID = from_id;
- userdata->mName.assign(name);
- userdata->mMessage.assign(message);
- userdata->mFee = membership_fee;
-
- LLStringUtil::format_map_t args;
- args["[MESSAGE]"] = message;
- LLNotifyBox::showXml("JoinGroup", args,
- &join_group_callback,
- (void*)userdata);
+ LLSD payload;
+ payload["transaction_id"] = session_id;
+ payload["group_id"] = from_id;
+ payload["name"] = name;
+ payload["message"] = message;
+ payload["fee"] = membership_fee;
+
+ LLSD args;
+ args["MESSAGE"] = message;
+ LLNotifications::instance().add("JoinGroup", args, payload, join_group_response);
}
}
break;
@@ -1722,7 +1825,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
if ( is_muted )
{
// Same as closing window
- inventory_offer_callback(-1, info);
+ info->forceResponse(IOR_DECLINE);
}
else
{
@@ -1733,23 +1836,25 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
case IM_INVENTORY_ACCEPTED:
{
- args["[NAME]"] = name;
- LLNotifyBox::showXml("InventoryAccepted", args);
+ args["NAME"] = name;
+ LLNotifications::instance().add("InventoryAccepted", args);
break;
}
case IM_INVENTORY_DECLINED:
{
- args["[NAME]"] = name;
- LLNotifyBox::showXml("InventoryDeclined", args);
+ args["NAME"] = name;
+ LLNotifications::instance().add("InventoryDeclined", args);
break;
}
case IM_GROUP_VOTE:
{
- LLUUID *userdata = new LLUUID(session_id);
- args["[NAME]"] = name;
- args["[MESSAGE]"] = message;
- LLNotifyBox::showXml("GroupVote", args,
- &group_vote_callback, userdata);
+ LLSD args;
+ args["NAME"] = name;
+ args["MESSAGE"] = message;
+
+ LLSD payload;
+ payload["group_id"] = session_id;
+ LLNotifications::instance().add("GroupVote", args, payload);
}
break;
@@ -1856,9 +1961,9 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
}
{
// Construct a viewer alert for this message.
- args["[NAME]"] = name;
- args["[MESSAGE]"] = message;
- LLNotifyBox::showXml("ObjectMessage", args);
+ args["NAME"] = name;
+ args["MESSAGE"] = message;
+ LLNotifications::instance().add("ObjectMessage", args);
}
break;
case IM_BUSY_AUTO_RESPONSE:
@@ -1887,27 +1992,34 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
}
else
{
+ LLSD args;
// *TODO:translate -> [FIRST] [LAST] (maybe)
- LLLureInfo* info = new LLLureInfo(from_id, session_id, FALSE);
- args["[NAME]"] = name;
- args["[MESSAGE]"] = message;
- LLNotifyBox::showXml("OfferTeleport", args,
- lure_callback, (void*)info);
+ args["NAME"] = name;
+ args["MESSAGE"] = message;
+ LLSD payload;
+ payload["from_id"] = from_id;
+ payload["lure_id"] = session_id;
+ payload["godlike"] = FALSE;
+ LLNotifications::instance().add("TeleportOffered", args, payload);
}
}
break;
case IM_GODLIKE_LURE_USER:
{
- LLLureInfo* info = new LLLureInfo(from_id, session_id, TRUE);
+ LLSD payload;
+ payload["from_id"] = from_id;
+ payload["lure_id"] = session_id;
+ payload["godlike"] = TRUE;
// do not show a message box, because you're about to be
// teleported.
- lure_callback(0, (void *)info);
+ LLNotifications::instance().forceResponse(LLNotification::Params("TeleportOffered").payload(payload), 0);
}
break;
case IM_GOTO_URL:
{
+ LLSD args;
// n.b. this is for URLs sent by the system, not for
// URLs sent by scripts (i.e. llLoadURL)
if (binary_bucket_size <= 0)
@@ -1918,38 +2030,33 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
return;
}
- char* url = new char[binary_bucket_size];
- if (url == NULL)
- {
- LL_ERRS("Messaging") << "Memory Allocation failed" << LL_ENDL;
- return;
- }
-
- strncpy(url, (char*)binary_bucket, binary_bucket_size-1); /* Flawfinder: ignore */
- url[binary_bucket_size-1] = '\0';
- args["[MESSAGE]"] = message;
- args["[URL]"] = url;
- LLNotifyBox::showXml("GotoURL", args,
- goto_url_callback, (void*)url);
+ std::string url;
+
+ url.assign((char*)binary_bucket, binary_bucket_size-1);
+ args["MESSAGE"] = message;
+ args["URL"] = url;
+ LLSD payload;
+ payload["url"] = url;
+ LLNotifications::instance().add("GotoURL", args, payload );
}
break;
case IM_FRIENDSHIP_OFFERED:
{
- LLFriendshipOffer* offer = new LLFriendshipOffer;
- offer->mFromID = from_id;
- offer->mTransactionID = session_id;
- offer->mOnline = (offline == IM_ONLINE);
- offer->mHost = msg->getSender();
+ LLSD payload;
+ payload["from_id"] = from_id;
+ payload["session_id"] = session_id;;
+ payload["online"] = (offline == IM_ONLINE);
+ payload["sender"] = msg->getSender().getIPandPort();
if (is_busy)
{
busy_message(msg, from_id);
- friendship_offer_callback(1, (void*)offer);
+ LLNotifications::instance().forceResponse(LLNotification::Params("OfferFriendship").payload(payload), 1);
}
else if (is_muted)
{
- friendship_offer_callback(1, (void*)offer);
+ LLNotifications::instance().forceResponse(LLNotification::Params("OfferFriendship").payload(payload), 1);
}
else
{
@@ -1957,14 +2064,12 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
if(message.empty())
{
//support for frienship offers from clients before July 2008
- LLNotifyBox::showXml("OfferFriendshipNoMessage", args,
- &friendship_offer_callback, (void*)offer);
+ LLNotifications::instance().add("OfferFriendshipNoMessage", args, payload);
}
else
{
args["[MESSAGE]"] = message;
- LLNotifyBox::showXml("OfferFriendship", args,
- &friendship_offer_callback, (void*)offer);
+ LLNotifications::instance().add("OfferFriendship", args, payload);
}
}
}
@@ -1981,14 +2086,14 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
strings.push_back(from_id.asString());
send_generic_message("requestonlinenotification", strings);
- args["[NAME]"] = name;
- LLNotifyBox::showXml("FriendshipAccepted", args);
+ args["NAME"] = name;
+ LLNotifications::instance().add("FriendshipAccepted", args);
}
break;
case IM_FRIENDSHIP_DECLINED:
- args["[NAME]"] = name;
- LLNotifyBox::showXml("FriendshipDeclined", args);
+ args["NAME"] = name;
+ LLNotifications::instance().add("FriendshipDeclined", args);
break;
default:
@@ -2025,61 +2130,9 @@ void busy_message (LLMessageSystem* msg, LLUUID from_id)
}
}
-void friendship_offer_callback(S32 option, void* user_data)
+bool callingcard_offer_callback(const LLSD& notification, const LLSD& response)
{
- LLFriendshipOffer* offer = (LLFriendshipOffer*)user_data;
- if(!offer) return;
- LLUUID fid;
- LLMessageSystem* msg = gMessageSystem;
- switch(option)
- {
- case 0:
- // accept
- LLAvatarTracker::formFriendship(offer->mFromID);
-
- fid = gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD);
-
- // This will also trigger an onlinenotification if the user is online
- msg->newMessageFast(_PREHASH_AcceptFriendship);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_TransactionBlock);
- msg->addUUIDFast(_PREHASH_TransactionID, offer->mTransactionID);
- msg->nextBlockFast(_PREHASH_FolderData);
- msg->addUUIDFast(_PREHASH_FolderID, fid);
- msg->sendReliable(offer->mHost);
- break;
- case 1:
- // decline
- msg->newMessageFast(_PREHASH_DeclineFriendship);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_TransactionBlock);
- msg->addUUIDFast(_PREHASH_TransactionID, offer->mTransactionID);
- msg->sendReliable(offer->mHost);
- break;
- default:
- // close button probably, possibly timed out
- break;
- }
-
- delete offer;
- offer = NULL;
-}
-
-struct LLCallingCardOfferData
-{
- LLUUID mTransactionID;
- LLUUID mSourceID;
- LLHost mHost;
-};
-
-void callingcard_offer_callback(S32 option, void* user_data)
-{
- LLCallingCardOfferData* offerdata = (LLCallingCardOfferData*)user_data;
- if(!offerdata) return;
+ S32 option = LLNotification::getSelectedOption(notification, response);
LLUUID fid;
LLUUID from_id;
LLMessageSystem* msg = gMessageSystem;
@@ -2092,11 +2145,11 @@ void callingcard_offer_callback(S32 option, void* user_data)
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
msg->nextBlockFast(_PREHASH_TransactionBlock);
- msg->addUUIDFast(_PREHASH_TransactionID, offerdata->mTransactionID);
+ msg->addUUIDFast(_PREHASH_TransactionID, notification["payload"]["transaction_id"].asUUID());
fid = gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD);
msg->nextBlockFast(_PREHASH_FolderData);
msg->addUUIDFast(_PREHASH_FolderID, fid);
- msg->sendReliable(offerdata->mHost);
+ msg->sendReliable(LLHost(notification["payload"]["sender"].asString()));
break;
case 1:
// decline
@@ -2105,18 +2158,18 @@ void callingcard_offer_callback(S32 option, void* user_data)
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
msg->nextBlockFast(_PREHASH_TransactionBlock);
- msg->addUUIDFast(_PREHASH_TransactionID, offerdata->mTransactionID);
- msg->sendReliable(offerdata->mHost);
- busy_message(msg, offerdata->mSourceID);
+ msg->addUUIDFast(_PREHASH_TransactionID, notification["payload"]["transaction_id"].asUUID());
+ msg->sendReliable(LLHost(notification["payload"]["sender"].asString()));
+ busy_message(msg, notification["payload"]["source_id"].asUUID());
break;
default:
// close button probably, possibly timed out
break;
}
- delete offerdata;
- offerdata = NULL;
+ return false;
}
+static LLNotificationFunctorRegistration callingcard_offer_cb_reg("OfferCallingCard", callingcard_offer_callback);
void process_offer_callingcard(LLMessageSystem* msg, void**)
{
@@ -2128,13 +2181,13 @@ void process_offer_callingcard(LLMessageSystem* msg, void**)
LLUUID tid;
msg->getUUIDFast(_PREHASH_AgentBlock, _PREHASH_TransactionID, tid);
- LLCallingCardOfferData* offerdata = new LLCallingCardOfferData;
- offerdata->mTransactionID = tid;
- offerdata->mSourceID = source_id;
- offerdata->mHost = msg->getSender();
+ LLSD payload;
+ payload["transaction_id"] = tid;
+ payload["source_id"] = source_id;
+ payload["sender"] = msg->getSender().getIPandPort();
LLViewerObject* source = gObjectList.findObject(source_id);
- LLStringUtil::format_map_t args;
+ LLSD args;
std::string source_name;
if(source && source->isAvatar())
{
@@ -2142,8 +2195,8 @@ void process_offer_callingcard(LLMessageSystem* msg, void**)
LLNameValue* nvlast = source->getNVPair("LastName");
if (nvfirst && nvlast)
{
- args["[FIRST]"] = nvfirst->getString();
- args["[LAST]"] = nvlast->getString();
+ args["FIRST"] = nvfirst->getString();
+ args["LAST"] = nvlast->getString();
source_name = std::string(nvfirst->getString()) + " " + nvlast->getString();
}
}
@@ -2154,33 +2207,27 @@ void process_offer_callingcard(LLMessageSystem* msg, void**)
|| LLMuteList::getInstance()->isMuted(source_id, source_name, LLMute::flagTextChat))
{
// automatically decline offer
- callingcard_offer_callback(1, (void*)offerdata);
- offerdata = NULL; // pointer was freed by callback
+ LLNotifications::instance().forceResponse(LLNotification::Params("OfferCallingCard").payload(payload), 1);
}
else
{
- LLNotifyBox::showXml("OfferCallingCard", args,
- &callingcard_offer_callback, (void*)offerdata);
- offerdata = NULL; // pointer ownership transferred
+ LLNotifications::instance().add("OfferCallingCard", args, payload);
}
}
else
{
LL_WARNS("Messaging") << "Calling card offer from an unknown source." << LL_ENDL;
}
-
- delete offerdata; // !=NULL if we didn't give ownership away
- offerdata = NULL;
}
void process_accept_callingcard(LLMessageSystem* msg, void**)
{
- LLNotifyBox::showXml("CallingCardAccepted");
+ LLNotifications::instance().add("CallingCardAccepted");
}
void process_decline_callingcard(LLMessageSystem* msg, void**)
{
- LLNotifyBox::showXml("CallingCardDeclined");
+ LLNotifications::instance().add("CallingCardDeclined");
}
@@ -2496,18 +2543,18 @@ public:
LLInventoryModel::EXCLUDE_TRASH,
is_card);
}
- LLStringUtil::format_map_t args;
+ LLSD args;
if ( land_items.count() > 0 )
{ // Show notification that they can now teleport to landmarks. Use a random landmark from the inventory
S32 random_land = ll_rand( land_items.count() - 1 );
- args["[NAME]"] = land_items[random_land]->getName();
- LLNotifyBox::showXml("TeleportToLandmark",args);
+ args["NAME"] = land_items[random_land]->getName();
+ LLNotifications::instance().add("TeleportToLandmark",args);
}
if ( card_items.count() > 0 )
{ // Show notification that they can now contact people. Use a random calling card from the inventory
S32 random_card = ll_rand( card_items.count() - 1 );
- args["[NAME]"] = card_items[random_card]->getName();
- LLNotifyBox::showXml("TeleportToPerson",args);
+ args["NAME"] = card_items[random_card]->getName();
+ LLNotifications::instance().add("TeleportToPerson",args);
}
gInventory.removeObserver(this);
@@ -2688,11 +2735,6 @@ void process_avatar_init_complete(LLMessageSystem* msg, void**)
}
*/
-static void display_release_notes(S32, void* data)
-{
- gAgent.getRegion()->showReleaseNotes();
-}
-
void process_agent_movement_complete(LLMessageSystem* msg, void**)
{
gAgentMovementCompleted = true;
@@ -2864,8 +2906,9 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**)
if (!gLastVersionChannel.empty())
{
- LLNotifyBox::showXml(
- "ServerVersionChanged", display_release_notes, NULL);
+ LLSD payload;
+ payload["message"] = version_channel;
+ LLNotifications::instance().add("ServerVersionChanged", LLSD(), payload);
}
gLastVersionChannel = version_channel;
@@ -4059,9 +4102,9 @@ void process_money_balance_reply( LLMessageSystem* msg, void** )
// Make the user confirm the transaction, since they might
// have missed something during an event.
// *TODO:translate
- LLStringUtil::format_map_t args;
- args["[MESSAGE]"] = desc;
- LLNotifyBox::showXml("SystemMessage", args);
+ LLSD args;
+ args["MESSAGE"] = desc;
+ LLNotifications::instance().add("SystemMessage", args);
// Once the 'recent' container gets large enough, chop some
// off the beginning.
@@ -4121,54 +4164,54 @@ void process_alert_core(const std::string& message, BOOL modal)
// Allow the server to spawn a named alert so that server alerts can be
// translated out of English.
std::string alert_name(message.substr(ALERT_PREFIX.length()));
- LLAlertDialog::showXml(alert_name);
+ LLNotifications::instance().add(alert_name);
}
else if (message.find(NOTIFY_PREFIX) == 0)
{
// Allow the server to spawn a named notification so that server notifications can be
// translated out of English.
std::string notify_name(message.substr(NOTIFY_PREFIX.length()));
- LLNotifyBox::showXml(notify_name);
+ LLNotifications::instance().add(notify_name);
}
else if (message[0] == '/')
{
// System message is important, show in upper-right box not tip
std::string text(message.substr(1));
- LLStringUtil::format_map_t args;
+ LLSD args;
if (text.substr(0,17) == "RESTART_X_MINUTES")
{
S32 mins = 0;
LLStringUtil::convertToS32(text.substr(18), mins);
- args["[MINUTES]"] = llformat("%d",mins);
- LLNotifyBox::showXml("RegionRestartMinutes", args);
+ args["MINUTES"] = llformat("%d",mins);
+ LLNotifications::instance().add("RegionRestartMinutes", args);
}
else if (text.substr(0,17) == "RESTART_X_SECONDS")
{
S32 secs = 0;
LLStringUtil::convertToS32(text.substr(18), secs);
- args["[SECONDS]"] = llformat("%d",secs);
- LLNotifyBox::showXml("RegionRestartSeconds", args);
+ args["SECONDS"] = llformat("%d",secs);
+ LLNotifications::instance().add("RegionRestartSeconds", args);
}
else
{
// *TODO:translate
- args["[MESSAGE]"] = text;
- LLNotifyBox::showXml("SystemMessage", args);
+ args["MESSAGE"] = text;
+ LLNotifications::instance().add("SystemMessage", args);
}
}
else if (modal)
{
// *TODO:translate
- LLStringUtil::format_map_t args;
- args["[ERROR_MESSAGE]"] = message;
- gViewerWindow->alertXml("ErrorMessage", args);
+ LLSD args;
+ args["ERROR_MESSAGE"] = message;
+ LLNotifications::instance().add("ErrorMessage", args);
}
else
{
// *TODO:translate
- LLStringUtil::format_map_t args;
- args["[MESSAGE]"] = message;
- LLNotifyBox::showXml("SystemMessageTip", args);
+ LLSD args;
+ args["MESSAGE"] = message;
+ LLNotifications::instance().add("SystemMessageTip", args);
}
}
@@ -4300,23 +4343,7 @@ void process_economy_data(LLMessageSystem *msg, void** /*user_data*/)
gMenuHolder->childSetLabelArg("Bulk Upload", "[COST]", llformat("%d", upload_cost));
}
-class LLScriptQuestionCBData
-{
-public:
- LLScriptQuestionCBData(const LLUUID &taskid, const LLUUID &itemid, const LLHost &sender, S32 questions, const std::string& object_name, const std::string& owner_name)
- : mTaskID(taskid), mItemID(itemid), mSender(sender), mQuestions(questions), mObjectName(object_name), mOwnerName(owner_name)
- {
- }
-
- LLUUID mTaskID;
- LLUUID mItemID;
- LLHost mSender;
- S32 mQuestions;
- std::string mObjectName;
- std::string mOwnerName;
-};
-
-void notify_cautioned_script_question(LLScriptQuestionCBData* cbdata, S32 orig_questions, BOOL granted)
+void notify_cautioned_script_question(const LLSD& notification, const LLSD& response, S32 orig_questions, BOOL granted)
{
// only continue if at least some permissions were requested
if (orig_questions)
@@ -4327,16 +4354,16 @@ void notify_cautioned_script_question(LLScriptQuestionCBData* cbdata, S32 orig_q
// located in [REGIONNAME] at [REGIONPOS],
// has been <granted|denied> permission to: [PERMISSIONS]."
- LLUIString notice(LLNotifyBox::getTemplateMessage(granted ? "ScriptQuestionCautionChatGranted" : "ScriptQuestionCautionChatDenied"));
+ LLUIString notice(LLFloaterChat::getInstance()->getString(granted ? "ScriptQuestionCautionChatGranted" : "ScriptQuestionCautionChatDenied"));
// always include the object name and owner name
- notice.setArg("[OBJECTNAME]", cbdata->mObjectName);
- notice.setArg("[OWNERNAME]", cbdata->mOwnerName);
+ notice.setArg("[OBJECTNAME]", notification["payload"]["object_name"].asString());
+ notice.setArg("[OWNERNAME]", notification["payload"]["owner_name"].asString());
// try to lookup viewerobject that corresponds to the object that
// requested permissions (here, taskid->requesting object id)
BOOL foundpos = FALSE;
- LLViewerObject* viewobj = gObjectList.findObject(cbdata->mTaskID);
+ LLViewerObject* viewobj = gObjectList.findObject(notification["payload"]["task_id"].asUUID());
if (viewobj)
{
// found the viewerobject, get it's position in its region
@@ -4369,7 +4396,7 @@ void notify_cautioned_script_question(LLScriptQuestionCBData* cbdata, S32 orig_q
std::string perms;
for (S32 i = 0; i < SCRIPT_PERMISSION_EOF; i++)
{
- if ((orig_questions & LSCRIPTRunTimePermissionBits[i]) && LLNotifyBox::getTemplateIsCaution(SCRIPT_QUESTIONS[i]))
+ if ((orig_questions & LSCRIPTRunTimePermissionBits[i]) && SCRIPT_QUESTION_IS_CAUTION[i])
{
count++;
caution = TRUE;
@@ -4381,7 +4408,7 @@ void notify_cautioned_script_question(LLScriptQuestionCBData* cbdata, S32 orig_q
perms.append(", ");
}
- perms.append(LLNotifyBox::getTemplateMessage(SCRIPT_QUESTIONS[i]));
+ perms.append(LLFloaterChat::getInstance()->getString(SCRIPT_QUESTIONS[i]));
}
}
@@ -4397,43 +4424,12 @@ void notify_cautioned_script_question(LLScriptQuestionCBData* cbdata, S32 orig_q
}
}
-void script_question_decline_cb(S32 option, void* user_data)
-{
- LLMessageSystem *msg = gMessageSystem;
- LLScriptQuestionCBData *cbdata = (LLScriptQuestionCBData *)user_data;
-
- // remember the permissions requested so they can be checked
- // when it comes time to log a chat message
- S32 orig = cbdata->mQuestions;
-
- // this callback will always decline all permissions requested
- // (any question flags set in the ScriptAnswerYes message
- // will be interpreted as having been granted, so clearing all
- // the bits will deny every permission)
- cbdata->mQuestions = 0;
-
- // respond with the permissions denial
- msg->newMessageFast(_PREHASH_ScriptAnswerYes);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_Data);
- msg->addUUIDFast(_PREHASH_TaskID, cbdata->mTaskID);
- msg->addUUIDFast(_PREHASH_ItemID, cbdata->mItemID);
- msg->addS32Fast(_PREHASH_Questions, cbdata->mQuestions);
- msg->sendReliable(cbdata->mSender);
-
- // log a chat message, if appropriate
- notify_cautioned_script_question(cbdata, orig, FALSE);
-
- delete cbdata;
-}
-
-void script_question_cb(S32 option, void* user_data)
+bool script_question_cb(const LLSD& notification, const LLSD& response)
{
+ S32 option = LLNotification::getSelectedOption(notification, response);
LLMessageSystem *msg = gMessageSystem;
- LLScriptQuestionCBData *cbdata = (LLScriptQuestionCBData *)user_data;
- S32 orig = cbdata->mQuestions;
+ S32 orig = notification["payload"]["questions"].asInteger();
+ S32 new_questions = orig;
// check whether permissions were granted or denied
BOOL allowed = TRUE;
@@ -4441,48 +4437,68 @@ void script_question_cb(S32 option, void* user_data)
// if any other button was clicked, the permissions were denied
if (option != 0)
{
- cbdata->mQuestions = 0;
+ new_questions = 0;
allowed = FALSE;
}
+ LLUUID task_id = notification["payload"]["task_id"].asUUID();
+ LLUUID item_id = notification["payload"]["item_id"].asUUID();
+
// reply with the permissions granted or denied
msg->newMessageFast(_PREHASH_ScriptAnswerYes);
msg->nextBlockFast(_PREHASH_AgentData);
msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
msg->nextBlockFast(_PREHASH_Data);
- msg->addUUIDFast(_PREHASH_TaskID, cbdata->mTaskID);
- msg->addUUIDFast(_PREHASH_ItemID, cbdata->mItemID);
- msg->addS32Fast(_PREHASH_Questions, cbdata->mQuestions);
- msg->sendReliable(cbdata->mSender);
+ msg->addUUIDFast(_PREHASH_TaskID, task_id);
+ msg->addUUIDFast(_PREHASH_ItemID, item_id);
+ msg->addS32Fast(_PREHASH_Questions, new_questions);
+ msg->sendReliable(LLHost(notification["payload"]["sender"].asString()));
// only log a chat message if caution prompts are enabled
if (gSavedSettings.getBOOL("PermissionsCautionEnabled"))
{
// log a chat message, if appropriate
- notify_cautioned_script_question(cbdata, orig, allowed);
+ notify_cautioned_script_question(notification, response, orig, allowed);
}
- if ( option == 2 ) // mute
+ if ( response["Mute"] ) // mute
{
- LLMuteList::getInstance()->add(LLMute(cbdata->mItemID, cbdata->mObjectName, LLMute::OBJECT));
+ LLMuteList::getInstance()->add(LLMute(item_id, notification["payload"]["object_name"].asString(), LLMute::OBJECT));
// purge the message queue of any previously queued requests from the same source. DEV-4879
class OfferMatcher : public LLNotifyBoxView::Matcher
{
public:
OfferMatcher(const LLUUID& to_block) : blocked_id(to_block) {}
- BOOL matches(LLNotifyBox::notify_callback_t callback, void* cb_data) const
+ BOOL matches(const LLNotificationPtr notification) const
{
- return callback == script_question_cb && ((LLScriptQuestionCBData*)cb_data)->mItemID == blocked_id;
+ if (notification->getName() == "ScriptQuestionCaution"
+ || notification->getName() == "ScriptQuestion")
+ {
+ return (notification->getPayload()["item_id"].asUUID() == blocked_id);
+ }
+ return FALSE;
}
private:
const LLUUID& blocked_id;
};
- gNotifyBoxView->purgeMessagesMatching(OfferMatcher(cbdata->mItemID));
+ // should do this via the channel
+ gNotifyBoxView->purgeMessagesMatching(OfferMatcher(item_id));
+ }
+
+ if (response["Details"])
+ {
+ // respawn notification...
+ LLNotifications::instance().add(notification["name"], notification["substitutions"], notification["payload"]);
+
+ // ...with description on top
+ LLNotifications::instance().add("DebitPermissionDetails");
}
- delete cbdata;
+ return false;
}
+static LLNotificationFunctorRegistration script_question_cb_reg_1("ScriptQuestion", script_question_cb);
+static LLNotificationFunctorRegistration script_question_cb_reg_2("ScriptQuestionCaution", script_question_cb);
void process_script_question(LLMessageSystem *msg, void **user_data)
{
@@ -4532,9 +4548,9 @@ void process_script_question(LLMessageSystem *msg, void **user_data)
{
BOOL caution = FALSE;
S32 count = 0;
- LLStringUtil::format_map_t args;
- args["[OBJECTNAME]"] = object_name;
- args["[NAME]"] = owner_name;
+ LLSD args;
+ args["OBJECTNAME"] = object_name;
+ args["NAME"] = owner_name;
// check the received permission flags against each permission
for (S32 i = 0; i < SCRIPT_PERMISSION_EOF; i++)
@@ -4542,34 +4558,32 @@ void process_script_question(LLMessageSystem *msg, void **user_data)
if (questions & LSCRIPTRunTimePermissionBits[i])
{
count++;
- script_question += " " + LLNotifyBox::getTemplateMessage(SCRIPT_QUESTIONS[i]) + "\n";
+ script_question += " " + LLFloaterChat::getInstance()->getString(SCRIPT_QUESTIONS[i]) + "\n";
// check whether permission question should cause special caution dialog
- caution |= LLNotifyBox::getTemplateIsCaution(SCRIPT_QUESTIONS[i]);
+ caution |= (SCRIPT_QUESTION_IS_CAUTION[i]);
}
}
- args["[QUESTIONS]"] = script_question;
+ args["QUESTIONS"] = script_question;
- LLScriptQuestionCBData *cbdata = new LLScriptQuestionCBData(taskid, itemid, sender, questions, object_name, owner_name);
+ LLSD payload;
+ payload["task_id"] = taskid;
+ payload["item_id"] = itemid;
+ payload["sender"] = sender.getIPandPort();
+ payload["questions"] = questions;
+ payload["object_name"] = object_name;
+ payload["owner_name"] = owner_name;
// check whether cautions are even enabled or not
if (gSavedSettings.getBOOL("PermissionsCautionEnabled"))
{
- if (caution)
- {
- // display the caution permissions prompt
- LLNotifyBox::showXml("ScriptQuestionCaution", args, TRUE, script_question_cb, cbdata);
- }
- else
- {
- // display the permissions request normally
- LLNotifyBox::showXml("ScriptQuestion", args, FALSE, script_question_cb, cbdata);
- }
+ // display the caution permissions prompt
+ LLNotifications::instance().add(caution ? "ScriptQuestionCaution" : "ScriptQuestion", args, payload);
}
else
{
// fall back to default behavior if cautions are entirely disabled
- LLNotifyBox::showXml("ScriptQuestion", args, FALSE, script_question_cb, cbdata);
+ LLNotifications::instance().add("ScriptQuestion", args, payload);
}
}
@@ -4706,18 +4720,18 @@ void process_teleport_failed(LLMessageSystem *msg, void**)
std::string reason;
msg->getStringFast(_PREHASH_Info, _PREHASH_Reason, reason);
- LLStringUtil::format_map_t args;
+ LLSD args;
std::string big_reason = LLAgent::sTeleportErrorMessages[reason];
if ( big_reason.size() > 0 )
{ // Substitute verbose reason from the local map
- args["[REASON]"] = big_reason;
+ args["REASON"] = big_reason;
}
else
{ // Nothing found in the map - use what the server returned
- args["[REASON]"] = reason;
+ args["REASON"] = reason;
}
- gViewerWindow->alertXml("CouldNotTeleportReason", args);
+ LLNotifications::instance().add("CouldNotTeleportReason", args);
if( gAgent.getTeleportState() != LLAgent::TELEPORT_NONE )
{
@@ -4839,9 +4853,10 @@ void send_group_notice(const LLUUID& group_id,
bin_bucket_size);
}
-void handle_lure_callback(S32 option, const std::string& text, void* userdata)
+bool handle_lure_callback(const LLSD& notification, const LLSD& response)
{
- LLDynamicArray<LLUUID>* invitees = (LLDynamicArray<LLUUID>*)userdata;
+ std::string text = response["message"].asString();
+ S32 option = LLNotification::getSelectedOption(notification, response);
if(0 == option)
{
@@ -4853,21 +4868,17 @@ void handle_lure_callback(S32 option, const std::string& text, void* userdata)
msg->nextBlockFast(_PREHASH_Info);
msg->addU8Fast(_PREHASH_LureType, (U8)0); // sim will fill this in.
msg->addStringFast(_PREHASH_Message, text);
- for(LLDynamicArray<LLUUID>::iterator itr = invitees->begin(); itr != invitees->end(); ++itr)
+ for(LLSD::array_const_iterator it = notification["payload"]["ids"].beginArray();
+ it != notification["payload"]["ids"].endArray();
+ ++it)
{
msg->nextBlockFast(_PREHASH_TargetData);
- msg->addUUIDFast(_PREHASH_TargetID, *itr);
+ msg->addUUIDFast(_PREHASH_TargetID, it->asUUID());
}
gAgent.sendReliableMessage();
}
- delete invitees;
- invitees = NULL;
-}
-
-void handle_lure_callback_godlike(S32 option, void* userdata)
-{
- handle_lure_callback(option, LLStringUtil::null, userdata);
+ return false;
}
void handle_lure(const LLUUID& invitee)
@@ -4880,21 +4891,23 @@ void handle_lure(const LLUUID& invitee)
// Prompt for a message to the invited user.
void handle_lure(LLDynamicArray<LLUUID>& ids)
{
- LLDynamicArray<LLUUID>* userdata = new LLDynamicArray<LLUUID>(ids);
+ LLSD edit_args;
+ edit_args["REGION"] = gAgent.getRegion()->getName();
- LLStringUtil::format_map_t edit_args;
- edit_args["[REGION]"] = gAgent.getRegion()->getName();
+ LLSD payload;
+ for (LLDynamicArray<LLUUID>::iterator it = ids.begin();
+ it != ids.end();
+ ++it)
+ {
+ payload["ids"].append(*it);
+ }
if (gAgent.isGodlike())
{
- gViewerWindow->alertXmlEditText("OfferTeleportFromGod", edit_args,
- &handle_lure_callback_godlike, userdata,
- NULL, NULL, edit_args);
+ LLNotifications::instance().add("OfferTeleportFromGod", edit_args, payload, handle_lure_callback);
}
else
{
- gViewerWindow->alertXmlEditText("OfferTeleport", edit_args,
- NULL, NULL,
- handle_lure_callback, userdata, edit_args);
+ LLNotifications::instance().add("OfferTeleport", edit_args, payload, handle_lure_callback);
}
}
@@ -4986,21 +4999,13 @@ const S32 SCRIPT_DIALOG_BUTTON_STR_SIZE = 24;
const S32 SCRIPT_DIALOG_MAX_MESSAGE_SIZE = 512;
const char* SCRIPT_DIALOG_HEADER = "Script Dialog:\n";
-struct ScriptDialogInfo
+bool callback_script_dialog(const LLSD& notification, const LLSD& response)
{
- LLHost mSender;
- LLUUID mObjectID;
- S32 mChatChannel;
- std::vector<std::string> mButtons;
-};
-
-void callback_script_dialog(S32 option, void* data)
-{
- ScriptDialogInfo* info = (ScriptDialogInfo*)data;
- if (!info) return;
-
+ LLNotificationForm form(notification["form"]);
+ std::string button = LLNotification::getSelectedOptionName(response);
+ S32 button_idx = LLNotification::getSelectedOption(notification, response);
// Didn't click "Ignore"
- if (0 != option)
+ if (button_idx != -1)
{
LLMessageSystem* msg = gMessageSystem;
msg->newMessage("ScriptDialogReply");
@@ -5008,112 +5013,108 @@ void callback_script_dialog(S32 option, void* data)
msg->addUUID("AgentID", gAgent.getID());
msg->addUUID("SessionID", gAgent.getSessionID());
msg->nextBlock("Data");
- msg->addUUID("ObjectID", info->mObjectID);
- msg->addS32("ChatChannel", info->mChatChannel);
- msg->addS32("ButtonIndex", option);
- msg->addString("ButtonLabel", info->mButtons[option-1]);
- msg->sendReliable(info->mSender);
+ msg->addUUID("ObjectID", notification["payload"]["object_id"].asUUID());
+ msg->addS32("ChatChannel", notification["payload"]["chat_channel"].asInteger());
+ msg->addS32("ButtonIndex", button_idx);
+ msg->addString("ButtonLabel", button);
+ msg->sendReliable(LLHost(notification["payload"]["sender"].asString()));
}
- delete info;
+ return false;
}
+static LLNotificationFunctorRegistration callback_script_dialog_reg_1("ScriptDialog", callback_script_dialog);
+static LLNotificationFunctorRegistration callback_script_dialog_reg_2("ScriptDialogGroup", callback_script_dialog);
void process_script_dialog(LLMessageSystem* msg, void**)
{
S32 i;
- ScriptDialogInfo* info = new ScriptDialogInfo;
+ LLSD payload;
- std::string message; // Account for size of "Script Dialog:\n"
+ std::string message;
std::string first_name;
std::string last_name;
std::string title;
- info->mSender = msg->getSender();
- msg->getUUID("Data", "ObjectID", info->mObjectID);
+ LLUUID object_id;
+ S32 chat_channel;
+ msg->getUUID("Data", "ObjectID", object_id);
msg->getString("Data", "FirstName", first_name);
msg->getString("Data", "LastName", last_name);
msg->getString("Data", "ObjectName", title);
msg->getString("Data", "Message", message);
- msg->getS32("Data", "ChatChannel", info->mChatChannel);
+ msg->getS32("Data", "ChatChannel", chat_channel);
// unused for now
LLUUID image_id;
msg->getUUID("Data", "ImageID", image_id);
+ payload["sender"] = msg->getSender().getIPandPort();
+ payload["object_id"] = object_id;
+ payload["chat_channel"] = chat_channel;
+
+ // build up custom form
S32 button_count = msg->getNumberOfBlocks("Buttons");
if (button_count > SCRIPT_DIALOG_MAX_BUTTONS)
{
button_count = SCRIPT_DIALOG_MAX_BUTTONS;
}
+ LLNotificationForm form;
for (i = 0; i < button_count; i++)
{
std::string tdesc;
msg->getString("Buttons", "ButtonLabel", tdesc, i);
- info->mButtons.push_back(tdesc);
+ form.addElement("button", std::string(tdesc));
}
- LLStringUtil::format_map_t args;
- args["[TITLE]"] = title;
- args["[MESSAGE]"] = message;
+ LLSD args;
+ args["TITLE"] = title;
+ args["MESSAGE"] = message;
+ LLNotificationPtr notification;
if (!first_name.empty())
{
- args["[FIRST]"] = first_name;
- args["[LAST]"] = last_name;
- LLNotifyBox::showXml("ScriptDialog", args,
- callback_script_dialog, info,
- info->mButtons,
- TRUE);
+ args["FIRST"] = first_name;
+ args["LAST"] = last_name;
+ notification = LLNotifications::instance().add(
+ LLNotification::Params("ScriptDialog").substitutions(args).payload(payload).form_elements(form.asLLSD()));
}
else
{
- args["[GROUPNAME]"] = last_name;
- LLNotifyBox::showXml("ScriptDialogGroup", args,
- callback_script_dialog, info,
- info->mButtons,
- TRUE);
+ args["GROUPNAME"] = last_name;
+ notification = LLNotifications::instance().add(
+ LLNotification::Params("ScriptDialogGroup").substitutions(args).payload(payload).form_elements(form.asLLSD()));
}
}
//---------------------------------------------------------------------------
-struct LoadUrlInfo
-{
- LLUUID mObjectID;
- LLUUID mOwnerID;
- BOOL mOwnerIsGroup;
- std::string mObjectName;
- std::string mMessage;
- std::string mUrl;
-};
-std::vector<LoadUrlInfo*> gLoadUrlList;
+std::vector<LLSD> gLoadUrlList;
-void callback_load_url(S32 option, void* data)
+bool callback_load_url(const LLSD& notification, const LLSD& response)
{
- LoadUrlInfo* infop = (LoadUrlInfo*)data;
- if (!infop) return;
+ S32 option = LLNotification::getSelectedOption(notification, response);
if (0 == option)
{
- LLWeb::loadURLExternal(infop->mUrl);
+ LLWeb::loadURL(notification["payload"]["url"].asString());
}
- delete infop;
- infop = NULL;
+ return false;
}
+static LLNotificationFunctorRegistration callback_load_url_reg("LoadWebPage", callback_load_url);
// We've got the name of the person who owns the object hurling the url.
// Display confirmation dialog.
void callback_load_url_name(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* data)
{
- std::vector<LoadUrlInfo*>::iterator it;
+ std::vector<LLSD>::iterator it;
for (it = gLoadUrlList.begin(); it != gLoadUrlList.end(); )
{
- LoadUrlInfo* infop = *it;
- if (infop->mOwnerID == id)
+ LLSD load_url_info = *it;
+ if (load_url_info["owner_id"].asUUID() == id)
{
it = gLoadUrlList.erase(it);
@@ -5130,16 +5131,15 @@ void callback_load_url_name(const LLUUID& id, const std::string& first, const st
// For legacy name-only mutes.
if (LLMuteList::getInstance()->isMuted(LLUUID::null, owner_name))
{
- delete infop;
- infop = NULL;
continue;
}
- LLStringUtil::format_map_t args;
- args["[URL]"] = infop->mUrl;
- args["[MESSAGE]"] = infop->mMessage;
- args["[OBJECTNAME]"] = infop->mObjectName;
- args["[NAME]"] = owner_name;
- LLNotifyBox::showXml("LoadWebPage", args, callback_load_url, infop);
+ LLSD args;
+ args["URL"] = load_url_info["url"].asString();
+ args["MESSAGE"] = load_url_info["message"].asString();;
+ args["OBJECTNAME"] = load_url_info["object_name"].asString();
+ args["NAME"] = owner_name;
+
+ LLNotifications::instance().add("LoadWebPage", args, load_url_info);
}
else
{
@@ -5150,40 +5150,51 @@ void callback_load_url_name(const LLUUID& id, const std::string& first, const st
void process_load_url(LLMessageSystem* msg, void**)
{
- LoadUrlInfo* infop = new LoadUrlInfo;
-
- msg->getString("Data", "ObjectName", infop->mObjectName);
- msg->getUUID( "Data", "ObjectID", infop->mObjectID);
- msg->getUUID( "Data", "OwnerID", infop->mOwnerID);
- msg->getBOOL( "Data", "OwnerIsGroup", infop->mOwnerIsGroup);
- msg->getString("Data", "Message", infop->mMessage);
- msg->getString("Data", "URL", infop->mUrl);
+ LLUUID object_id;
+ LLUUID owner_id;
+ BOOL owner_is_group;
+ char object_name[256]; /* Flawfinder: ignore */
+ char message[256]; /* Flawfinder: ignore */
+ char url[256]; /* Flawfinder: ignore */
+
+ msg->getString("Data", "ObjectName", 256, object_name);
+ msg->getUUID( "Data", "ObjectID", object_id);
+ msg->getUUID( "Data", "OwnerID", owner_id);
+ msg->getBOOL( "Data", "OwnerIsGroup", owner_is_group);
+ msg->getString("Data", "Message", 256, message);
+ msg->getString("Data", "URL", 256, url);
+
+ LLSD payload;
+ payload["object_id"] = object_id;
+ payload["owner_id"] = owner_id;
+ payload["owner_is_group"] = owner_is_group;
+ payload["object_name"] = object_name;
+ payload["message"] = message;
+ payload["url"] = url;
// URL is safety checked in load_url above
// Check if object or owner is muted
- if (LLMuteList::getInstance()->isMuted(infop->mObjectID, infop->mObjectName) ||
- LLMuteList::getInstance()->isMuted(infop->mOwnerID))
+ if (LLMuteList::getInstance()->isMuted(object_id, object_name) ||
+ LLMuteList::getInstance()->isMuted(owner_id))
{
LL_INFOS("Messaging")<<"Ignoring load_url from muted object/owner."<<LL_ENDL;
- delete infop;
- infop = NULL;
return;
}
// Add to list of pending name lookups
- gLoadUrlList.push_back(infop);
+ gLoadUrlList.push_back(payload);
- gCacheName->get(infop->mOwnerID, infop->mOwnerIsGroup, callback_load_url_name);
+ gCacheName->get(owner_id, owner_is_group, callback_load_url_name);
}
void callback_download_complete(void** data, S32 result, LLExtStat ext_status)
{
std::string* filepath = (std::string*)data;
- LLStringUtil::format_map_t args;
- args["[DOWNLOAD_PATH]"] = *filepath;
- gViewerWindow->alertXml("FinishedRawDownload", args);
+ LLSD args;
+ args["DOWNLOAD_PATH"] = *filepath;
+ LLNotifications::instance().add("FinishedRawDownload", args);
delete filepath;
}
@@ -5415,3 +5426,10 @@ void invalid_message_callback(LLMessageSystem* msg,
// Please do not add more message handlers here. This file is huge.
// Put them in a file related to the functionality you are implementing. JC
+
+void LLOfferInfo::forceResponse(InventoryOfferResponse response)
+{
+ LLNotification::Params params("UserGiveItem");
+ params.functor(boost::bind(&LLOfferInfo::inventory_offer_callback, this, _1, _2));
+ LLNotifications::instance().forceResponse(params, response);
+}
diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h
index a2ed04d0a7..bbda752e89 100644
--- a/indra/newview/llviewermessage.h
+++ b/indra/newview/llviewermessage.h
@@ -192,11 +192,15 @@ void process_decline_callingcard(LLMessageSystem* msg, void**);
void invalid_message_callback(LLMessageSystem*, void*, EMessageException);
void process_initiate_download(LLMessageSystem* msg, void**);
-void inventory_offer_callback(S32 option, void* user_data);
void start_new_inventory_observer();
struct LLOfferInfo
{
+ LLOfferInfo() {};
+ LLOfferInfo(const LLSD& sd);
+
+ void forceResponse(InventoryOfferResponse response);
+
EInstantMessage mIM;
LLUUID mFromID;
BOOL mFromGroup;
@@ -208,6 +212,10 @@ struct LLOfferInfo
std::string mFromName;
std::string mDesc;
LLHost mHost;
+
+ LLSD asLLSD();
+ bool inventory_offer_callback(const LLSD& notification, const LLSD& response);
+
};
void process_feature_disabled_message(LLMessageSystem* msg, void**);
diff --git a/indra/newview/llviewerparcelmedia.cpp b/indra/newview/llviewerparcelmedia.cpp
index fe588534e5..05c589c398 100644
--- a/indra/newview/llviewerparcelmedia.cpp
+++ b/indra/newview/llviewerparcelmedia.cpp
@@ -50,7 +50,7 @@ S32 LLViewerParcelMedia::sMediaParcelLocalID = 0;
LLUUID LLViewerParcelMedia::sMediaRegionID;
// Local functions
-void callback_play_media(S32 option, void* data);
+bool callback_play_media(const LLSD& notification, const LLSD& response, LLParcel* parcel);
// Move this to its own file.
// helper class that tries to download a URL from a web site and calls a method
@@ -167,8 +167,8 @@ void LLViewerParcelMedia::update(LLParcel* parcel)
// First use warning
if( gSavedSettings.getWarning("FirstStreamingVideo") )
{
- gViewerWindow->alertXml("ParcelCanPlayMedia",
- callback_play_media, (void*)parcel);
+ LLNotifications::instance().add("ParcelCanPlayMedia", LLSD(), LLSD(),
+ boost::bind(callback_play_media, _1, _2, parcel));
}
@@ -192,7 +192,7 @@ void LLViewerParcelMedia::update(LLParcel* parcel)
{
gSavedSettings.setWarning("QuickTimeInstalled", FALSE);
- LLNotifyBox::showXml("NoQuickTime" );
+ LLNotifications::instance().add("NoQuickTime" );
};
}
}
@@ -382,9 +382,9 @@ void LLViewerParcelMedia::processParcelMediaUpdate( LLMessageSystem *msg, void *
}
}
-void callback_play_media(S32 option, void* data)
+bool callback_play_media(const LLSD& notification, const LLSD& response, LLParcel* parcel)
{
- LLParcel* parcel = (LLParcel*)data;
+ S32 option = LLNotification::getSelectedOption(notification, response);
if (option == 0)
{
gSavedSettings.setBOOL("AudioStreamingVideo", TRUE);
@@ -395,6 +395,6 @@ void callback_play_media(S32 option, void* data)
gSavedSettings.setBOOL("AudioStreamingVideo", FALSE);
}
gSavedSettings.setWarning("FirstStreamingVideo", FALSE);
-
+ return false;
}
diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp
index 6e37ec2095..099204e740 100644
--- a/indra/newview/llviewerparcelmgr.cpp
+++ b/indra/newview/llviewerparcelmgr.cpp
@@ -90,7 +90,7 @@ void callback_prepare_video(S32 option, void* data);
void prepare_video(const LLParcel *parcelp);
void start_video(const LLParcel *parcelp);
void stop_video();
-void callback_god_force_owner(S32 option, void* user_data);
+bool callback_god_force_owner(const LLSD&, const LLSD&);
struct LLGodForceOwnerData
{
@@ -515,7 +515,7 @@ LLParcelSelectionHandle LLViewerParcelMgr::selectLand(const LLVector3d &corner1,
if (region != region_other)
{
- LLNotifyBox::showXml("CantSelectLandFromMultipleRegions");
+ LLNotifications::instance().add("CantSelectLandFromMultipleRegions");
mSelected = FALSE;
notifyObservers();
return NULL;
@@ -904,7 +904,7 @@ void LLViewerParcelMgr::sendParcelGodForceOwner(const LLUUID& owner_id)
{
if (!mSelected)
{
- gViewerWindow->alertXml("CannotSetLandOwnerNothingSelected");
+ LLNotifications::instance().add("CannotSetLandOwnerNothingSelected");
return;
}
@@ -919,7 +919,7 @@ void LLViewerParcelMgr::sendParcelGodForceOwner(const LLUUID& owner_id)
if (!region)
{
// TODO: Add a force owner version of this alert.
- gViewerWindow->alertXml("CannotContentifyNoRegion");
+ LLNotifications::instance().add("CannotContentifyNoRegion");
return;
}
@@ -927,29 +927,33 @@ void LLViewerParcelMgr::sendParcelGodForceOwner(const LLUUID& owner_id)
LLViewerRegion *region2 = LLWorld::getInstance()->getRegionFromPosGlobal( east_north_region_check );
if (region != region2)
{
- gViewerWindow->alertXml("CannotSetLandOwnerMultipleRegions");
+ LLNotifications::instance().add("CannotSetLandOwnerMultipleRegions");
return;
}
llinfos << "Region " << region->getOriginGlobal() << llendl;
- LLGodForceOwnerData* data = new LLGodForceOwnerData(owner_id, mCurrentParcel->getLocalID(), region->getHost());
+ LLSD payload;
+ payload["owner_id"] = owner_id;
+ payload["parcel_local_id"] = mCurrentParcel->getLocalID();
+ payload["region_host"] = region->getHost().getIPandPort();
+ LLNotification::Params params("ForceOwnerAuctionWarning");
+ params.payload(payload).functor(callback_god_force_owner);
+
if(mCurrentParcel->getAuctionID())
{
- gViewerWindow->alertXml("ForceOwnerAuctionWarning",
- callback_god_force_owner,
- (void*)data);
+ LLNotifications::instance().add(params);
}
else
{
- callback_god_force_owner(0, (void*)data);
+ LLNotifications::instance().forceResponse(params, 0);
}
}
-void callback_god_force_owner(S32 option, void* user_data)
+bool callback_god_force_owner(const LLSD& notification, const LLSD& response)
{
- LLGodForceOwnerData* data = (LLGodForceOwnerData*)user_data;
- if(data && (0 == option))
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ if(0 == option)
{
LLMessageSystem* msg = gMessageSystem;
msg->newMessage("ParcelGodForceOwner");
@@ -957,24 +961,24 @@ void callback_god_force_owner(S32 option, void* user_data)
msg->addUUID("AgentID", gAgent.getID());
msg->addUUID("SessionID", gAgent.getSessionID());
msg->nextBlock("Data");
- msg->addUUID("OwnerID", data->mOwnerID);
- msg->addS32( "LocalID", data->mLocalID);
- msg->sendReliable(data->mHost);
+ msg->addUUID("OwnerID", notification["payload"]["owner_id"].asUUID());
+ msg->addS32( "LocalID", notification["payload"]["parcel_local_id"].asInteger());
+ msg->sendReliable(LLHost(notification["payload"]["region_host"].asString()));
}
- delete data;
+ return false;
}
void LLViewerParcelMgr::sendParcelGodForceToContent()
{
if (!mSelected)
{
- gViewerWindow->alertXml("CannotContentifyNothingSelected");
+ LLNotifications::instance().add("CannotContentifyNothingSelected");
return;
}
LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal( mWestSouth );
if (!region)
{
- gViewerWindow->alertXml("CannotContentifyNoRegion");
+ LLNotifications::instance().add("CannotContentifyNoRegion");
return;
}
@@ -992,14 +996,14 @@ void LLViewerParcelMgr::sendParcelRelease()
{
if (!mSelected)
{
- gViewerWindow->alertXml("CannotReleaseLandNothingSelected");
+ LLNotifications::instance().add("CannotReleaseLandNothingSelected");
return;
}
LLViewerRegion *region = LLWorld::getInstance()->getRegionFromPosGlobal( mWestSouth );
if (!region)
{
- gViewerWindow->alertXml("CannotReleaseLandNoRegion");
+ LLNotifications::instance().add("CannotReleaseLandNoRegion");
return;
}
@@ -1054,14 +1058,14 @@ LLViewerParcelMgr::ParcelBuyInfo* LLViewerParcelMgr::setupParcelBuy(
{
if (!mSelected || !mCurrentParcel)
{
- gViewerWindow->alertXml("CannotBuyLandNothingSelected");
+ LLNotifications::instance().add("CannotBuyLandNothingSelected");
return NULL;
}
LLViewerRegion *region = LLWorld::getInstance()->getRegionFromPosGlobal( mWestSouth );
if (!region)
{
- gViewerWindow->alertXml("CannotBuyLandNoRegion");
+ LLNotifications::instance().add("CannotBuyLandNoRegion");
return NULL;
}
@@ -1079,7 +1083,7 @@ LLViewerParcelMgr::ParcelBuyInfo* LLViewerParcelMgr::setupParcelBuy(
if (region != region2)
{
- gViewerWindow->alertXml("CantBuyLandAcrossMultipleRegions");
+ LLNotifications::instance().add("CantBuyLandAcrossMultipleRegions");
return NULL;
}
}
@@ -1160,18 +1164,18 @@ void LLViewerParcelMgr::sendParcelDeed(const LLUUID& group_id)
{
if (!mSelected || !mCurrentParcel)
{
- gViewerWindow->alertXml("CannotDeedLandNothingSelected");
+ LLNotifications::instance().add("CannotDeedLandNothingSelected");
return;
}
if(group_id.isNull())
{
- gViewerWindow->alertXml("CannotDeedLandNoGroup");
+ LLNotifications::instance().add("CannotDeedLandNoGroup");
return;
}
LLViewerRegion *region = LLWorld::getInstance()->getRegionFromPosGlobal( mWestSouth );
if (!region)
{
- gViewerWindow->alertXml("CannotDeedLandNoRegion");
+ LLNotifications::instance().add("CannotDeedLandNoRegion");
return;
}
@@ -1908,26 +1912,27 @@ void LLViewerParcelMgr::deedLandToGroup()
{
std::string group_name;
gCacheName->getGroupName(mCurrentParcel->getGroupID(), group_name);
- LLStringUtil::format_map_t args;
- args["[AREA]"] = llformat("%d", mCurrentParcel->getArea());
- args["[GROUP_NAME]"] = group_name;
+ LLSD args;
+ args["AREA"] = llformat("%d", mCurrentParcel->getArea());
+ args["GROUP_NAME"] = group_name;
if(mCurrentParcel->getContributeWithDeed())
{
std::string first_name, last_name;
gCacheName->getName(mCurrentParcel->getOwnerID(), first_name, last_name);
- args["[FIRST_NAME]"] = first_name;
- args["[LAST_NAME]"] = last_name;
- gViewerWindow->alertXml("DeedLandToGroupWithContribution",args, deedAlertCB, NULL);
+ args["FIRST_NAME"] = first_name;
+ args["LAST_NAME"] = last_name;
+ LLNotifications::instance().add("DeedLandToGroupWithContribution",args, LLSD(), deedAlertCB);
}
else
{
- gViewerWindow->alertXml("DeedLandToGroup",args, deedAlertCB, NULL);
+ LLNotifications::instance().add("DeedLandToGroup",args, LLSD(), deedAlertCB);
}
}
// static
-void LLViewerParcelMgr::deedAlertCB(S32 option, void*)
+bool LLViewerParcelMgr::deedAlertCB(const LLSD& notification, const LLSD& response)
{
+ S32 option = LLNotification::getSelectedOption(notification, response);
if (option == 0)
{
LLParcel* parcel = LLViewerParcelMgr::getInstance()->getParcelSelection()->getParcel();
@@ -1938,6 +1943,7 @@ void LLViewerParcelMgr::deedAlertCB(S32 option, void*)
}
LLViewerParcelMgr::getInstance()->sendParcelDeed(group_id);
}
+ return false;
}
@@ -1945,26 +1951,26 @@ void LLViewerParcelMgr::startReleaseLand()
{
if (!mSelected)
{
- gViewerWindow->alertXml("CannotReleaseLandNothingSelected");
+ LLNotifications::instance().add("CannotReleaseLandNothingSelected");
return;
}
if (mRequestResult == PARCEL_RESULT_NO_DATA)
{
- gViewerWindow->alertXml("CannotReleaseLandWatingForServer");
+ LLNotifications::instance().add("CannotReleaseLandWatingForServer");
return;
}
if (mRequestResult == PARCEL_RESULT_MULTIPLE)
{
- gViewerWindow->alertXml("CannotReleaseLandSelected");
+ LLNotifications::instance().add("CannotReleaseLandSelected");
return;
}
if (!isParcelOwnedByAgent(mCurrentParcel, GP_LAND_RELEASE)
&& !(gAgent.canManageEstate()))
{
- gViewerWindow->alertXml("CannotReleaseLandDontOwn");
+ LLNotifications::instance().add("CannotReleaseLandDontOwn");
return;
}
@@ -1972,31 +1978,30 @@ void LLViewerParcelMgr::startReleaseLand()
LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal(parcel_center);
if (!region)
{
- gViewerWindow->alertXml("CannotReleaseLandRegionNotFound");
+ LLNotifications::instance().add("CannotReleaseLandRegionNotFound");
return;
}
/*
if ((region->getRegionFlags() & REGION_FLAGS_BLOCK_LAND_RESELL)
&& !gAgent.isGodlike())
{
- LLStringUtil::format_map_t args;
- args["[REGION]"] = region->getName();
- gViewerWindow->alertXml("CannotReleaseLandNoTransfer", args);
+ LLSD args;
+ args["REGION"] = region->getName();
+ LLNotifications::instance().add("CannotReleaseLandNoTransfer", args);
return;
}
*/
if (!mCurrentParcelSelection->mWholeParcelSelected)
{
- gViewerWindow->alertXml("CannotReleaseLandPartialSelection");
+ LLNotifications::instance().add("CannotReleaseLandPartialSelection");
return;
}
// Compute claim price
- LLStringUtil::format_map_t args;
- args["[AREA]"] = llformat("%d",mCurrentParcel->getArea());
- gViewerWindow->alertXml("ReleaseLandWarning", args,
- releaseAlertCB, this);
+ LLSD args;
+ args["AREA"] = llformat("%d",mCurrentParcel->getArea());
+ LLNotifications::instance().add("ReleaseLandWarning", args, LLSD(), releaseAlertCB);
}
bool LLViewerParcelMgr::canAgentBuyParcel(LLParcel* parcel, bool forGroup) const
@@ -2052,38 +2057,42 @@ void LLViewerParcelMgr::startDivideLand()
{
if (!mSelected)
{
- gViewerWindow->alertXml("CannotDivideLandNothingSelected");
+ LLNotifications::instance().add("CannotDivideLandNothingSelected");
return;
}
if (mCurrentParcelSelection->mWholeParcelSelected)
{
- gViewerWindow->alertXml("CannotDivideLandPartialSelection");
+ LLNotifications::instance().add("CannotDivideLandPartialSelection");
return;
}
- gViewerWindow->alertXml("LandDivideWarning",
- callbackDivideLand,
- this);
+ LLSD payload;
+ payload["west_south_border"] = ll_sd_from_vector3d(mWestSouth);
+ payload["east_north_border"] = ll_sd_from_vector3d(mEastNorth);
+
+ LLNotifications::instance().add("LandDivideWarning", LLSD(), payload, callbackDivideLand);
}
// static
-void LLViewerParcelMgr::callbackDivideLand(S32 option, void* data)
+bool LLViewerParcelMgr::callbackDivideLand(const LLSD& notification, const LLSD& response)
{
- LLViewerParcelMgr* self = (LLViewerParcelMgr*)data;
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ LLVector3d west_south_d = ll_vector3d_from_sd(notification["payload"]["west_south_border"]);
+ LLVector3d east_north_d = ll_vector3d_from_sd(notification["payload"]["east_north_border"]);
+ LLVector3d parcel_center = (west_south_d + east_north_d) / 2.0;
- LLVector3d parcel_center = (self->mWestSouth + self->mEastNorth) / 2.0;
LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal(parcel_center);
if (!region)
{
- gViewerWindow->alertXml("CannotDivideLandNoRegion");
- return;
+ LLNotifications::instance().add("CannotDivideLandNoRegion");
+ return false;
}
if (0 == option)
{
- LLVector3 west_south = region->getPosRegionFromGlobal(self->mWestSouth);
- LLVector3 east_north = region->getPosRegionFromGlobal(self->mEastNorth);
+ LLVector3 west_south = region->getPosRegionFromGlobal(west_south_d);
+ LLVector3 east_north = region->getPosRegionFromGlobal(east_north_d);
LLMessageSystem* msg = gMessageSystem;
msg->newMessage("ParcelDivide");
@@ -2097,6 +2106,7 @@ void LLViewerParcelMgr::callbackDivideLand(S32 option, void* data)
msg->addF32("North", east_north.mV[VY]);
msg->sendReliable(region->getHost());
}
+ return false;
}
@@ -2104,44 +2114,48 @@ void LLViewerParcelMgr::startJoinLand()
{
if (!mSelected)
{
- gViewerWindow->alertXml("CannotJoinLandNothingSelected");
+ LLNotifications::instance().add("CannotJoinLandNothingSelected");
return;
}
if (mCurrentParcelSelection->mWholeParcelSelected)
{
- gViewerWindow->alertXml("CannotJoinLandEntireParcelSelected");
+ LLNotifications::instance().add("CannotJoinLandEntireParcelSelected");
return;
}
if (!mCurrentParcelSelection->mSelectedMultipleOwners)
{
- gViewerWindow->alertXml("CannotJoinLandSelection");
+ LLNotifications::instance().add("CannotJoinLandSelection");
return;
}
- gViewerWindow->alertXml("JoinLandWarning",
- callbackJoinLand,
- this);
+ LLSD payload;
+ payload["west_south_border"] = ll_sd_from_vector3d(mWestSouth);
+ payload["east_north_border"] = ll_sd_from_vector3d(mEastNorth);
+
+ LLNotifications::instance().add("JoinLandWarning", LLSD(), payload, callbackJoinLand);
}
// static
-void LLViewerParcelMgr::callbackJoinLand(S32 option, void* data)
+bool LLViewerParcelMgr::callbackJoinLand(const LLSD& notification, const LLSD& response)
{
- LLViewerParcelMgr* self = (LLViewerParcelMgr*)data;
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ LLVector3d west_south_d = ll_vector3d_from_sd(notification["payload"]["west_south_border"]);
+ LLVector3d east_north_d = ll_vector3d_from_sd(notification["payload"]["east_north_border"]);
+ LLVector3d parcel_center = (west_south_d + east_north_d) / 2.0;
- LLVector3d parcel_center = (self->mWestSouth + self->mEastNorth) / 2.0;
LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal(parcel_center);
if (!region)
{
- gViewerWindow->alertXml("CannotJoinLandNoRegion");
- return;
+ LLNotifications::instance().add("CannotJoinLandNoRegion");
+ return false;
}
if (0 == option)
{
- LLVector3 west_south = region->getPosRegionFromGlobal(self->mWestSouth);
- LLVector3 east_north = region->getPosRegionFromGlobal(self->mEastNorth);
+ LLVector3 west_south = region->getPosRegionFromGlobal(west_south_d);
+ LLVector3 east_north = region->getPosRegionFromGlobal(east_north_d);
LLMessageSystem* msg = gMessageSystem;
msg->newMessage("ParcelJoin");
@@ -2155,6 +2169,7 @@ void LLViewerParcelMgr::callbackJoinLand(S32 option, void* data)
msg->addF32("North", east_north.mV[VY]);
msg->sendReliable(region->getHost());
}
+ return false;
}
@@ -2162,19 +2177,19 @@ void LLViewerParcelMgr::startDeedLandToGroup()
{
if (!mSelected || !mCurrentParcel)
{
- gViewerWindow->alertXml("CannotDeedLandNothingSelected");
+ LLNotifications::instance().add("CannotDeedLandNothingSelected");
return;
}
if (mRequestResult == PARCEL_RESULT_NO_DATA)
{
- gViewerWindow->alertXml("CannotDeedLandWaitingForServer");
+ LLNotifications::instance().add("CannotDeedLandWaitingForServer");
return;
}
if (mRequestResult == PARCEL_RESULT_MULTIPLE)
{
- gViewerWindow->alertXml("CannotDeedLandMultipleSelected");
+ LLNotifications::instance().add("CannotDeedLandMultipleSelected");
return;
}
@@ -2182,7 +2197,7 @@ void LLViewerParcelMgr::startDeedLandToGroup()
LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal(parcel_center);
if (!region)
{
- gViewerWindow->alertXml("CannotDeedLandNoRegion");
+ LLNotifications::instance().add("CannotDeedLandNoRegion");
return;
}
@@ -2192,9 +2207,9 @@ void LLViewerParcelMgr::startDeedLandToGroup()
if((region->getRegionFlags() & REGION_FLAGS_BLOCK_LAND_RESELL)
&& (mCurrentParcel->getOwnerID() != region->getOwner()))
{
- LLStringUtil::format_map_t args;
- args["[REGION]"] = region->getName();
- gViewerWindow->alertXml("CannotDeedLandNoTransfer", args);
+ LLSD args;
+ args["REGION"] = region->getName();
+ LLNotifications::instance().add("CannotDeedLandNoTransfer", args);
return;
}
}
@@ -2222,13 +2237,15 @@ void LLViewerParcelMgr::reclaimParcel()
}
// static
-void LLViewerParcelMgr::releaseAlertCB(S32 option, void *)
+bool LLViewerParcelMgr::releaseAlertCB(const LLSD& notification, const LLSD& response)
{
+ S32 option = LLNotification::getSelectedOption(notification, response);
if (option == 0)
{
// Send the release message, not a force
LLViewerParcelMgr::getInstance()->sendParcelRelease();
}
+ return false;
}
void LLViewerParcelMgr::buyPass()
diff --git a/indra/newview/llviewerparcelmgr.h b/indra/newview/llviewerparcelmgr.h
index 4326e07e46..920423cdfa 100644
--- a/indra/newview/llviewerparcelmgr.h
+++ b/indra/newview/llviewerparcelmgr.h
@@ -110,7 +110,7 @@ public:
void selectCollisionParcel();
// Select the parcel at a specific point
- LLSafeHandle<LLParcelSelection> selectParcelAt(const LLVector3d& pos_global);
+ LLParcelSelectionHandle selectParcelAt(const LLVector3d& pos_global);
// Take the current rectangle select, and select the parcel contained
// within it.
@@ -259,7 +259,7 @@ public:
static BOOL isParcelModifiableByAgent(const LLParcel* parcelp, U64 group_proxy_power);
private:
- static void releaseAlertCB(S32 option, void *data);
+ static bool releaseAlertCB(const LLSD& notification, const LLSD& response);
// If the user is claiming land and the current selection
// borders a piece of land the user already owns, ask if he
@@ -272,12 +272,10 @@ private:
// move land from current owner to it's group.
void deedLandToGroup();
- static void claimAlertCB(S32 option, void* data);
- static void buyAlertCB(S32 option, void* data);
- static void deedAlertCB(S32 option, void*);
+ static bool deedAlertCB(const LLSD& notification, const LLSD& response);
- static void callbackDivideLand(S32 option, void* data);
- static void callbackJoinLand(S32 option, void* data);
+ static bool callbackDivideLand(const LLSD& notification, const LLSD& response);
+ static bool callbackJoinLand(const LLSD& notification, const LLSD& response);
//void finishClaim(BOOL user_to_user_sale, U32 join);
LLViewerImage* getBlockedImage() const;
diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp
index c2c3e7e320..50486137c1 100644
--- a/indra/newview/llviewertexteditor.cpp
+++ b/indra/newview/llviewertexteditor.cpp
@@ -1420,58 +1420,50 @@ void LLViewerTextEditor::openEmbeddedLandmark( LLInventoryItem* item )
void LLViewerTextEditor::openEmbeddedNotecard( LLInventoryItem* item )
{
- //if (saved)
- //{
- // An LLInventoryItem needs to be in an inventory to be opened.
- // This will give the item to the viewer's agent.
- // The callback will attempt to open it if its not already opened.
copyInventory(item, gInventoryCallbacks.registerCB(mInventoryCallback));
-
- //}
- //else
- //{
- // LLNotecardCopyInfo *info = new LLNotecardCopyInfo(this, item);
- // gViewerWindow->alertXml("ConfirmNotecardSave",
- // LLViewerTextEditor::onNotecardDialog, (void*)info);
- //}
}
void LLViewerTextEditor::showUnsavedAlertDialog( LLInventoryItem* item )
{
- LLNotecardCopyInfo *info = new LLNotecardCopyInfo(this, item);
- gViewerWindow->alertXml( "ConfirmNotecardSave",
- LLViewerTextEditor::onNotecardDialog, (void*)info);
+ LLSD payload;
+ payload["item_id"] = item->getUUID();
+ payload["notecard_id"] = mNotecardInventoryID;
+ LLNotifications::instance().add( "ConfirmNotecardSave", LLSD(), payload, LLViewerTextEditor::onNotecardDialog);
}
+
// static
-void LLViewerTextEditor::onNotecardDialog( S32 option, void* userdata )
+bool LLViewerTextEditor::onNotecardDialog(const LLSD& notification, const LLSD& response )
{
- LLNotecardCopyInfo *info = (LLNotecardCopyInfo *)userdata;
+ S32 option = LLNotification::getSelectedOption(notification, response);
if( option == 0 )
{
// itemptr is deleted by LLPreview::save
- LLPointer<LLInventoryItem>* itemptr = new LLPointer<LLInventoryItem>(info->mItem);
- LLPreview::save( info->mTextEd->mNotecardInventoryID, itemptr);
+ LLPointer<LLInventoryItem>* itemptr = new LLPointer<LLInventoryItem>(gInventory.getItem(notification["payload"]["item_id"].asUUID()));
+ LLPreview::save( notification["payload"]["notecard_id"].asUUID() , itemptr);
}
+ return false;
}
void LLViewerTextEditor::showCopyToInvDialog( LLInventoryItem* item )
{
- LLNotecardCopyInfo *info = new LLNotecardCopyInfo(this, item);
- gViewerWindow->alertXml( "ConfirmItemCopy",
- LLViewerTextEditor::onCopyToInvDialog, (void*)info);
+ LLSD payload;
+ payload["item_id"] = item->getUUID();
+ payload["notecard_id"] = mNotecardInventoryID;
+ LLNotifications::instance().add( "ConfirmItemCopy", LLSD(), payload,
+ boost::bind(&LLViewerTextEditor::onCopyToInvDialog, this, _1, _2));
}
-// static
-void LLViewerTextEditor::onCopyToInvDialog( S32 option, void* userdata )
+bool LLViewerTextEditor::onCopyToInvDialog(const LLSD& notification, const LLSD& response)
{
- LLNotecardCopyInfo *info = (LLNotecardCopyInfo *)userdata;
+ S32 option = LLNotification::getSelectedOption(notification, response);
if( 0 == option )
{
- info->mTextEd->copyInventory(info->mItem);
+ LLInventoryItem* itemp = gInventory.getItem(notification["payload"]["item_id"].asUUID());
+ copyInventory(itemp);
}
- delete info;
+ return false;
}
diff --git a/indra/newview/llviewertexteditor.h b/indra/newview/llviewertexteditor.h
index 7ce28fc60a..2e1c0f1d86 100644
--- a/indra/newview/llviewertexteditor.h
+++ b/indra/newview/llviewertexteditor.h
@@ -113,8 +113,8 @@ private:
void showCopyToInvDialog( LLInventoryItem* item );
void showUnsavedAlertDialog( LLInventoryItem* item );
- static void onCopyToInvDialog( S32 option, void* userdata );
- static void onNotecardDialog( S32 option, void* userdata );
+ bool onCopyToInvDialog(const LLSD& notification, const LLSD& response );
+ static bool onNotecardDialog(const LLSD& notification, const LLSD& response );
LLPointer<LLInventoryItem> mDragItem;
BOOL mDragItemSaved;
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 48b4a79afa..a129fac47b 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -182,6 +182,9 @@
#include "llviewerjoystick.h"
#include "llviewernetwork.h"
+#include "llfloatertest.h" // HACK!
+#include "llfloaternotificationsconsole.h"
+
#if LL_WINDOWS
#include <tchar.h> // For Unicode conversion methods
#endif
@@ -246,6 +249,7 @@ std::string LLViewerWindow::sMovieBaseName;
extern void toggle_debug_menus(void*);
+
////////////////////////////////////////////////////////////////////////////
//
// LLDebugText
@@ -1421,6 +1425,13 @@ LLViewerWindow::LLViewerWindow(
mIsFullscreenChecked(false),
mCurrResolutionIndex(0)
{
+ // these are self registering so they don't need to be retained here
+ new LLNotificationChannel("VW_alerts", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alert"));
+ new LLNotificationChannel("VW_alertmodal", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alertmodal"));
+
+ LLNotifications::instance().getChannel("VW_alerts")->connectChanged(&LLViewerWindow::onAlert);
+ LLNotifications::instance().getChannel("VW_alertmodal")->connectChanged(&LLViewerWindow::onAlert);
+
// Default to application directory.
LLViewerWindow::sSnapshotBaseName = "Snapshot";
LLViewerWindow::sMovieBaseName = "SLmovie";
@@ -1532,8 +1543,6 @@ LLViewerWindow::LLViewerWindow(
// Can't have spaces in settings.ini strings, so use underscores instead and convert them.
LLStringUtil::replaceChar(mOverlayTitle, '_', ' ');
- LLAlertDialog::setDisplayCallback(alertCallback); // call this before calling any modal dialogs
-
// sync the keyboard's setting with the saved setting
gSavedSettings.getControl("NumpadControl")->firePropertyChanged();
@@ -2179,7 +2188,7 @@ void LLViewerWindow::setNormalControlsVisible( BOOL visible )
void LLViewerWindow::setMenuBackgroundColor(bool god_mode, bool dev_grid)
{
- LLStringUtil::format_map_t args;
+ LLSD args;
LLColor4 new_bg_color;
if(god_mode && LLViewerLogin::getInstance()->isInProductionGrid())
@@ -2232,12 +2241,6 @@ void LLViewerWindow::draw()
stop_glerror();
LLUI::setLineWidth(1.f);
- //popup alerts from the UI
- LLAlertInfo alert;
- while (LLPanel::nextAlert(alert))
- {
- alertXml(alert.mLabel, alert.mArgs);
- }
LLUI::setLineWidth(1.f);
// Reset any left-over transforms
@@ -2421,6 +2424,15 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
}
}
+ // Debugging view for unified notifications
+ if ((MASK_SHIFT & mask)
+ && (MASK_CONTROL & mask)
+ && ('N' == key || 'n' == key))
+ {
+ LLFloaterNotificationConsole::showInstance();
+ return TRUE;
+ }
+
// handle escape key
//if (key == KEY_ESCAPE && mask == MASK_NONE)
//{
@@ -4909,10 +4921,10 @@ BOOL LLViewerWindow::changeDisplaySettings(BOOL fullscreen, LLCoordScreen size,
if (!result_first_try)
{
- LLStringUtil::format_map_t args;
- args["[RESX]"] = llformat("%d",size.mX);
- args["[RESY]"] = llformat("%d",size.mY);
- alertXml("ResolutionSwitchFail", args);
+ LLSD args;
+ args["RESX"] = llformat("%d",size.mX);
+ args["RESY"] = llformat("%d",size.mY);
+ LLNotifications::instance().add("ResolutionSwitchFail", args);
size = old_size; // for reshape below
}
@@ -5027,72 +5039,18 @@ S32 LLViewerWindow::getChatConsoleBottomPad()
//----------------------------------------------------------------------------
-// static
-bool LLViewerWindow::alertCallback(S32 modal)
-{
- if (gNoRender)
- {
- return false;
- }
- else
- {
-// if (modal) // we really always want to take you out of mouselook
- {
- // If we're in mouselook, the mouse is hidden and so the user can't click
- // the dialog buttons. In that case, change to First Person instead.
- if( gAgent.cameraMouselook() )
- {
- gAgent.changeCameraToDefault();
- }
- }
- return true;
- }
-}
-
-LLAlertDialog* LLViewerWindow::alertXml(const std::string& xml_filename,
- LLAlertDialog::alert_callback_t callback, void* user_data)
-{
- LLStringUtil::format_map_t args;
- return alertXml( xml_filename, args, callback, user_data );
-}
-LLAlertDialog* LLViewerWindow::alertXml(const std::string& xml_filename, const LLStringUtil::format_map_t& args,
- LLAlertDialog::alert_callback_t callback, void* user_data)
+//static
+bool LLViewerWindow::onAlert(const LLSD& notify)
{
- if (gNoRender)
- {
- llinfos << "Alert: " << xml_filename << llendl;
- if (callback)
- {
- callback(-1, user_data);
- }
- return NULL;
- }
+ LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID());
- // If we're in mouselook, the mouse is hidden and so the user can't click
- // the dialog buttons. In that case, change to First Person instead.
- if( gAgent.cameraMouselook() )
- {
- gAgent.changeCameraToDefault();
- }
-
- // Note: object adds, removes, and destroys itself.
- return LLAlertDialog::showXml( xml_filename, args, callback, user_data );
-}
-
-LLAlertDialog* LLViewerWindow::alertXmlEditText(const std::string& xml_filename, const LLStringUtil::format_map_t& args,
- LLAlertDialog::alert_callback_t callback, void* user_data,
- LLAlertDialog::alert_text_callback_t text_callback, void *text_data,
- const LLStringUtil::format_map_t& edit_args, BOOL draw_asterixes)
-{
if (gNoRender)
{
- llinfos << "Alert: " << xml_filename << llendl;
- if (callback)
- {
- callback(-1, user_data);
- }
- return NULL;
+ llinfos << "Alert: " << notification->getName() << llendl;
+ notification->respond(LLSD::emptyMap());
+ LLNotifications::instance().cancel(notification);
+ return false;
}
// If we're in mouselook, the mouse is hidden and so the user can't click
@@ -5101,20 +5059,7 @@ LLAlertDialog* LLViewerWindow::alertXmlEditText(const std::string& xml_filename,
{
gAgent.changeCameraToDefault();
}
-
- // Note: object adds, removes, and destroys itself.
- LLAlertDialog* alert = LLAlertDialog::createXml( xml_filename, args, callback, user_data );
- if (alert)
- {
- if (text_callback)
- {
- alert->setEditTextCallback(text_callback, text_data);
- }
- alert->setEditTextArgs(edit_args);
- alert->setDrawAsterixes(draw_asterixes);
- alert->show();
- }
- return alert;
+ return false;
}
////////////////////////////////////////////////////////////////////////////
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index 6309cec819..d6c27a31bc 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -47,6 +47,7 @@
#include "lltimer.h"
#include "llstat.h"
#include "llalertdialog.h"
+#include "llnotifications.h"
class LLView;
class LLViewerObject;
@@ -353,20 +354,10 @@ public:
void drawPickBuffer() const;
- LLAlertDialog* alertXml(const std::string& xml_filename,
- LLAlertDialog::alert_callback_t callback = NULL, void* user_data = NULL);
- LLAlertDialog* alertXml(const std::string& xml_filename, const LLStringUtil::format_map_t& args,
- LLAlertDialog::alert_callback_t callback = NULL, void* user_data = NULL);
- LLAlertDialog* alertXmlEditText(const std::string& xml_filename, const LLStringUtil::format_map_t& args,
- LLAlertDialog::alert_callback_t callback, void* user_data,
- LLAlertDialog::alert_text_callback_t text_callback, void *text_data,
- const LLStringUtil::format_map_t& edit_args = LLStringUtil::format_map_t(),
- BOOL draw_asterixes = FALSE);
-
- static bool alertCallback(S32 modal);
-
private:
bool shouldShowToolTipFor(LLMouseHandler *mh);
+ static bool onAlert(const LLSD& notify);
+
void switchToolByMask(MASK mask);
void destroyWindow();
void drawMouselookInstructions();
diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp
index d416ae5bf6..d644ad5085 100644
--- a/indra/newview/llvograss.cpp
+++ b/indra/newview/llvograss.cpp
@@ -109,12 +109,6 @@ void LLVOGrass::updateSpecies()
}
-void alert_done(S32 option, void* user_data)
-{
- return;
-}
-
-
void LLVOGrass::initClass()
{
LLVector3 pos(0.0f, 0.0f, 0.0f);
@@ -224,9 +218,9 @@ void LLVOGrass::initClass()
if (!have_all_grass)
{
- LLStringUtil::format_map_t args;
- args["[SPECIES]"] = err;
- gViewerWindow->alertXml("ErrorUndefinedGrasses", args, alert_done );
+ LLSD args;
+ args["SPECIES"] = err;
+ LLNotifications::instance().add("ErrorUndefinedGrasses", args);
}
for (S32 i = 0; i < GRASS_MAX_BLADES; ++i)
diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index 8b1eba11a0..fb28420715 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -4188,7 +4188,7 @@ class LLViewerRequiredVoiceVersion : public LLHTTPNode
if (!sAlertedUser)
{
//sAlertedUser = TRUE;
- gViewerWindow->alertXml("VoiceVersionMismatch");
+ LLNotifications::instance().add("VoiceVersionMismatch");
gSavedSettings.setBOOL("EnableVoiceChat", FALSE); // toggles listener
}
}
diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp
index 7e3b96eb8f..486ecb82e3 100644
--- a/indra/newview/llvotree.cpp
+++ b/indra/newview/llvotree.cpp
@@ -253,9 +253,9 @@ void LLVOTree::initClass()
if (!have_all_trees)
{
- LLStringUtil::format_map_t args;
- args["[SPECIES]"] = err;
- gViewerWindow->alertXml("ErrorUndefinedTrees", args );
+ LLSD args;
+ args["SPECIES"] = err;
+ LLNotifications::instance().add("ErrorUndefinedTrees", args);
}
};
diff --git a/indra/newview/llwearable.cpp b/indra/newview/llwearable.cpp
index ef077101e9..c473fed04a 100644
--- a/indra/newview/llwearable.cpp
+++ b/indra/newview/llwearable.cpp
@@ -867,9 +867,9 @@ void LLWearable::saveNewAsset()
std::string buffer = llformat("Unable to save '%s' to wearable file.", mName.c_str());
llwarns << buffer << llendl;
- LLStringUtil::format_map_t args;
- args["[NAME]"] = mName;
- gViewerWindow->alertXml("CannotSaveWearableOutOfSpace", args);
+ LLSD args;
+ args["NAME"] = mName;
+ LLNotifications::instance().add("CannotSaveWearableOutOfSpace", args);
return;
}
@@ -915,9 +915,9 @@ void LLWearable::onSaveNewAssetComplete(const LLUUID& new_asset_id, void* userda
{
std::string buffer = llformat("Unable to save %s to central asset store.", type_name.c_str());
llwarns << buffer << " Status: " << status << llendl;
- LLStringUtil::format_map_t args;
- args["[NAME]"] = type_name;
- gViewerWindow->alertXml("CannotSaveToAssetStore", args);
+ LLSD args;
+ args["NAME"] = type_name;
+ LLNotifications::instance().add("CannotSaveToAssetStore", args);
}
// Delete temp file
diff --git a/indra/newview/llwearablelist.cpp b/indra/newview/llwearablelist.cpp
index a32c43302d..70719b827c 100644
--- a/indra/newview/llwearablelist.cpp
+++ b/indra/newview/llwearablelist.cpp
@@ -149,27 +149,27 @@ void LLWearableList::processGetAssetReply( const char* filename, const LLAssetID
{
// Fail
break;
- }
+ }
default:
- {
+ {
static const S32 MAX_RETRIES = 3;
if (data->mRetries < MAX_RETRIES)
{
- // Try again
+ // Try again
data->mRetries++;
- gAssetStorage->getAssetData(uuid,
- data->mAssetType,
- LLWearableList::processGetAssetReply,
- userdata); // re-use instead of deleting.
- return;
- }
+ gAssetStorage->getAssetData(uuid,
+ data->mAssetType,
+ LLWearableList::processGetAssetReply,
+ userdata); // re-use instead of deleting.
+ return;
+ }
else
{
// Fail
break;
}
}
- }
+ }
}
if (wearable) // success
@@ -180,17 +180,17 @@ void LLWearableList::processGetAssetReply( const char* filename, const LLAssetID
}
else
{
- LLStringUtil::format_map_t args;
+ LLSD args;
// *TODO:translate
- args["[TYPE]"] = LLAssetType::lookupHumanReadable(data->mAssetType);
+ args["TYPE"] = LLAssetType::lookupHumanReadable(data->mAssetType);
if (data->mName.empty())
{
- LLNotifyBox::showXml("FailedToFindWearableUnnamed", args);
+ LLNotifications::instance().add("FailedToFindWearableUnnamed", args);
}
else
{
- args["[DESC]"] = data->mName;
- LLNotifyBox::showXml("FailedToFindWearable", args);
+ args["DESC"] = data->mName;
+ LLNotifications::instance().add("FailedToFindWearable", args);
}
}
// Always call callback; wearable will be NULL if we failed
diff --git a/indra/newview/llwldaycycle.cpp b/indra/newview/llwldaycycle.cpp
index 1abf760580..9f8ddc1029 100644
--- a/indra/newview/llwldaycycle.cpp
+++ b/indra/newview/llwldaycycle.cpp
@@ -82,9 +82,9 @@ void LLWLDayCycle::loadDayCycle(const std::string & fileName)
if(!success)
{
// alert the user
- LLStringUtil::format_map_t args;
- args["[SKY]"] = day_data[i][1].asString();
- gViewerWindow->alertXml("WLMissingSky", args);
+ LLSD args;
+ args["SKY"] = day_data[i][1].asString();
+ LLNotifications::instance().add("WLMissingSky", args);
continue;
}
diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp
index d9c6b6c58a..7fbcaf6c21 100644
--- a/indra/newview/llxmlrpctransaction.cpp
+++ b/indra/newview/llxmlrpctransaction.cpp
@@ -417,28 +417,10 @@ void LLXMLRPCTransaction::Impl::setStatus(Status status,
mStatusMessage =
"Despite our best efforts, something unexpected has gone wrong. \n"
" \n"
- "Please check www.secondlife.com/status \n"
+ "Please check secondlife.com/status \n"
"to see if there is a known problem with the service.";
mStatusURI = "http://secondlife.com/status/";
- /*
- mStatusMessage =
- "Despite our best efforts, something unexpected has gone wrong.\n"
- "Please go to the Support section of the SecondLife.com web site\n"
- "and report the problem. If possible, include your SecondLife.log\n"
- "file from:\n"
-#if LL_WINDOWS
- "C:\\Documents and Settings\\<name>\\Application Data\\SecondLife\\logs\n"
-#elif LL_DARWIN
- "~/Library/Application Support/SecondLife/logs\n"
-#elif LL_LINUX
- "~/.secondlife/logs\n"
-#else
-#error "Need platform here."
-#endif
- "Thank you.";
- mStatusURI = "http://secondlife.com/community/support.php";
- */
}
}
}