summaryrefslogtreecommitdiff
path: root/indra/llxml
diff options
context:
space:
mode:
authorSteven Bennetts <steve@lindenlab.com>2009-05-08 07:43:08 +0000
committerSteven Bennetts <steve@lindenlab.com>2009-05-08 07:43:08 +0000
commita4000c3744e42fcbb638e742f3b63fa31a0dee15 (patch)
tree7f472c30e65bbfa04ee9bc06631a1af305cc31fb /indra/llxml
parent6c4cadbb04d633ad7b762058bdeba6e1f650dafd (diff)
merge trunk@116587 skinning-7@119389 -> viewer-2.0.0-skinning-7
Diffstat (limited to 'indra/llxml')
-rw-r--r--indra/llxml/CMakeLists.txt3
-rw-r--r--indra/llxml/llcontrol.cpp724
-rw-r--r--indra/llxml/llcontrol.h286
-rw-r--r--indra/llxml/llcontrolgroupreader.h73
-rw-r--r--indra/llxml/llxmlnode.cpp148
-rw-r--r--indra/llxml/llxmlnode.h30
6 files changed, 828 insertions, 436 deletions
diff --git a/indra/llxml/CMakeLists.txt b/indra/llxml/CMakeLists.txt
index dc7787beea..b1ac85812c 100644
--- a/indra/llxml/CMakeLists.txt
+++ b/indra/llxml/CMakeLists.txt
@@ -5,11 +5,13 @@ project(llxml)
include(00-Common)
include(LLCommon)
include(LLMath)
+include(LLVFS)
include(LLXML)
include_directories(
${LLCOMMON_INCLUDE_DIRS}
${LLMATH_INCLUDE_DIRS}
+ ${LLVFS_INCLUDE_DIRS}
)
set(llxml_SOURCE_FILES
@@ -38,6 +40,7 @@ add_library (llxml ${llxml_SOURCE_FILES})
# Libraries on which this library depends, needed for Linux builds
# Sort by high-level to low-level
target_link_libraries( llxml
+ llvfs
llmath
${BOOST_SIGNALS_LIBRARY}
${EXPAT_LIBRARIES}
diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp
index d9ed45ab9d..2271c02cd0 100644
--- a/indra/llxml/llcontrol.cpp
+++ b/indra/llxml/llcontrol.cpp
@@ -56,6 +56,45 @@
#define CONTROL_ERRS LL_WARNS("ControlErrors")
#endif
+
+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<LLColor4U>();
+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 <> LLSD convert_to_llsd<LLColor4U>(const LLColor4U& in);
+
+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 <> U32 convert_from_llsd<U32>(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 <> 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 <> LLColor4 convert_from_llsd<LLColor4>(const LLSD& sd, eControlType type, const std::string& control_name);
+template <> LLColor4U convert_from_llsd<LLColor4U>(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 <> LLSD convert_from_llsd<LLSD>(const LLSD& sd, eControlType type, const std::string& control_name);
+
//this defines the current version of the settings file
const S32 CURRENT_VERSION = 101;
@@ -87,9 +126,6 @@ bool LLControlVariable::llsd_compare(const LLSD& a, const LLSD & b)
case TYPE_COL3:
result = LLColor3(a) == LLColor3(b);
break;
- case TYPE_COL4U:
- result = LLColor4U(a) == LLColor4U(b);
- break;
case TYPE_STRING:
result = a.asString() == b.asString();
break;
@@ -148,9 +184,15 @@ LLSD LLControlVariable::getComparableValue(const LLSD& value)
return storable_value;
}
-void LLControlVariable::setValue(const LLSD& value, bool saved_value)
+void LLControlVariable::setValue(const LLSD& new_value, bool saved_value)
{
- LLSD storable_value = getComparableValue(value);
+ if (mValidateSignal(this, new_value) == false)
+ {
+ // can not set new value, exit
+ return;
+ }
+
+ LLSD storable_value = getComparableValue(new_value);
bool value_changed = llsd_compare(getValue(), storable_value) == FALSE;
if(saved_value)
{
@@ -163,7 +205,7 @@ void LLControlVariable::setValue(const LLSD& value, bool saved_value)
}
else
{
- // This is a unsaved value. Its needs to reside at
+ // This is an unsaved value. Its needs to reside at
// mValues[2] (or greater). It must not affect
// the result of getSaveValue()
if (llsd_compare(mValues.back(), storable_value) == FALSE)
@@ -185,10 +227,9 @@ void LLControlVariable::setValue(const LLSD& value, bool saved_value)
}
}
-
if(value_changed)
{
- mSignal(storable_value);
+ mCommitSignal(this, storable_value);
}
}
@@ -262,7 +303,8 @@ LLPointer<LLControlVariable> LLControlGroup::getControl(const std::string& name)
////////////////////////////////////////////////////////////////////////////
-LLControlGroup::LLControlGroup()
+LLControlGroup::LLControlGroup(const std::string& name)
+: LLInstanceTracker<LLControlGroup, std::string>(name)
{
mTypeString[TYPE_U32] = "U32";
mTypeString[TYPE_S32] = "S32";
@@ -274,7 +316,6 @@ LLControlGroup::LLControlGroup()
mTypeString[TYPE_RECT] = "Rect";
mTypeString[TYPE_COL4] = "Color4";
mTypeString[TYPE_COL3] = "Color3";
- mTypeString[TYPE_COL4U] = "Color4u";
mTypeString[TYPE_LLSD] = "LLSD";
}
@@ -309,10 +350,13 @@ BOOL LLControlGroup::declareControl(const std::string& name, eControlType type,
{
if (persist && existing_control->isType(type))
{
- // Sometimes we need to declare a control *after* it has been loaded from a settings file.
- LLSD cur_value = existing_control->getValue(); // get the current value
- existing_control->setDefaultValue(initial_val); // set the default to the declared value
- existing_control->setValue(cur_value); // now set to the loaded value
+ if (!existing_control->llsd_compare(existing_control->getDefault(), initial_val))
+ {
+ // Sometimes we need to declare a control *after* it has been loaded from a settings file.
+ LLSD cur_value = existing_control->getValue(); // get the current value
+ existing_control->setDefaultValue(initial_val); // set the default to the declared value
+ existing_control->setValue(cur_value); // now set to the loaded value
+ }
}
else
{
@@ -367,11 +411,6 @@ BOOL LLControlGroup::declareRect(const std::string& name, const LLRect &initial_
return declareControl(name, TYPE_RECT, initial_val.getValue(), comment, persist);
}
-BOOL LLControlGroup::declareColor4U(const std::string& name, const LLColor4U &initial_val, const std::string& comment, BOOL persist )
-{
- return declareControl(name, TYPE_COL4U, initial_val.getValue(), comment, persist);
-}
-
BOOL LLControlGroup::declareColor4(const std::string& name, const LLColor4 &initial_val, const std::string& comment, BOOL persist )
{
return declareControl(name, TYPE_COL4, initial_val.getValue(), comment, persist);
@@ -389,81 +428,32 @@ BOOL LLControlGroup::declareLLSD(const std::string& name, const LLSD &initial_va
BOOL LLControlGroup::getBOOL(const std::string& name)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_BOOLEAN))
- return control->get().asBoolean();
- else
- {
- CONTROL_ERRS << "Invalid BOOL control " << name << llendl;
- return FALSE;
- }
+ return (BOOL)get<bool>(name);
}
S32 LLControlGroup::getS32(const std::string& name)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_S32))
- return control->get().asInteger();
- else
- {
- CONTROL_ERRS << "Invalid S32 control " << name << llendl;
- return 0;
- }
+ return get<S32>(name);
}
U32 LLControlGroup::getU32(const std::string& name)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_U32))
- return control->get().asInteger();
- else
- {
- CONTROL_ERRS << "Invalid U32 control " << name << llendl;
- return 0;
- }
+ return get<U32>(name);
}
F32 LLControlGroup::getF32(const std::string& name)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_F32))
- return (F32) control->get().asReal();
- else
- {
- CONTROL_ERRS << "Invalid F32 control " << name << llendl;
- return 0.0f;
- }
-}
-
-std::string LLControlGroup::findString(const std::string& name)
-{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_STRING))
- return control->get().asString();
- return LLStringUtil::null;
+ return get<F32>(name);
}
std::string LLControlGroup::getString(const std::string& name)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_STRING))
- return control->get().asString();
- else
- {
- CONTROL_ERRS << "Invalid string control " << name << llendl;
- return LLStringUtil::null;
- }
+ return get<std::string>(name);
}
LLWString LLControlGroup::getWString(const std::string& name)
{
- return utf8str_to_wstring(getString(name));
+ return get<LLWString>(name);
}
std::string LLControlGroup::getText(const std::string& name)
@@ -476,123 +466,38 @@ std::string LLControlGroup::getText(const std::string& name)
LLVector3 LLControlGroup::getVector3(const std::string& name)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_VEC3))
- return control->get();
- else
- {
- CONTROL_ERRS << "Invalid LLVector3 control " << name << llendl;
- return LLVector3::zero;
- }
+ return get<LLVector3>(name);
}
LLVector3d LLControlGroup::getVector3d(const std::string& name)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_VEC3D))
- return control->get();
- else
- {
- CONTROL_ERRS << "Invalid LLVector3d control " << name << llendl;
- return LLVector3d::zero;
- }
+ return get<LLVector3d>(name);
}
LLRect LLControlGroup::getRect(const std::string& name)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_RECT))
- return control->get();
- else
- {
- CONTROL_ERRS << "Invalid rect control " << name << llendl;
- return LLRect::null;
- }
+ return get<LLRect>(name);
}
LLColor4 LLControlGroup::getColor(const std::string& name)
{
- ctrl_name_table_t::const_iterator i = mNameTable.find(name);
-
- if (i != mNameTable.end())
- {
- LLControlVariable* control = i->second;
-
- switch(control->mType)
- {
- case TYPE_COL4:
- {
- return LLColor4(control->get());
- }
- case TYPE_COL4U:
- {
- return LLColor4(LLColor4U(control->get()));
- }
- default:
- {
- CONTROL_ERRS << "Control " << name << " not a color" << llendl;
- return LLColor4::white;
- }
- }
- }
- else
- {
- CONTROL_ERRS << "Invalid getColor control " << name << llendl;
- return LLColor4::white;
- }
-}
-
-LLColor4U LLControlGroup::getColor4U(const std::string& name)
-{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_COL4U))
- return control->get();
- else
- {
- CONTROL_ERRS << "Invalid LLColor4 control " << name << llendl;
- return LLColor4U::white;
- }
+ return get<LLColor4>(name);
}
LLColor4 LLControlGroup::getColor4(const std::string& name)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_COL4))
- return control->get();
- else
- {
- CONTROL_ERRS << "Invalid LLColor4 control " << name << llendl;
- return LLColor4::white;
- }
+ return get<LLColor4>(name);
}
LLColor3 LLControlGroup::getColor3(const std::string& name)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_COL3))
- return control->get();
- else
- {
- CONTROL_ERRS << "Invalid LLColor3 control " << name << llendl;
- return LLColor3::white;
- }
+ return get<LLColor3>(name);
}
LLSD LLControlGroup::getLLSD(const std::string& name)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_LLSD))
- return control->getValue();
- CONTROL_ERRS << "Invalid LLSD control " << name << llendl;
- return LLSD();
+ return get<LLSD>(name);
}
BOOL LLControlGroup::controlExists(const std::string& name)
@@ -601,170 +506,67 @@ BOOL LLControlGroup::controlExists(const std::string& name)
return iter != mNameTable.end();
}
+
//-------------------------------------------------------------------
// Set functions
//-------------------------------------------------------------------
void LLControlGroup::setBOOL(const std::string& name, BOOL val)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_BOOLEAN))
- {
- control->set(val);
- }
- else
- {
- CONTROL_ERRS << "Invalid control " << name << llendl;
- }
+ set<bool>(name, val);
}
void LLControlGroup::setS32(const std::string& name, S32 val)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_S32))
- {
- control->set(val);
- }
- else
- {
- CONTROL_ERRS << "Invalid control " << name << llendl;
- }
+ set(name, val);
}
void LLControlGroup::setF32(const std::string& name, F32 val)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_F32))
- {
- control->set(val);
- }
- else
- {
- CONTROL_ERRS << "Invalid control " << name << llendl;
- }
+ set(name, val);
}
void LLControlGroup::setU32(const std::string& name, U32 val)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_U32))
- {
- control->set((LLSD::Integer) val);
- }
- else
- {
- CONTROL_ERRS << "Invalid control " << name << llendl;
- }
+ set(name, val);
}
void LLControlGroup::setString(const std::string& name, const std::string &val)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_STRING))
- {
- control->set(val);
- }
- else
- {
- CONTROL_ERRS << "Invalid control " << name << llendl;
- }
+ set(name, val);
}
void LLControlGroup::setVector3(const std::string& name, const LLVector3 &val)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_VEC3))
- {
- control->set(val.getValue());
- }
- else
- {
- CONTROL_ERRS << "Invalid control " << name << llendl;
- }
+ set(name, val);
}
void LLControlGroup::setVector3d(const std::string& name, const LLVector3d &val)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_VEC3D))
- {
- control->set(val.getValue());
- }
- else
- {
- CONTROL_ERRS << "Invalid control " << name << llendl;
- }
+ set(name, val);
}
void LLControlGroup::setRect(const std::string& name, const LLRect &val)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_RECT))
- {
- control->set(val.getValue());
- }
- else
- {
- CONTROL_ERRS << "Invalid rect control " << name << llendl;
- }
-}
-
-void LLControlGroup::setColor4U(const std::string& name, const LLColor4U &val)
-{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_COL4U))
- {
- control->set(val.getValue());
- }
- else
- {
- CONTROL_ERRS << "Invalid LLColor4 control " << name << llendl;
- }
+ set(name, val);
}
void LLControlGroup::setColor4(const std::string& name, const LLColor4 &val)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_COL4))
- {
- control->set(val.getValue());
- }
- else
- {
- CONTROL_ERRS << "Invalid LLColor4 control " << name << llendl;
- }
+ set(name, val);
}
void LLControlGroup::setLLSD(const std::string& name, const LLSD& val)
{
- LLControlVariable* control = getControl(name);
-
- if (control && control->isType(TYPE_LLSD))
- {
- setValue(name, val);
- }
- else
- {
- CONTROL_ERRS << "Invalid LLSD control " << name << llendl;
- }
+ set(name, val);
}
-void LLControlGroup::setValue(const std::string& name, const LLSD& val)
+void LLControlGroup::setUntypedValue(const std::string& name, const LLSD& val)
{
if (name.empty())
{
@@ -775,7 +577,7 @@ void LLControlGroup::setValue(const std::string& name, const LLSD& val)
if (control)
{
- control->set(val);
+ control->setValue(val);
}
else
{
@@ -783,6 +585,7 @@ void LLControlGroup::setValue(const std::string& name, const LLSD& val)
}
}
+
//---------------------------------------------------------------
// Load and save
//---------------------------------------------------------------
@@ -851,9 +654,6 @@ U32 LLControlGroup::loadFromFileLegacy(const std::string& filename, BOOL require
case TYPE_COL4:
declareColor4(name, LLColor4::white, LLStringUtil::null, NO_PERSIST);
break;
- case TYPE_COL4U:
- declareColor4U(name, LLColor4U::white, LLStringUtil::null, NO_PERSIST);
- break;
case TYPE_STRING:
default:
declareString(name, LLStringUtil::null, LLStringUtil::null, NO_PERSIST);
@@ -951,15 +751,6 @@ U32 LLControlGroup::loadFromFileLegacy(const std::string& filename, BOOL require
validitems++;
}
break;
- case TYPE_COL4U:
- {
- LLColor4U color;
-
- child_nodep->getAttributeColor4U("value", color);
- control->set(color.getValue());
- validitems++;
- }
- break;
case TYPE_COL4:
{
LLColor4 color;
@@ -1059,10 +850,11 @@ U32 LLControlGroup::loadFromFile(const std::string& filename, bool set_default_v
}
U32 validitems = 0;
- bool persist = true;
bool hidefromsettingseditor = false;
+
for(LLSD::map_const_iterator itr = settings.beginMap(); itr != settings.endMap(); ++itr)
{
+ bool persist = true;
name = (*itr).first;
control_map = (*itr).second;
@@ -1153,55 +945,6 @@ void LLControlGroup::applyToAll(ApplyFunctor* func)
}
//============================================================================
-// First-use
-
-static std::string get_warn_name(const std::string& name)
-{
- std::string warnname = "Warn" + name;
- for (std::string::iterator iter = warnname.begin(); iter != warnname.end(); ++iter)
- {
- char c = *iter;
- if (!isalnum(c))
- {
- *iter = '_';
- }
- }
- return warnname;
-}
-
-void LLControlGroup::addWarning(const std::string& name)
-{
- std::string warnname = get_warn_name(name);
- if(mNameTable.find(warnname) == mNameTable.end())
- {
- std::string comment = std::string("Enables ") + name + std::string(" warning dialog");
- declareBOOL(warnname, TRUE, comment);
- mWarnings.insert(warnname);
- }
-}
-
-BOOL LLControlGroup::getWarning(const std::string& name)
-{
- std::string warnname = get_warn_name(name);
- return getBOOL(warnname);
-}
-
-void LLControlGroup::setWarning(const std::string& name, BOOL val)
-{
- std::string warnname = get_warn_name(name);
- setBOOL(warnname, val);
-}
-
-void LLControlGroup::resetWarnings()
-{
- for (std::set<std::string>::iterator iter = mWarnings.begin();
- iter != mWarnings.end(); ++iter)
- {
- setBOOL(*iter, TRUE);
- }
-}
-
-//============================================================================
#ifdef TEST_HARNESS
void main()
@@ -1265,4 +1008,297 @@ void main()
#endif
+template <> eControlType get_control_type<U32>()
+{
+ return TYPE_U32;
+}
+
+template <> eControlType get_control_type<S32>()
+{
+ return TYPE_S32;
+}
+
+template <> eControlType get_control_type<F32>()
+{
+ return TYPE_F32;
+}
+
+template <> eControlType get_control_type<bool> ()
+{
+ return TYPE_BOOLEAN;
+}
+/*
+// Yay BOOL, its really an S32.
+template <> eControlType get_control_type<BOOL> ()
+{
+ return TYPE_BOOLEAN;
+}
+*/
+template <> eControlType get_control_type<std::string>()
+{
+ return TYPE_STRING;
+}
+
+template <> eControlType get_control_type<LLVector3>()
+{
+ return TYPE_VEC3;
+}
+
+template <> eControlType get_control_type<LLVector3d>()
+{
+ return TYPE_VEC3D;
+}
+
+template <> eControlType get_control_type<LLRect>()
+{
+ return TYPE_RECT;
+}
+
+template <> eControlType get_control_type<LLColor4>()
+{
+ return TYPE_COL4;
+}
+
+template <> eControlType get_control_type<LLColor3>()
+{
+ return TYPE_COL3;
+}
+
+template <> eControlType get_control_type<LLSD>()
+{
+ return TYPE_LLSD;
+}
+
+
+template <> LLSD convert_to_llsd<U32>(const U32& in)
+{
+ return (LLSD::Integer)in;
+}
+
+template <> LLSD convert_to_llsd<LLVector3>(const LLVector3& in)
+{
+ return in.getValue();
+}
+
+template <> LLSD convert_to_llsd<LLVector3d>(const LLVector3d& in)
+{
+ return in.getValue();
+}
+
+template <> LLSD convert_to_llsd<LLRect>(const LLRect& in)
+{
+ return in.getValue();
+}
+
+template <> LLSD convert_to_llsd<LLColor4>(const LLColor4& in)
+{
+ return in.getValue();
+}
+
+template <> LLSD convert_to_llsd<LLColor3>(const LLColor3& in)
+{
+ return in.getValue();
+}
+
+template <> LLSD convert_to_llsd<LLColor4U>(const LLColor4U& in)
+{
+ return in.getValue();
+}
+
+
+template<>
+bool convert_from_llsd<bool>(const LLSD& sd, eControlType type, const std::string& control_name)
+{
+ if (type == TYPE_BOOLEAN)
+ return sd.asBoolean();
+ else
+ {
+ CONTROL_ERRS << "Invalid BOOL value" << llendl;
+ return FALSE;
+ }
+}
+
+template<>
+S32 convert_from_llsd<S32>(const LLSD& sd, eControlType type, const std::string& control_name)
+{
+ if (type == TYPE_S32)
+ return sd.asInteger();
+ else
+ {
+ CONTROL_ERRS << "Invalid S32 value" << llendl;
+ return 0;
+ }
+}
+
+template<>
+U32 convert_from_llsd<U32>(const LLSD& sd, eControlType type, const std::string& control_name)
+{
+ if (type == TYPE_U32)
+ return sd.asInteger();
+ else
+ {
+ CONTROL_ERRS << "Invalid U32 value" << llendl;
+ return 0;
+ }
+}
+
+template<>
+F32 convert_from_llsd<F32>(const LLSD& sd, eControlType type, const std::string& control_name)
+{
+ if (type == TYPE_F32)
+ return (F32) sd.asReal();
+ else
+ {
+ CONTROL_ERRS << "Invalid F32 value" << llendl;
+ return 0.0f;
+ }
+}
+
+template<>
+std::string convert_from_llsd<std::string>(const LLSD& sd, eControlType type, const std::string& control_name)
+{
+ if (type == TYPE_STRING)
+ return sd.asString();
+ else
+ {
+ CONTROL_ERRS << "Invalid string value" << llendl;
+ return LLStringUtil::null;
+ }
+}
+
+template<>
+LLWString convert_from_llsd<LLWString>(const LLSD& sd, eControlType type, const std::string& control_name)
+{
+ return utf8str_to_wstring(convert_from_llsd<std::string>(sd, type, control_name));
+}
+
+template<>
+LLVector3 convert_from_llsd<LLVector3>(const LLSD& sd, eControlType type, const std::string& control_name)
+{
+ if (type == TYPE_VEC3)
+ return sd;
+ else
+ {
+ CONTROL_ERRS << "Invalid LLVector3 value" << llendl;
+ return LLVector3::zero;
+ }
+}
+
+template<>
+LLVector3d convert_from_llsd<LLVector3d>(const LLSD& sd, eControlType type, const std::string& control_name)
+{
+ if (type == TYPE_VEC3D)
+ return sd;
+ else
+ {
+ CONTROL_ERRS << "Invalid LLVector3d value" << llendl;
+ return LLVector3d::zero;
+ }
+}
+
+template<>
+LLRect convert_from_llsd<LLRect>(const LLSD& sd, eControlType type, const std::string& control_name)
+{
+ if (type == TYPE_RECT)
+ return sd;
+ else
+ {
+ CONTROL_ERRS << "Invalid rect value" << llendl;
+ return LLRect::null;
+ }
+}
+
+
+template<>
+LLColor4 convert_from_llsd<LLColor4>(const LLSD& sd, eControlType type, const std::string& control_name)
+{
+ if (type == TYPE_COL4)
+ {
+ LLColor4 color(sd);
+ if (color.mV[VRED] < 0.f || color.mV[VRED] > 1.f)
+ {
+ llwarns << "Color " << control_name << " value out of range " << llendl;
+ }
+ else if (color.mV[VGREEN] < 0.f || color.mV[VGREEN] > 1.f)
+ {
+ llwarns << "Color " << control_name << " value out of range " << llendl;
+ }
+ else if (color.mV[VBLUE] < 0.f || color.mV[VBLUE] > 1.f)
+ {
+ llwarns << "Color " << control_name << " value out of range " << llendl;
+ }
+ else if (color.mV[VALPHA] < 0.f || color.mV[VALPHA] > 1.f)
+ {
+ llwarns << "Color " << control_name << " value out of range " << llendl;
+ }
+
+ return LLColor4(sd);
+ }
+ else
+ {
+ CONTROL_ERRS << "Control " << control_name << " not a color" << llendl;
+ return LLColor4::white;
+ }
+}
+
+template<>
+LLColor3 convert_from_llsd<LLColor3>(const LLSD& sd, eControlType type, const std::string& control_name)
+{
+ if (type == TYPE_COL3)
+ return sd;
+ else
+ {
+ CONTROL_ERRS << "Invalid LLColor3 value" << llendl;
+ return LLColor3::white;
+ }
+}
+
+template<>
+LLSD convert_from_llsd<LLSD>(const LLSD& sd, eControlType type, const std::string& control_name)
+{
+ return sd;
+}
+
+
+#if TEST_CACHED_CONTROL
+
+#define DECL_LLCC(T, V) static LLCachedControl<T> mySetting_##T("TestCachedControl"#T, V)
+DECL_LLCC(U32, (U32)666);
+DECL_LLCC(S32, (S32)-666);
+DECL_LLCC(F32, (F32)-666.666);
+DECL_LLCC(bool, true);
+DECL_LLCC(BOOL, FALSE);
+static LLCachedControl<std::string> mySetting_string("TestCachedControlstring", "Default String Value");
+DECL_LLCC(LLVector3, LLVector3(1.0f, 2.0f, 3.0f));
+DECL_LLCC(LLVector3d, LLVector3d(6.0f, 5.0f, 4.0f));
+DECL_LLCC(LLRect, LLRect(0, 0, 100, 500));
+DECL_LLCC(LLColor4, LLColor4(0.0f, 0.5f, 1.0f));
+DECL_LLCC(LLColor3, LLColor3(1.0f, 0.f, 0.5f));
+DECL_LLCC(LLColor4U, LLColor4U(255, 200, 100, 255));
+
+LLSD test_llsd = LLSD()["testing1"] = LLSD()["testing2"];
+DECL_LLCC(LLSD, test_llsd);
+
+static LLCachedControl<std::string> test_BrowserHomePage("BrowserHomePage", "hahahahahha", "Not the real comment");
+
+void test_cached_control()
+{
+#define TEST_LLCC(T, V) if((T)mySetting_##T != V) llerrs << "Fail "#T << llendl
+ TEST_LLCC(U32, 666);
+ TEST_LLCC(S32, (S32)-666);
+ TEST_LLCC(F32, (F32)-666.666);
+ TEST_LLCC(bool, true);
+ TEST_LLCC(BOOL, FALSE);
+ if((std::string)mySetting_string != "Default String Value") llerrs << "Fail string" << llendl;
+ TEST_LLCC(LLVector3, LLVector3(1.0f, 2.0f, 3.0f));
+ TEST_LLCC(LLVector3d, LLVector3d(6.0f, 5.0f, 4.0f));
+ TEST_LLCC(LLRect, LLRect(0, 0, 100, 500));
+ TEST_LLCC(LLColor4, LLColor4(0.0f, 0.5f, 1.0f));
+ TEST_LLCC(LLColor3, LLColor3(1.0f, 0.f, 0.5f));
+ TEST_LLCC(LLColor4U, LLColor4U(255, 200, 100, 255));
+//There's no LLSD comparsion for LLCC yet. TEST_LLCC(LLSD, test_llsd);
+
+ if((std::string)test_BrowserHomePage != "http://www.secondlife.com") llerrs << "Fail BrowserHomePage" << llendl;
+}
+#endif // TEST_CACHED_CONTROL
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
diff --git a/indra/llxml/llcontrolgroupreader.h b/indra/llxml/llcontrolgroupreader.h
index 960b19036e..116ea2eae0 100644
--- a/indra/llxml/llcontrolgroupreader.h
+++ b/indra/llxml/llcontrolgroupreader.h
@@ -3,7 +3,30 @@
* @brief Interface providing readonly access to LLControlGroup (intended for unit testing)
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
* Copyright (c) 2001-2009, 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$
*/
@@ -13,9 +36,11 @@
#include "stdtypes.h"
#include <string>
-// Many of the types below are commented out because for the purposes of the early testing we're doing,
-// we don't need them and we don't want to pull in all the machinery to support them.
-// But the model is here for future unit test extensions.
+#include "v3math.h"
+#include "v3dmath.h"
+#include "v3color.h"
+#include "v4color.h"
+#include "llrect.h"
class LLControlGroupReader
{
@@ -23,22 +48,32 @@ public:
LLControlGroupReader() {}
virtual ~LLControlGroupReader() {}
- virtual std::string getString(const std::string& name) = 0;
- //virtual LLWString getWString(const std::string& name) = 0;
- virtual std::string getText(const std::string& name) = 0;
- //virtual LLVector3 getVector3(const std::string& name) = 0;
- //virtual LLVector3d getVector3d(const std::string& name) = 0;
- //virtual LLRect getRect(const std::string& name) = 0;
- virtual BOOL getBOOL(const std::string& name) = 0;
- virtual S32 getS32(const std::string& name) = 0;
- virtual F32 getF32(const std::string& name) = 0;
- virtual U32 getU32(const std::string& name) = 0;
- //virtual LLSD getLLSD(const std::string& name) = 0;
-
- //virtual LLColor4 getColor(const std::string& name) = 0;
- //virtual LLColor4U getColor4U(const std::string& name) = 0;
- //virtual LLColor4 getColor4(const std::string& name) = 0;
- //virtual LLColor3 getColor3(const std::string& name) = 0;
+ virtual std::string getString(const std::string& name) { return ""; }
+ virtual LLWString getWString(const std::string& name) { return LLWString(); }
+ virtual std::string getText(const std::string& name) { return ""; }
+ virtual LLVector3 getVector3(const std::string& name) { return LLVector3(); }
+ virtual LLVector3d getVector3d(const std::string& name) { return LLVector3d(); }
+ virtual LLRect getRect(const std::string& name) { return LLRect(); }
+ virtual BOOL getBOOL(const std::string& name) { return FALSE; }
+ virtual S32 getS32(const std::string& name) { return 0; }
+ virtual F32 getF32(const std::string& name) {return 0.0f; }
+ virtual U32 getU32(const std::string& name) {return 0; }
+ virtual LLSD getLLSD(const std::string& name) { return LLSD(); }
+
+ virtual LLColor4 getColor(const std::string& name) { return LLColor4(); }
+ virtual LLColor4 getColor4(const std::string& name) { return LLColor4(); }
+ virtual LLColor3 getColor3(const std::string& name) { return LLColor3(); }
+
+ virtual void setBOOL(const std::string& name, BOOL val) {}
+ virtual void setS32(const std::string& name, S32 val) {}
+ virtual void setF32(const std::string& name, F32 val) {}
+ virtual void setU32(const std::string& name, U32 val) {}
+ virtual void setString(const std::string& name, const std::string& val) {}
+ virtual void setVector3(const std::string& name, const LLVector3 &val) {}
+ virtual void setVector3d(const std::string& name, const LLVector3d &val) {}
+ virtual void setRect(const std::string& name, const LLRect &val) {}
+ virtual void setColor4(const std::string& name, const LLColor4 &val) {}
+ virtual void setLLSD(const std::string& name, const LLSD& val) {}
};
#endif /* LL_LLCONTROLGROUPREADER_H */
diff --git a/indra/llxml/llxmlnode.cpp b/indra/llxml/llxmlnode.cpp
index 800b13573f..e97aa55190 100644
--- a/indra/llxml/llxmlnode.cpp
+++ b/indra/llxml/llxmlnode.cpp
@@ -47,6 +47,7 @@
#include "llquaternion.h"
#include "llstring.h"
#include "lluuid.h"
+#include "lldir.h"
const S32 MAX_COLUMN_WIDTH = 80;
@@ -64,6 +65,7 @@ LLXMLNode::LLXMLNode() :
mPrecision(64),
mType(TYPE_CONTAINER),
mEncoding(ENCODING_DEFAULT),
+ mLineNumber(-1),
mParent(NULL),
mChildren(NULL),
mAttributes(),
@@ -85,6 +87,7 @@ LLXMLNode::LLXMLNode(const char* name, BOOL is_attribute) :
mPrecision(64),
mType(TYPE_CONTAINER),
mEncoding(ENCODING_DEFAULT),
+ mLineNumber(-1),
mParent(NULL),
mChildren(NULL),
mAttributes(),
@@ -106,6 +109,7 @@ LLXMLNode::LLXMLNode(LLStringTableEntry* name, BOOL is_attribute) :
mPrecision(64),
mType(TYPE_CONTAINER),
mEncoding(ENCODING_DEFAULT),
+ mLineNumber(-1),
mParent(NULL),
mChildren(NULL),
mAttributes(),
@@ -226,6 +230,10 @@ BOOL LLXMLNode::removeChild(LLXMLNode *target_child)
{
mChildren->head = target_child->mNext;
}
+ if (target_child == mChildren->tail)
+ {
+ mChildren->tail = target_child->mPrev;
+ }
LLXMLNodePtr prev = target_child->mPrev;
LLXMLNodePtr next = target_child->mNext;
@@ -387,6 +395,7 @@ void XMLCALL StartXMLNode(void *userData,
{
// Create a new node
LLXMLNode *new_node_ptr = new LLXMLNode(name, FALSE);
+
LLXMLNodePtr new_node = new_node_ptr;
new_node->mID.clear();
LLXMLNodePtr ptr_new_node = new_node;
@@ -401,7 +410,8 @@ void XMLCALL StartXMLNode(void *userData,
}
new_node_ptr->mParser = parent->mParser;
-
+ new_node_ptr->setLineNumber(XML_GetCurrentLineNumber(*new_node_ptr->mParser));
+
// Set the current active node to the new node
XML_Parser *parser = parent->mParser;
XML_SetUserData(*parser, (void *)new_node_ptr);
@@ -492,6 +502,7 @@ void XMLCALL StartXMLNode(void *userData,
if (!new_node->getAttribute(attr_name.c_str(), attr_node, FALSE))
{
attr_node = new LLXMLNode(attr_name.c_str(), TRUE);
+ attr_node->setLineNumber(XML_GetCurrentLineNumber(*new_node_ptr->mParser));
}
attr_node->setValue(attr_value);
new_node->addChild(attr_node);
@@ -836,12 +847,66 @@ BOOL LLXMLNode::isFullyDefault()
}
// static
-void LLXMLNode::writeHeaderToFile(LLFILE *fOut)
+bool LLXMLNode::getLayeredXMLNode(const std::string &xui_filename, LLXMLNodePtr& root,
+ const std::vector<std::string>& paths)
+{
+ std::string full_filename = gDirUtilp->findSkinnedFilename(paths.front(), xui_filename);
+ if (full_filename.empty())
+ {
+ return false;
+ }
+
+ if (!LLXMLNode::parseFile(full_filename, root, NULL))
+ {
+ // try filename as passed in since sometimes we load an xml file from a user-supplied path
+ if (!LLXMLNode::parseFile(xui_filename, root, NULL))
+ {
+ llwarns << "Problem reading UI description file: " << xui_filename << llendl;
+ return false;
+ }
+ }
+
+ LLXMLNodePtr updateRoot;
+
+ std::vector<std::string>::const_iterator itor;
+
+ for (itor = paths.begin(), ++itor; itor != paths.end(); ++itor)
+ {
+ std::string nodeName;
+ std::string updateName;
+
+ std::string layer_filename = gDirUtilp->findSkinnedFilename((*itor), xui_filename);
+ if(layer_filename.empty())
+ {
+ // no localized version of this file, that's ok, keep looking
+ continue;
+ }
+
+ if (!LLXMLNode::parseFile(layer_filename, updateRoot, NULL))
+ {
+ llwarns << "Problem reading localized UI description file: " << (*itor) + gDirUtilp->getDirDelimiter() + xui_filename << llendl;
+ return false;
+ }
+
+ updateRoot->getAttributeString("name", updateName);
+ root->getAttributeString("name", nodeName);
+
+ if (updateName == nodeName)
+ {
+ LLXMLNode::updateNode(root, updateRoot);
+ }
+ }
+
+ return true;
+}
+
+// static
+void LLXMLNode::writeHeaderToFile(LLFILE *out_file)
{
- fprintf(fOut, "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>\n");
+ fprintf(out_file, "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>\n");
}
-void LLXMLNode::writeToFile(LLFILE *fOut, const std::string& indent)
+void LLXMLNode::writeToFile(LLFILE *out_file, const std::string& indent)
{
if (isFullyDefault())
{
@@ -852,7 +917,8 @@ void LLXMLNode::writeToFile(LLFILE *fOut, const std::string& indent)
std::ostringstream ostream;
writeToOstream(ostream, indent);
std::string outstring = ostream.str();
- if (fwrite(outstring.c_str(), 1, outstring.length(), fOut) != outstring.length())
+ size_t written = fwrite(outstring.c_str(), 1, outstring.length(), out_file);
+ if (written != outstring.length())
{
llwarns << "Short write" << llendl;
}
@@ -872,12 +938,12 @@ void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& i
BOOL has_default_length = mDefault.isNull()?FALSE:(mLength == mDefault->mLength);
// stream the name
- output_stream << indent << "<" << mName->mString;
+ output_stream << indent << "<" << mName->mString << "\n";
// ID
if (mID != "")
{
- output_stream << " id=\"" << mID << "\"";
+ output_stream << indent << " id=\"" << mID << "\"\n";
}
// Type
@@ -886,22 +952,22 @@ void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& i
switch (mType)
{
case TYPE_BOOLEAN:
- output_stream << " type=\"boolean\"";
+ output_stream << indent << " type=\"boolean\"\n";
break;
case TYPE_INTEGER:
- output_stream << " type=\"integer\"";
+ output_stream << indent << " type=\"integer\"\n";
break;
case TYPE_FLOAT:
- output_stream << " type=\"float\"";
+ output_stream << indent << " type=\"float\"\n";
break;
case TYPE_STRING:
- output_stream << " type=\"string\"";
+ output_stream << indent << " type=\"string\"\n";
break;
case TYPE_UUID:
- output_stream << " type=\"uuid\"";
+ output_stream << indent << " type=\"uuid\"\n";
break;
case TYPE_NODEREF:
- output_stream << " type=\"noderef\"";
+ output_stream << indent << " type=\"noderef\"\n";
break;
default:
// default on switch(enum) eliminates a warning on linux
@@ -915,13 +981,13 @@ void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& i
switch (mEncoding)
{
case ENCODING_DECIMAL:
- output_stream << " encoding=\"decimal\"";
+ output_stream << indent << " encoding=\"decimal\"\n";
break;
case ENCODING_HEX:
- output_stream << " encoding=\"hex\"";
+ output_stream << indent << " encoding=\"hex\"\n";
break;
/*case ENCODING_BASE32:
- output_stream << " encoding=\"base32\"";
+ output_stream << indent << " encoding=\"base32\"\n";
break;*/
default:
// default on switch(enum) eliminates a warning on linux
@@ -932,24 +998,23 @@ void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& i
// Precision
if (!has_default_precision && (mType == TYPE_INTEGER || mType == TYPE_FLOAT))
{
- output_stream << " precision=\"" << mPrecision << "\"";
+ output_stream << indent << " precision=\"" << mPrecision << "\"\n";
}
// Version
if (mVersionMajor > 0 || mVersionMinor > 0)
{
- output_stream << " version=\"" << mVersionMajor << "." << mVersionMinor << "\"";
+ output_stream << indent << " version=\"" << mVersionMajor << "." << mVersionMinor << "\"\n";
}
// Array length
if (!has_default_length && mLength > 0)
{
- output_stream << " length=\"" << mLength << "\"";
+ output_stream << indent << " length=\"" << mLength << "\"\n";
}
{
// Write out attributes
- S32 col_pos = 0;
LLXMLAttribList::const_iterator attr_itr;
LLXMLAttribList::const_iterator attr_end = mAttributes.end();
for (attr_itr = mAttributes.begin(); attr_itr != attr_end; ++attr_itr)
@@ -971,17 +1036,14 @@ void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& i
std::string attr_str = llformat(" %s=\"%s\"",
attr.c_str(),
escapeXML(child->mValue).c_str());
- if (col_pos + (S32)attr_str.length() > MAX_COLUMN_WIDTH)
- {
- output_stream << "\n" << indent << " ";
- col_pos = 4;
- }
- col_pos += attr_str.length();
- output_stream << attr_str;
+ output_stream << indent << attr_str << "\n";
}
}
}
+ // erase last \n before attaching final > or />
+ output_stream.seekp(-1, std::ios::cur);
+
if (mChildren.isNull() && mValue == "")
{
output_stream << " />\n";
@@ -993,7 +1055,7 @@ void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& i
if (mChildren.notNull())
{
// stream non-attributes
- std::string next_indent = indent + "\t";
+ std::string next_indent = indent + " ";
for (LLXMLNode* child = getFirstChild(); child; child = child->getNextSibling())
{
child->writeToOstream(output_stream, next_indent);
@@ -1002,7 +1064,7 @@ void LLXMLNode::writeToOstream(std::ostream& output_stream, const std::string& i
if (!mValue.empty())
{
std::string contents = getTextContents();
- output_stream << indent << "\t" << escapeXML(contents) << "\n";
+ output_stream << indent << " " << escapeXML(contents) << "\n";
}
output_stream << indent << "</" << mName->mString << ">\n";
}
@@ -2475,14 +2537,15 @@ std::string LLXMLNode::escapeXML(const std::string& xml)
return out;
}
-void LLXMLNode::setStringValue(U32 length, const std::string *array)
+void LLXMLNode::setStringValue(U32 length, const std::string *strings)
{
if (length == 0) return;
std::string new_value;
for (U32 pos=0; pos<length; ++pos)
{
- new_value.append(escapeXML(array[pos]));
+ // *NOTE: Do not escape strings here - do it on output
+ new_value.append( strings[pos] );
if (pos < length-1) new_value.append(" ");
}
@@ -3150,6 +3213,19 @@ LLXMLNodePtr LLXMLNode::getNextSibling() const
return ret;
}
+std::string LLXMLNode::getSanitizedValue() const
+{
+ if (mIsAttribute)
+ {
+ return getValue() ;
+ }
+ else
+ {
+ return getTextContents();
+ }
+}
+
+
std::string LLXMLNode::getTextContents() const
{
std::string msg;
@@ -3215,3 +3291,13 @@ std::string LLXMLNode::getTextContents() const
}
return msg;
}
+
+void LLXMLNode::setLineNumber(S32 line_number)
+{
+ mLineNumber = line_number;
+}
+
+S32 LLXMLNode::getLineNumber()
+{
+ return mLineNumber;
+}
diff --git a/indra/llxml/llxmlnode.h b/indra/llxml/llxmlnode.h
index d4e127b05c..c983a14410 100644
--- a/indra/llxml/llxmlnode.h
+++ b/indra/llxml/llxmlnode.h
@@ -44,8 +44,8 @@
#include <map>
#include "indra_constants.h"
-#include "llmemory.h"
-#include "llthread.h"
+#include "llpointer.h"
+#include "llthread.h" // LLThreadSafeRefCount
#include "llstring.h"
#include "llstringtable.h"
@@ -153,8 +153,18 @@ public:
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());
+
+ static bool getLayeredXMLNode(const std::string &xui_filename, LLXMLNodePtr& root,
+ const std::vector<std::string>& paths);
+
+
+ // Write standard XML file header:
+ // <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+ static void writeHeaderToFile(LLFILE *out_file);
+
+ // Write XML to file with one attribute per line.
+ // XML escapes values as they are written.
+ void writeToFile(LLFILE *out_file, const std::string& indent = std::string());
void writeToOstream(std::ostream& output_stream, const std::string& indent = std::string());
// Utility
@@ -207,6 +217,7 @@ public:
U32 getLength() const { return mLength; }
U32 getPrecision() const { return mPrecision; }
const std::string& getValue() const { return mValue; }
+ std::string getSanitizedValue() const;
std::string getTextContents() const;
const LLStringTableEntry* getName() const { return mName; }
BOOL hasName(const char* name) const { return mName == gStringTable.checkStringEntry(name); }
@@ -227,6 +238,8 @@ public:
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);
+ S32 getLineNumber();
+
// The following skip over attributes
LLXMLNodePtr getFirstChild() const;
LLXMLNodePtr getNextSibling() const;
@@ -262,6 +275,8 @@ public:
void setName(const std::string& name);
void setName(LLStringTableEntry* name);
+ void setLineNumber(S32 line_number);
+
// Escapes " (quot) ' (apos) & (amp) < (lt) > (gt)
static std::string escapeXML(const std::string& xml);
@@ -300,6 +315,7 @@ public:
U32 mPrecision; // The number of BITS per array item
ValueType mType; // The value type
Encoding mEncoding; // The value encoding
+ S32 mLineNumber; // line number in source file, if applicable
LLXMLNode* mParent; // The parent node
LLXMLChildrenPtr mChildren; // The child nodes
@@ -312,7 +328,11 @@ public:
protected:
LLStringTableEntry *mName; // The name of this node
- std::string mValue; // The value of this node (use getters/setters only)
+
+ // The value of this node (use getters/setters only)
+ // Values are not XML-escaped in memory
+ // They may contain " (quot) ' (apos) & (amp) < (lt) > (gt)
+ std::string mValue;
LLXMLNodePtr mDefault; // Mirror node in the default tree