summaryrefslogtreecommitdiff
path: root/indra/llxml/llcontrol.h
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llxml/llcontrol.h')
-rw-r--r--indra/llxml/llcontrol.h286
1 files changed, 249 insertions, 37 deletions
diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h
index ba0a1c7cbf..1782c20a7e 100644
--- a/indra/llxml/llcontrol.h
+++ b/indra/llxml/llcontrol.h
@@ -33,11 +33,14 @@
#ifndef LL_LLCONTROL_H
#define LL_LLCONTROL_H
+#include "llboost.h"
#include "llevent.h"
#include "llnametable.h"
#include "llmap.h"
#include "llstring.h"
#include "llrect.h"
+#include "llrefcount.h"
+#include "llinstancetracker.h"
#include "llcontrolgroupreader.h"
@@ -65,7 +68,6 @@ class LLVector3;
class LLVector3d;
class LLColor4;
class LLColor3;
-class LLColor4U;
const BOOL NO_PERSIST = FALSE;
@@ -81,15 +83,17 @@ typedef enum e_control_type
TYPE_RECT,
TYPE_COL4,
TYPE_COL3,
- TYPE_COL4U,
TYPE_LLSD,
TYPE_COUNT
} eControlType;
-class LLControlVariable : public LLRefCount
+class LLControlVariable : public LLRefCount, boost::noncopyable
{
friend class LLControlGroup;
- typedef boost::signal<void(const LLSD&)> signal_t;
+
+public:
+ typedef boost::signal<bool(LLControlVariable* control, const LLSD&), boost_boolean_combiner> validate_signal_t;
+ typedef boost::signal<void(LLControlVariable* control, const LLSD&)> commit_signal_t;
private:
std::string mName;
@@ -99,7 +103,8 @@ private:
bool mHideFromSettingsEditor;
std::vector<LLSD> mValues;
- signal_t mSignal;
+ commit_signal_t mCommitSignal;
+ validate_signal_t mValidateSignal;
public:
LLControlVariable(const std::string& name, eControlType type,
@@ -116,7 +121,9 @@ public:
void resetToDefault(bool fire_signal = false);
- signal_t* getSignal() { return &mSignal; }
+ commit_signal_t* getSignal() { return &mCommitSignal; } // shorthand for commit signal
+ commit_signal_t* getCommitSignal() { return &mCommitSignal; }
+ validate_signal_t* getValidateSignal() { return &mValidateSignal; }
bool isDefault() { return (mValues.size() == 1); }
bool isSaveValueDefault();
@@ -136,31 +143,55 @@ public:
void firePropertyChanged()
{
- mSignal(mValues.back());
+ mCommitSignal(this, mValues.back());
}
private:
LLSD getComparableValue(const LLSD& value);
bool llsd_compare(const LLSD& a, const LLSD & b);
-
};
+typedef LLPointer<LLControlVariable> LLControlVariablePtr;
+
+//! Helper functions for converting between static types and LLControl values
+template <class T>
+eControlType get_control_type()
+{
+ llwarns << "Usupported control type: " << typeid(T).name() << "." << llendl;
+ return TYPE_COUNT;
+}
+
+template <class T>
+LLSD convert_to_llsd(const T& in)
+{
+ // default implementation
+ return LLSD(in);
+}
+
+template <class T>
+T convert_from_llsd(const LLSD& sd, eControlType type, const std::string& control_name)
+{
+ // needs specialization
+ return T(sd);
+}
+
//const U32 STRING_CACHE_SIZE = 10000;
-class LLControlGroup : public LLControlGroupReader
+class LLControlGroup : public LLInstanceTracker<LLControlGroup, std::string>
{
protected:
- typedef std::map<std::string, LLPointer<LLControlVariable> > ctrl_name_table_t;
+ typedef std::map<std::string, LLControlVariablePtr > ctrl_name_table_t;
ctrl_name_table_t mNameTable;
- std::set<std::string> mWarnings;
std::string mTypeString[TYPE_COUNT];
eControlType typeStringToEnum(const std::string& typestr);
std::string typeEnumToString(eControlType typeenum);
public:
- LLControlGroup();
+ LLControlGroup(const std::string& name);
~LLControlGroup();
void cleanup();
- LLPointer<LLControlVariable> getControl(const std::string& name);
+ typedef LLInstanceTracker<LLControlGroup, std::string>::instance_iter instance_iter;
+
+ LLControlVariablePtr getControl(const std::string& name);
struct ApplyFunctor
{
@@ -178,33 +209,47 @@ public:
BOOL declareVec3(const std::string& name, const LLVector3 &initial_val,const std::string& comment, BOOL persist = TRUE);
BOOL declareVec3d(const std::string& name, const LLVector3d &initial_val, const std::string& comment, BOOL persist = TRUE);
BOOL declareRect(const std::string& name, const LLRect &initial_val, const std::string& comment, BOOL persist = TRUE);
- BOOL declareColor4U(const std::string& name, const LLColor4U &initial_val, const std::string& comment, BOOL persist = TRUE);
BOOL declareColor4(const std::string& name, const LLColor4 &initial_val, const std::string& comment, BOOL persist = TRUE);
BOOL declareColor3(const std::string& name, const LLColor3 &initial_val, const std::string& comment, BOOL persist = TRUE);
BOOL declareLLSD(const std::string& name, const LLSD &initial_val, const std::string& comment, BOOL persist = TRUE);
-
- std::string findString(const std::string& name);
- std::string getString(const std::string& name);
- LLWString getWString(const std::string& name);
- std::string getText(const std::string& name);
- LLVector3 getVector3(const std::string& name);
- LLVector3d getVector3d(const std::string& name);
- LLRect getRect(const std::string& name);
+ std::string getString(const std::string& name);
+ std::string getText(const std::string& name);
BOOL getBOOL(const std::string& name);
S32 getS32(const std::string& name);
F32 getF32(const std::string& name);
U32 getU32(const std::string& name);
+
+ LLWString getWString(const std::string& name);
+ LLVector3 getVector3(const std::string& name);
+ LLVector3d getVector3d(const std::string& name);
+ LLRect getRect(const std::string& name);
LLSD getLLSD(const std::string& name);
- // Note: If an LLColor4U control exists, it will cast it to the correct
- // LLColor4 for you.
LLColor4 getColor(const std::string& name);
- LLColor4U getColor4U(const std::string& name);
LLColor4 getColor4(const std::string& name);
LLColor3 getColor3(const std::string& name);
+ // generic getter
+ template<typename T> T get(const std::string& name)
+ {
+ LLControlVariable* control = getControl(name);
+ LLSD value;
+ eControlType type = TYPE_COUNT;
+
+ if (control)
+ {
+ value = control->get();
+ type = control->type();
+ }
+ else
+ {
+ llwarns << "Control " << name << " not found." << llendl;
+ }
+ return convert_from_llsd<T>(value, type, name);
+ }
+
void setBOOL(const std::string& name, BOOL val);
void setS32(const std::string& name, S32 val);
void setF32(const std::string& name, F32 val);
@@ -213,12 +258,26 @@ public:
void setVector3(const std::string& name, const LLVector3 &val);
void setVector3d(const std::string& name, const LLVector3d &val);
void setRect(const std::string& name, const LLRect &val);
- void setColor4U(const std::string& name, const LLColor4U &val);
void setColor4(const std::string& name, const LLColor4 &val);
- void setColor3(const std::string& name, const LLColor3 &val);
void setLLSD(const std::string& name, const LLSD& val);
- void setValue(const std::string& name, const LLSD& val);
+
+ // type agnostic setter that takes LLSD
+ void setUntypedValue(const std::string& name, const LLSD& val);
+
+ // generic setter
+ template<typename T> void set(const std::string& name, const T& val)
+ {
+ LLControlVariable* control = getControl(name);
+ if (control && control->isType(get_control_type<T>()))
+ {
+ control->set(convert_to_llsd(val));
+ }
+ else
+ {
+ llwarns << "Invalid control " << name << llendl;
+ }
+ }
BOOL controlExists(const std::string& name);
@@ -229,17 +288,170 @@ public:
U32 saveToFile(const std::string& filename, BOOL nondefault_only);
U32 loadFromFile(const std::string& filename, bool default_values = false);
void resetToDefaults();
+};
+
+//! Publish/Subscribe object to interact with LLControlGroups.
+
+//! Use an LLCachedControl instance to connect to a LLControlVariable
+//! without have to manually create and bind a listener to a local
+//! object.
+template <class T>
+class LLControlCache : public LLRefCount, public LLInstanceTracker<LLControlCache<T>, std::string>
+{
+public:
+ // This constructor will declare a control if it doesn't exist in the contol group
+ LLControlCache(LLControlGroup& group,
+ const std::string& name,
+ const T& default_value,
+ const std::string& comment)
+ : LLInstanceTracker<LLControlCache<T>, std::string >(name)
+ {
+ if(!group.controlExists(name))
+ {
+ if(!declareTypedControl(group, name, default_value, comment))
+ {
+ llerrs << "The control could not be created!!!" << llendl;
+ }
+ }
+
+ bindToControl(group, name);
+ }
+
+ LLControlCache(LLControlGroup& group,
+ const std::string& name)
+ : LLInstanceTracker<LLControlCache<T>, std::string >(name)
+ {
+ if(!group.controlExists(name))
+ {
+ llerrs << "Control named " << name << "not found." << llendl;
+ }
+
+ bindToControl(group, name);
+ }
+
+ ~LLControlCache()
+ {
+ if(mConnection.connected())
+ {
+ mConnection.disconnect();
+ }
+ }
+
+ const T& getValue() const { return mCachedValue; }
- // Ignorable Warnings
-
- // Add a config variable to be reset on resetWarnings()
- void addWarning(const std::string& name);
- BOOL getWarning(const std::string& name);
- void setWarning(const std::string& name, BOOL val);
-
- // Resets all ignorables
- void resetWarnings();
+private:
+ void bindToControl(LLControlGroup& group, const std::string& name)
+ {
+ LLControlVariablePtr controlp = group.getControl(name);
+ mType = controlp->type();
+ mCachedValue = convert_from_llsd<T>(controlp->get(), mType, name);
+
+ // Add a listener to the controls signal...
+ mConnection = controlp->getSignal()->connect(
+ boost::bind(&LLControlCache<T>::handleValueChange, this, _2)
+ );
+ mType = controlp->type();
+ }
+ bool declareTypedControl(LLControlGroup& group,
+ const std::string& name,
+ const T& default_value,
+ const std::string& comment)
+ {
+ LLSD init_value;
+ eControlType type = get_control_type<T>();
+ init_value = convert_to_llsd(default_value);
+ if(type < TYPE_COUNT)
+ {
+ group.declareControl(name, type, init_value, comment, FALSE);
+ return true;
+ }
+ return false;
+ }
+
+ bool handleValueChange(const LLSD& newvalue)
+ {
+ mCachedValue = convert_from_llsd<T>(newvalue, mType, "");
+ return true;
+ }
+
+private:
+ T mCachedValue;
+ eControlType mType;
+ boost::signals::connection mConnection;
+};
+
+template <typename T>
+class LLCachedControl
+{
+public:
+ LLCachedControl(LLControlGroup& group,
+ const std::string& name,
+ const T& default_value,
+ const std::string& comment = "Declared In Code")
+ {
+ mCachedControlPtr = LLControlCache<T>::getInstance(name);
+ if (mCachedControlPtr.isNull())
+ {
+ mCachedControlPtr = new LLControlCache<T>(group, name, default_value, comment);
+ }
+ }
+
+ LLCachedControl(LLControlGroup& group,
+ const std::string& name)
+ {
+ mCachedControlPtr = LLControlCache<T>::getInstance(name);
+ if (mCachedControlPtr.isNull())
+ {
+ mCachedControlPtr = new LLControlCache<T>(group, name);
+ }
+ }
+
+ operator const T&() const { return mCachedControlPtr->getValue(); }
+ operator boost::function<const T&()> () const { return boost::function<const T&()>(*this); }
+ const T& operator()() { return mCachedControlPtr->getValue(); }
+
+private:
+ LLPointer<LLControlCache<T> > mCachedControlPtr;
};
+template <> eControlType get_control_type<U32>();
+template <> eControlType get_control_type<S32>();
+template <> eControlType get_control_type<F32>();
+template <> eControlType get_control_type<bool>();
+// Yay BOOL, its really an S32.
+//template <> eControlType get_control_type<BOOL> ()
+template <> eControlType get_control_type<std::string>();
+template <> eControlType get_control_type<LLVector3>();
+template <> eControlType get_control_type<LLVector3d>();
+template <> eControlType get_control_type<LLRect>();
+template <> eControlType get_control_type<LLColor4>();
+template <> eControlType get_control_type<LLColor3>();
+template <> eControlType get_control_type<LLSD>();
+
+template <> LLSD convert_to_llsd<U32>(const U32& in);
+template <> LLSD convert_to_llsd<LLVector3>(const LLVector3& in);
+template <> LLSD convert_to_llsd<LLVector3d>(const LLVector3d& in);
+template <> LLSD convert_to_llsd<LLRect>(const LLRect& in);
+template <> LLSD convert_to_llsd<LLColor4>(const LLColor4& in);
+template <> LLSD convert_to_llsd<LLColor3>(const LLColor3& in);
+
+template<> std::string convert_from_llsd<std::string>(const LLSD& sd, eControlType type, const std::string& control_name);
+template<> LLWString convert_from_llsd<LLWString>(const LLSD& sd, eControlType type, const std::string& control_name);
+template<> LLVector3 convert_from_llsd<LLVector3>(const LLSD& sd, eControlType type, const std::string& control_name);
+template<> LLVector3d convert_from_llsd<LLVector3d>(const LLSD& sd, eControlType type, const std::string& control_name);
+template<> LLRect convert_from_llsd<LLRect>(const LLSD& sd, eControlType type, const std::string& control_name);
+template<> bool convert_from_llsd<bool>(const LLSD& sd, eControlType type, const std::string& control_name);
+template<> S32 convert_from_llsd<S32>(const LLSD& sd, eControlType type, const std::string& control_name);
+template<> F32 convert_from_llsd<F32>(const LLSD& sd, eControlType type, const std::string& control_name);
+template<> U32 convert_from_llsd<U32>(const LLSD& sd, eControlType type, const std::string& control_name);
+template<> LLColor3 convert_from_llsd<LLColor3>(const LLSD& sd, eControlType type, const std::string& control_name);
+template<> LLColor4 convert_from_llsd<LLColor4>(const LLSD& sd, eControlType type, const std::string& control_name);
+template<> LLSD convert_from_llsd<LLSD>(const LLSD& sd, eControlType type, const std::string& control_name);
+
+//#define TEST_CACHED_CONTROL 1
+#ifdef TEST_CACHED_CONTROL
+void test_cached_control();
+#endif // TEST_CACHED_CONTROL
+
#endif