summaryrefslogtreecommitdiff
path: root/indra/llui
diff options
context:
space:
mode:
authorSteve Bennetts <steve@lindenlab.com>2009-10-23 12:18:46 -0700
committerSteve Bennetts <steve@lindenlab.com>2009-10-23 12:18:46 -0700
commit4ddaa866dde7a92e56617a32464e0667de3759ef (patch)
treed28e7e39f8a5f4a1070482154824fbfb2a7b52e8 /indra/llui
parenta5453d45feaceb713c7cece76d88c2d2b8f825c6 (diff)
parent80b682d4b4dd1256ee09dd3327d2c51e3adee0b5 (diff)
merge
Diffstat (limited to 'indra/llui')
-rw-r--r--indra/llui/CMakeLists.txt4
-rw-r--r--indra/llui/llconsole.cpp5
-rw-r--r--indra/llui/llfloater.cpp46
-rw-r--r--indra/llui/llfloater.h12
-rw-r--r--indra/llui/llfloaterreg.cpp14
-rw-r--r--indra/llui/llfloaterreg.h1
-rw-r--r--indra/llui/llfloaterreglistener.cpp114
-rw-r--r--indra/llui/llfloaterreglistener.h36
-rw-r--r--indra/llui/llfunctorregistry.cpp1
-rw-r--r--indra/llui/llmodaldialog.cpp15
-rw-r--r--indra/llui/llmodaldialog.h3
-rw-r--r--indra/llui/llnotifications.cpp3
-rw-r--r--indra/llui/llnotifications.h17
-rw-r--r--indra/llui/llnotificationslistener.cpp55
-rw-r--r--indra/llui/llnotificationslistener.h34
-rw-r--r--indra/llui/llslider.cpp2
-rw-r--r--indra/llui/llsliderctrl.cpp1
-rw-r--r--indra/llui/llui.cpp7
-rw-r--r--indra/llui/llview.cpp12
-rw-r--r--indra/llui/llview.h5
20 files changed, 346 insertions, 41 deletions
diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt
index f4d1284095..f0b4436df5 100644
--- a/indra/llui/CMakeLists.txt
+++ b/indra/llui/CMakeLists.txt
@@ -43,6 +43,7 @@ set(llui_SOURCE_FILES
llflatlistview.cpp
llfloater.cpp
llfloaterreg.cpp
+ llfloaterreglistener.cpp
llflyoutbutton.cpp
llfocusmgr.cpp
llfunctorregistry.cpp
@@ -58,6 +59,7 @@ set(llui_SOURCE_FILES
llmultislider.cpp
llmultisliderctrl.cpp
llnotifications.cpp
+ llnotificationslistener.cpp
llpanel.cpp
llprogressbar.cpp
llradiogroup.cpp
@@ -127,6 +129,7 @@ set(llui_HEADER_FILES
llflatlistview.h
llfloater.h
llfloaterreg.h
+ llfloaterreglistener.h
llflyoutbutton.h
llfocusmgr.h
llfunctorregistry.h
@@ -145,6 +148,7 @@ set(llui_HEADER_FILES
llmultisliderctrl.h
llmultislider.h
llnotifications.h
+ llnotificationslistener.h
llpanel.h
llprogressbar.h
llradiogroup.h
diff --git a/indra/llui/llconsole.cpp b/indra/llui/llconsole.cpp
index 285ce82d2d..e0053b4cc7 100644
--- a/indra/llui/llconsole.cpp
+++ b/indra/llui/llconsole.cpp
@@ -120,6 +120,11 @@ void LLConsole::setFontSize(S32 size_index)
{
mFont = LLFontGL::getFontSansSerifHuge();
}
+ // Make sure the font exists
+ if (mFont == NULL)
+ {
+ mFont = LLFontGL::getFontDefault();
+ }
for(paragraph_t::iterator paragraph_it = mParagraphs.begin(); paragraph_it != mParagraphs.end(); paragraph_it++)
{
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 0c0c5921ce..021e2e94ac 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -61,6 +61,7 @@
#include "lltrans.h"
#include "llhelp.h"
#include "llmultifloater.h"
+#include "llsdutil.h"
// use this to control "jumping" behavior when Ctrl-Tabbing
const S32 TABBED_FLOATER_OFFSET = 0;
@@ -132,6 +133,16 @@ LLFloater::handle_map_t LLFloater::sFloaterMap;
LLFloaterView* gFloaterView = NULL;
+/*==========================================================================*|
+// DEV-38598: The fundamental problem with this operation is that it can only
+// support a subset of LLSD values. While it's plausible to compare two arrays
+// lexicographically, what strict ordering can you impose on maps?
+// (LLFloaterTOS's current key is an LLSD map.)
+
+// Of course something like this is necessary if you want to build a std::set
+// or std::map with LLSD keys. Fortunately we're getting by with other
+// container types for now.
+
//static
bool LLFloater::KeyCompare::compare(const LLSD& a, const LLSD& b)
{
@@ -159,32 +170,11 @@ bool LLFloater::KeyCompare::compare(const LLSD& a, const LLSD& b)
else
return false; // no valid operation for Binary
}
+|*==========================================================================*/
bool LLFloater::KeyCompare::equate(const LLSD& a, const LLSD& b)
{
- if (a.type() != b.type())
- {
- //llerrs << "Mismatched LLSD types: (" << a << ") mismatches (" << b << ")" << llendl;
- return false;
- }
- else if (a.isUndefined())
- return true;
- else if (a.isInteger())
- return a.asInteger() == b.asInteger();
- else if (a.isReal())
- return a.asReal() == b.asReal();
- else if (a.isString())
- return a.asString() == b.asString();
- else if (a.isUUID())
- return a.asUUID() == b.asUUID();
- else if (a.isDate())
- return a.asDate() == b.asDate();
- else if (a.isURI())
- return a.asString() == b.asString(); // compare URIs as strings
- else if (a.isBoolean())
- return a.asBoolean() == b.asBoolean();
- else
- return false; // no valid operation for Binary
+ return llsd_equals(a, b);
}
//************************************
@@ -2629,3 +2619,13 @@ bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr o
return true; // *TODO: Error checking
}
+bool LLFloater::isShown() const
+{
+ return ! isMinimized() && isInVisibleChain();
+}
+
+/* static */
+bool LLFloater::isShown(const LLFloater* floater)
+{
+ return floater && floater->isShown();
+}
diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h
index 123de12398..2fdaecf59a 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -87,12 +87,14 @@ friend class LLMultiFloater;
public:
struct KeyCompare
{
- static bool compare(const LLSD& a, const LLSD& b);
+// static bool compare(const LLSD& a, const LLSD& b);
static bool equate(const LLSD& a, const LLSD& b);
+/*==========================================================================*|
bool operator()(const LLSD& a, const LLSD& b) const
{
return compare(a, b);
}
+|*==========================================================================*/
};
enum EFloaterButtons
@@ -183,7 +185,13 @@ public:
void addDependentFloater(LLHandle<LLFloater> dependent_handle, BOOL reposition = TRUE);
LLFloater* getDependee() { return (LLFloater*)mDependeeHandle.get(); }
void removeDependentFloater(LLFloater* dependent);
- BOOL isMinimized() { return mMinimized; }
+ BOOL isMinimized() const { return mMinimized; }
+ /// isShown() differs from getVisible() in that isShown() also considers
+ /// isMinimized(). isShown() is true only if visible and not minimized.
+ bool isShown() const;
+ /// The static isShown() can accept a NULL pointer (which of course
+ /// returns false). When non-NULL, it calls the non-static isShown().
+ static bool isShown(const LLFloater* floater);
BOOL isFrontmost();
BOOL isDependent() { return !mDependeeHandle.isDead(); }
void setCanMinimize(BOOL can_minimize);
diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp
index 815260dff3..3c5a8a6921 100644
--- a/indra/llui/llfloaterreg.cpp
+++ b/indra/llui/llfloaterreg.cpp
@@ -36,6 +36,7 @@
#include "llfloater.h"
#include "llmultifloater.h"
+#include "llfloaterreglistener.h"
//*******************************************************
@@ -45,6 +46,8 @@ LLFloaterReg::instance_map_t LLFloaterReg::sInstanceMap;
LLFloaterReg::build_map_t LLFloaterReg::sBuildMap;
std::map<std::string,std::string> LLFloaterReg::sGroupMap;
+static LLFloaterRegListener sFloaterRegListener("LLFloaterReg");
+
//*******************************************************
//static
@@ -249,7 +252,7 @@ bool LLFloaterReg::hideInstance(const std::string& name, const LLSD& key)
bool LLFloaterReg::toggleInstance(const std::string& name, const LLSD& key)
{
LLFloater* instance = findInstance(name, key);
- if (instance && !instance->isMinimized() && instance->isInVisibleChain())
+ if (LLFloater::isShown(instance))
{
// When toggling *visibility*, close the host instead of the floater when hosted
if (instance->getHost())
@@ -269,14 +272,7 @@ bool LLFloaterReg::toggleInstance(const std::string& name, const LLSD& key)
bool LLFloaterReg::instanceVisible(const std::string& name, const LLSD& key)
{
LLFloater* instance = findInstance(name, key);
- if (instance && !instance->isMinimized() && instance->isInVisibleChain())
- {
- return true;
- }
- else
- {
- return false;
- }
+ return LLFloater::isShown(instance);
}
//static
diff --git a/indra/llui/llfloaterreg.h b/indra/llui/llfloaterreg.h
index 7edac43c96..451bd1dbe3 100644
--- a/indra/llui/llfloaterreg.h
+++ b/indra/llui/llfloaterreg.h
@@ -70,6 +70,7 @@ public:
typedef std::map<std::string, BuildData> build_map_t;
private:
+ friend class LLFloaterRegListener;
static instance_list_t sNullInstanceList;
static instance_map_t sInstanceMap;
static build_map_t sBuildMap;
diff --git a/indra/llui/llfloaterreglistener.cpp b/indra/llui/llfloaterreglistener.cpp
new file mode 100644
index 0000000000..57d148b5af
--- /dev/null
+++ b/indra/llui/llfloaterreglistener.cpp
@@ -0,0 +1,114 @@
+/**
+ * @file llfloaterreglistener.cpp
+ * @author Nat Goodspeed
+ * @date 2009-08-12
+ * @brief Implementation for llfloaterreglistener.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+// Precompiled header
+#include "linden_common.h"
+// associated header
+#include "llfloaterreglistener.h"
+// STL headers
+// std headers
+// external library headers
+// other Linden headers
+#include "llfloaterreg.h"
+#include "llfloater.h"
+#include "llbutton.h"
+
+LLFloaterRegListener::LLFloaterRegListener(const std::string& pumpName):
+ LLDispatchListener(pumpName, "op")
+{
+ add("getBuildMap", &LLFloaterRegListener::getBuildMap, LLSD().insert("reply", LLSD()));
+ LLSD requiredName;
+ requiredName["name"] = LLSD();
+ add("showInstance", &LLFloaterRegListener::showInstance, requiredName);
+ add("hideInstance", &LLFloaterRegListener::hideInstance, requiredName);
+ add("toggleInstance", &LLFloaterRegListener::toggleInstance, requiredName);
+ LLSD requiredNameButton;
+ requiredNameButton["name"] = LLSD();
+ requiredNameButton["button"] = LLSD();
+ add("clickButton", &LLFloaterRegListener::clickButton, requiredNameButton);
+}
+
+void LLFloaterRegListener::getBuildMap(const LLSD& event) const
+{
+ // Honor the "reqid" convention by echoing event["reqid"] in our reply packet.
+ LLReqID reqID(event);
+ LLSD reply(reqID.makeResponse());
+ // Build an LLSD map that mirrors sBuildMap. Since we have no good way to
+ // represent a C++ callable in LLSD, the only part of BuildData we can
+ // store is the filename. For each LLSD map entry, it would be more
+ // extensible to store a nested LLSD map containing a single key "file" --
+ // but we don't bother, simply storing the string filename instead.
+ for (LLFloaterReg::build_map_t::const_iterator mi(LLFloaterReg::sBuildMap.begin()),
+ mend(LLFloaterReg::sBuildMap.end());
+ mi != mend; ++mi)
+ {
+ reply[mi->first] = mi->second.mFile;
+ }
+ // Send the reply to the LLEventPump named in event["reply"].
+ LLEventPumps::instance().obtain(event["reply"]).post(reply);
+}
+
+void LLFloaterRegListener::showInstance(const LLSD& event) const
+{
+ LLFloaterReg::showInstance(event["name"], event["key"], event["focus"]);
+}
+
+void LLFloaterRegListener::hideInstance(const LLSD& event) const
+{
+ LLFloaterReg::hideInstance(event["name"], event["key"]);
+}
+
+void LLFloaterRegListener::toggleInstance(const LLSD& event) const
+{
+ LLFloaterReg::toggleInstance(event["name"], event["key"]);
+}
+
+void LLFloaterRegListener::clickButton(const LLSD& event) const
+{
+ // If the caller requests a reply, build the reply.
+ LLReqID reqID(event);
+ LLSD reply(reqID.makeResponse());
+
+ LLFloater* floater = LLFloaterReg::findInstance(event["name"], event["key"]);
+ if (! LLFloater::isShown(floater))
+ {
+ reply["type"] = "LLFloater";
+ reply["name"] = event["name"];
+ reply["key"] = event["key"];
+ reply["error"] = floater? "!isShown()" : "NULL";
+ }
+ else
+ {
+ // Here 'floater' points to an LLFloater instance with the specified
+ // name and key which isShown().
+ LLButton* button = floater->findChild<LLButton>(event["button"]);
+ if (! LLButton::isAvailable(button))
+ {
+ reply["type"] = "LLButton";
+ reply["name"] = event["button"];
+ reply["error"] = button? "!isAvailable()" : "NULL";
+ }
+ else
+ {
+ // Here 'button' points to an isAvailable() LLButton child of
+ // 'floater' with the specified button name. Pretend to click it.
+ button->onCommit();
+ // Leave reply["error"] isUndefined(): no error, i.e. success.
+ }
+ }
+
+ // Send a reply only if caller asked for a reply.
+ LLSD replyPump(event["reply"]);
+ if (replyPump.isString()) // isUndefined() if absent
+ {
+ LLEventPumps::instance().obtain(replyPump).post(reply);
+ }
+}
diff --git a/indra/llui/llfloaterreglistener.h b/indra/llui/llfloaterreglistener.h
new file mode 100644
index 0000000000..304ecd1090
--- /dev/null
+++ b/indra/llui/llfloaterreglistener.h
@@ -0,0 +1,36 @@
+/**
+ * @file llfloaterreglistener.h
+ * @author Nat Goodspeed
+ * @date 2009-08-12
+ * @brief Wrap (subset of) LLFloaterReg API with an event API
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#if ! defined(LL_LLFLOATERREGLISTENER_H)
+#define LL_LLFLOATERREGLISTENER_H
+
+#include "lleventdispatcher.h"
+#include <string>
+
+class LLSD;
+
+/// Event API wrapper for LLFloaterReg
+class LLFloaterRegListener: public LLDispatchListener
+{
+public:
+ /// As all public LLFloaterReg methods are static, there's no point in
+ /// binding an LLFloaterReg instance.
+ LLFloaterRegListener(const std::string& pumpName);
+
+private:
+ void getBuildMap(const LLSD& event) const;
+ void showInstance(const LLSD& event) const;
+ void hideInstance(const LLSD& event) const;
+ void toggleInstance(const LLSD& event) const;
+ void clickButton(const LLSD& event) const;
+};
+
+#endif /* ! defined(LL_LLFLOATERREGLISTENER_H) */
diff --git a/indra/llui/llfunctorregistry.cpp b/indra/llui/llfunctorregistry.cpp
index 0c5b1655b1..5f9644f258 100644
--- a/indra/llui/llfunctorregistry.cpp
+++ b/indra/llui/llfunctorregistry.cpp
@@ -31,6 +31,7 @@
* $/LicenseInfo$
**/
+#include "linden_common.h"
#include "llfunctorregistry.h"
// This is a default functor always resident in the system.
diff --git a/indra/llui/llmodaldialog.cpp b/indra/llui/llmodaldialog.cpp
index f77ec5f4c7..387af05935 100644
--- a/indra/llui/llmodaldialog.cpp
+++ b/indra/llui/llmodaldialog.cpp
@@ -297,5 +297,16 @@ void LLModalDialog::onAppFocusGained()
}
}
-
-
+void LLModalDialog::shutdownModals()
+{
+ // This method is only for use during app shutdown. ~LLModalDialog()
+ // checks sModalStack, and if the dialog instance is still there, it
+ // crumps with "Attempt to delete dialog while still in sModalStack!" But
+ // at app shutdown, all bets are off. If the user asks to shut down the
+ // app, we shouldn't have to care WHAT's open. Put differently, if a modal
+ // dialog is so crucial that we can't let the user terminate until s/he
+ // addresses it, we should reject a termination request. The current state
+ // of affairs is that we accept it, but then produce an llerrs popup that
+ // simply makes our software look unreliable.
+ sModalStack.clear();
+}
diff --git a/indra/llui/llmodaldialog.h b/indra/llui/llmodaldialog.h
index 9d716a1880..863572fb5a 100644
--- a/indra/llui/llmodaldialog.h
+++ b/indra/llui/llmodaldialog.h
@@ -73,7 +73,8 @@ public:
static void onAppFocusGained();
static S32 activeCount() { return sModalStack.size(); }
-
+ static void shutdownModals();
+
protected:
void centerOnScreen();
diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index a0e51151c9..ef222bad60 100644
--- a/indra/llui/llnotifications.cpp
+++ b/indra/llui/llnotifications.cpp
@@ -40,6 +40,7 @@
#include "lldir.h"
#include "llsdserialize.h"
#include "lltrans.h"
+#include "llnotificationslistener.h"
#include <algorithm>
#include <boost/regex.hpp>
@@ -945,6 +946,8 @@ LLNotifications::LLNotifications() : LLNotificationChannelBase(LLNotificationFil
mIgnoreAllNotifications(false)
{
LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Notification.Show", boost::bind(&LLNotifications::addFromCallback, this, _2));
+
+ mListener.reset(new LLNotificationsListener(*this));
}
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h
index cd05db3c30..0d7cb74f70 100644
--- a/indra/llui/llnotifications.h
+++ b/indra/llui/llnotifications.h
@@ -102,6 +102,7 @@
#include "llfunctorregistry.h"
#include "llpointer.h"
#include "llinitparam.h"
+#include "llnotificationslistener.h"
class LLNotification;
typedef boost::shared_ptr<LLNotification> LLNotificationPtr;
@@ -812,9 +813,19 @@ private:
LLNotificationComparator mComparator;
};
-
+// An interface class to provide a clean linker seam to the LLNotifications class.
+// Extend this interface as needed for your use of LLNotifications.
+class LLNotificationsInterface
+{
+public:
+ virtual LLNotificationPtr add(const std::string& name,
+ const LLSD& substitutions,
+ const LLSD& payload,
+ LLNotificationFunctorRegistry::ResponseFunctor functor) = 0;
+};
class LLNotifications :
+ public LLNotificationsInterface,
public LLSingleton<LLNotifications>,
public LLNotificationChannelBase
{
@@ -838,7 +849,7 @@ public:
const LLSD& substitutions,
const LLSD& payload,
const std::string& functor_name);
- LLNotificationPtr add(const std::string& name,
+ /* virtual */ LLNotificationPtr add(const std::string& name,
const LLSD& substitutions,
const LLSD& payload,
LLNotificationFunctorRegistry::ResponseFunctor functor);
@@ -917,6 +928,8 @@ private:
GlobalStringMap mGlobalStrings;
bool mIgnoreAllNotifications;
+
+ boost::scoped_ptr<LLNotificationsListener> mListener;
};
diff --git a/indra/llui/llnotificationslistener.cpp b/indra/llui/llnotificationslistener.cpp
new file mode 100644
index 0000000000..75f4d6177d
--- /dev/null
+++ b/indra/llui/llnotificationslistener.cpp
@@ -0,0 +1,55 @@
+/**
+ * @file llnotificationslistener.cpp
+ * @author Brad Kittenbrink
+ * @date 2009-07-08
+ * @brief Implementation for llnotificationslistener.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+
+#include "llnotificationslistener.h"
+
+#include "llnotifications.h"
+
+LLNotificationsListener::LLNotificationsListener(LLNotifications & notifications) :
+ LLDispatchListener("LLNotifications", "op"),
+ mNotifications(notifications)
+{
+ add("requestAdd", &LLNotificationsListener::requestAdd);
+}
+
+void LLNotificationsListener::requestAdd(const LLSD& event_data) const
+{
+ if(event_data.has("reply"))
+ {
+ mNotifications.add(event_data["name"],
+ event_data["substitutions"],
+ event_data["payload"],
+ boost::bind(&LLNotificationsListener::NotificationResponder,
+ this,
+ event_data["reply"].asString(),
+ _1, _2
+ )
+ );
+ }
+ else
+ {
+ mNotifications.add(event_data["name"],
+ event_data["substitutions"],
+ event_data["payload"]);
+ }
+}
+
+void LLNotificationsListener::NotificationResponder(const std::string& reply_pump,
+ const LLSD& notification,
+ const LLSD& response) const
+{
+ LLSD reponse_event;
+ reponse_event["notification"] = notification;
+ reponse_event["response"] = response;
+ LLEventPumps::getInstance()->obtain(reply_pump).post(reponse_event);
+}
diff --git a/indra/llui/llnotificationslistener.h b/indra/llui/llnotificationslistener.h
new file mode 100644
index 0000000000..6f71a7c781
--- /dev/null
+++ b/indra/llui/llnotificationslistener.h
@@ -0,0 +1,34 @@
+/**
+ * @file llnotificationslistener.h
+ * @author Brad Kittenbrink
+ * @date 2009-07-08
+ * @brief Wrap subset of LLNotifications API in event API for test scripts.
+ *
+ * $LicenseInfo:firstyear=2009&license=viewergpl$
+ * Copyright (c) 2009, Linden Research, Inc.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLNOTIFICATIONSLISTENER_H
+#define LL_LLNOTIFICATIONSLISTENER_H
+
+#include "lleventdispatcher.h"
+
+class LLNotifications;
+class LLSD;
+
+class LLNotificationsListener : public LLDispatchListener
+{
+public:
+ LLNotificationsListener(LLNotifications & notifications);
+
+ void requestAdd(LLSD const & event_data) const;
+
+private:
+ void NotificationResponder(const std::string& replypump,
+ const LLSD& notification,
+ const LLSD& response) const;
+ LLNotifications & mNotifications;
+};
+
+#endif // LL_LLNOTIFICATIONSLISTENER_H
diff --git a/indra/llui/llslider.cpp b/indra/llui/llslider.cpp
index 07b6895378..f86776384a 100644
--- a/indra/llui/llslider.cpp
+++ b/indra/llui/llslider.cpp
@@ -43,6 +43,8 @@
#include "lluictrlfactory.h"
static LLDefaultChildRegistry::Register<LLSlider> r1("slider_bar");
+//FIXME: make this into an unregistered template so that code constructed sliders don't
+// have ambigious template lookup problem
LLSlider::Params::Params()
: track_color("track_color"),
diff --git a/indra/llui/llsliderctrl.cpp b/indra/llui/llsliderctrl.cpp
index 3ecf629082..ed22c0a47f 100644
--- a/indra/llui/llsliderctrl.cpp
+++ b/indra/llui/llsliderctrl.cpp
@@ -396,4 +396,3 @@ void LLSliderCtrl::reportInvalidData()
make_ui_sound("UISndBadKeystroke");
}
-
diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp
index f253857851..da9384f876 100644
--- a/indra/llui/llui.cpp
+++ b/indra/llui/llui.cpp
@@ -1952,7 +1952,12 @@ namespace LLInitParam
return fontp;
}
}
-
+
+ if (mData.mValue == NULL)
+ {
+ mData.mValue = LLFontGL::getFontDefault();
+ }
+
// default to current value
return mData.mValue;
}
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index 31f12fe312..fe7fd59de8 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -438,6 +438,18 @@ void LLView::setEnabled(BOOL enabled)
}
//virtual
+bool LLView::isAvailable() const
+{
+ return isInEnabledChain() && isInVisibleChain();
+}
+
+//static
+bool LLView::isAvailable(const LLView* view)
+{
+ return view && view->isAvailable();
+}
+
+//virtual
BOOL LLView::setLabelArg( const std::string& key, const LLStringExplicit& text )
{
return FALSE;
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index 73146b2c1f..c3b442e022 100644
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -304,6 +304,11 @@ public:
BOOL getVisible() const { return mVisible; }
virtual void setEnabled(BOOL enabled);
BOOL getEnabled() const { return mEnabled; }
+ /// 'available' in this context means 'visible and enabled': in other
+ /// words, can a user actually interact with this?
+ virtual bool isAvailable() const;
+ /// The static isAvailable() tests an LLView* that could be NULL.
+ static bool isAvailable(const LLView* view);
U8 getSoundFlags() const { return mSoundFlags; }
virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text );