diff options
author | Steven Bennetts <steve@lindenlab.com> | 2008-03-20 21:41:26 +0000 |
---|---|---|
committer | Steven Bennetts <steve@lindenlab.com> | 2008-03-20 21:41:26 +0000 |
commit | e3b97ac65b10a58c1dac041743e4acd1042492f5 (patch) | |
tree | 1648189fd15e51ac1c2eb8d8018faa775c93f6d3 /indra/llxml | |
parent | b502c86f30d3ed01b795548364ab8090363eeac5 (diff) |
merge release@82383 viewer-cleanup2-7-merge@82828
QAR-369
Diffstat (limited to 'indra/llxml')
-rw-r--r-- | indra/llxml/llcontrol.cpp | 816 | ||||
-rw-r--r-- | indra/llxml/llcontrol.h | 210 |
2 files changed, 328 insertions, 698 deletions
diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp index 4ad44f455f..9de426fc03 100644 --- a/indra/llxml/llcontrol.cpp +++ b/indra/llxml/llcontrol.cpp @@ -57,19 +57,9 @@ #endif //this defines the current version of the settings file -U32 LLControlBase::sMaxControlNameLength = 0; - -//These lists are used to store the ID's of registered event listeners. -std::list<S32> LLControlBase::mFreeIDs; -std::list<S32> LLControlBase::mUsedIDs; - -S32 LLControlBase::mTopID; - -std::set<LLControlBase*> LLControlBase::mChangedControls; - const S32 CURRENT_VERSION = 101; -BOOL LLControl::llsd_compare(const LLSD& a, const LLSD & b) +BOOL LLControlVariable::llsd_compare(const LLSD& a, const LLSD & b) { switch (mType) { @@ -101,58 +91,154 @@ BOOL LLControl::llsd_compare(const LLSD& a, const LLSD & b) return FALSE; } -LLControlBase::~LLControlBase() +LLControlVariable::LLControlVariable(const LLString& name, eControlType type, + LLSD initial, const LLString& comment, + BOOL persist) + : mName(name), + mComment(comment), + mType(type), + mPersist(persist) +{ + if (mPersist && mComment.empty()) + { + llerrs << "Must supply a comment for control " << mName << llendl; + } + //Push back versus setValue'ing here, since we don't want to call a signal yet + mValues.push_back(initial); +} + + + +LLControlVariable::~LLControlVariable() +{ +} + +void LLControlVariable::setValue(const LLSD& value, bool saved_value) { + bool value_changed = llsd_compare(getValue(), value) == FALSE; + if(saved_value) + { + // If we're going to save this value, return to default but don't fire + resetToDefault(false); + if (llsd_compare(mValues.back(), value) == FALSE) + { + mValues.push_back(value); + } + } + else + { + // This is a unsaved value. Its needs to reside at + // mValues[2] (or greater). It must not affect + // the result of getSaveValue() + if (llsd_compare(mValues.back(), value) == FALSE) + { + while(mValues.size() > 2) + { + // Remove any unsaved values. + mValues.pop_back(); + } + + if(mValues.size() < 2) + { + // Add the default to the 'save' value. + mValues.push_back(mValues[0]); + } + + // Add the 'un-save' value. + mValues.push_back(value); + } + } + + if(value_changed) + { + mSignal(value); + } } -// virtual -void LLControlBase::resetToDefault() +void LLControlVariable::resetToDefault(bool fire_signal) { + //The first setting is always the default + //Pop to it and fire off the listener + while(mValues.size() > 1) mValues.pop_back(); + if(fire_signal) firePropertyChanged(); +} + +bool LLControlVariable::isSaveValueDefault() +{ + return (mValues.size() == 1) + || ((mValues.size() > 1) && llsd_compare(mValues[1], mValues[0])); } -LLControlGroup::LLControlGroup(): mNameTable() +LLSD LLControlVariable::getSaveValue() const { - //mFreeStringOffset = 0; + //The first level of the stack is default + //We assume that the second level is user preferences that should be saved + if(mValues.size() > 1) return mValues[1]; + return mValues[0]; } -LLControlGroup::~LLControlGroup() +LLControlVariable* LLControlGroup::getControl(const LLString& name) +{ + ctrl_name_table_t::iterator iter = mNameTable.find(name); + return iter == mNameTable.end() ? NULL : iter->second; +} + + +//////////////////////////////////////////////////////////////////////////// + +LLControlGroup::LLControlGroup() { + mTypeString[TYPE_U32] = "U32"; + mTypeString[TYPE_S32] = "S32"; + mTypeString[TYPE_F32] = "F32"; + mTypeString[TYPE_BOOLEAN] = "Boolean"; + mTypeString[TYPE_STRING] = "String"; + mTypeString[TYPE_VEC3] = "Vector3"; + mTypeString[TYPE_VEC3D] = "Vector3D"; + mTypeString[TYPE_RECT] = "Rect"; + mTypeString[TYPE_COL4] = "Color4"; + mTypeString[TYPE_COL3] = "Color3"; + mTypeString[TYPE_COL4U] = "Color4u"; + mTypeString[TYPE_LLSD] = "LLSD"; } -LLSD LLControlBase::registerListener(LLSimpleListenerObservable *listener, LLSD userdata) +LLControlGroup::~LLControlGroup() { - // Symmetric listener relationship - addListener(listener, "", userdata); - listener->addListener(this, "", userdata); - return getValue(); + cleanup(); } void LLControlGroup::cleanup() { + for_each(mNameTable.begin(), mNameTable.end(), DeletePairedPointer()); mNameTable.clear(); } -LLControlBase* LLControlGroup::getControl(const LLString& name) +eControlType LLControlGroup::typeStringToEnum(const LLString& typestr) { - ctrl_name_table_t::iterator iter = mNameTable.find(name); - return iter == mNameTable.end() ? NULL : (LLControlBase*)iter->second; + for(int i = 0; i < (int)TYPE_COUNT; ++i) + { + if(mTypeString[i] == typestr) return (eControlType)i; + } + return (eControlType)-1; +} + +LLString LLControlGroup::typeEnumToString(eControlType typeenum) +{ + return mTypeString[typeenum]; } BOOL LLControlGroup::declareControl(const LLString& name, eControlType type, const LLSD initial_val, const LLString& comment, BOOL persist) { - if(!mNameTable[name]) - { - // if not, create the control and add it to the name table - LLControl* control = new LLControl(name, type, initial_val, comment, persist); - mNameTable[name] = control; - return TRUE; - } - else + if(mNameTable.find(name) != mNameTable.end()) { llwarns << "LLControlGroup::declareControl: Control named " << name << " already exists." << llendl; - mNameTable.erase(name); - return FALSE; + mNameTable[name]->setValue(initial_val); + return TRUE; } + // if not, create the control and add it to the name table + LLControlVariable* control = new LLControlVariable(name, type, initial_val, comment, persist); + mNameTable[name] = control; + return TRUE; } BOOL LLControlGroup::declareU32(const LLString& name, const U32 initial_val, const LLString& comment, BOOL persist) @@ -210,19 +296,14 @@ BOOL LLControlGroup::declareColor3(const LLString& name, const LLColor3 &initial return declareControl(name, TYPE_COL3, initial_val.getValue(), comment, persist); } -LLSD LLControlGroup::registerListener(const LLString& name, LLSimpleListenerObservable *listener) +BOOL LLControlGroup::declareLLSD(const LLString& name, const LLSD &initial_val, const LLString& comment, BOOL persist ) { - LLControlBase *control = getControl(name); - if (control) - { - return control->registerListener(listener); - } - return LLSD(); + return declareControl(name, TYPE_LLSD, initial_val, comment, persist); } BOOL LLControlGroup::getBOOL(const LLString& name) { - LLControlBase* control = getControl(name); + LLControlVariable* control = getControl(name); if (control && control->isType(TYPE_BOOLEAN)) return control->get().asBoolean(); @@ -235,7 +316,7 @@ BOOL LLControlGroup::getBOOL(const LLString& name) S32 LLControlGroup::getS32(const LLString& name) { - LLControlBase* control = getControl(name); + LLControlVariable* control = getControl(name); if (control && control->isType(TYPE_S32)) return control->get().asInteger(); @@ -248,7 +329,7 @@ S32 LLControlGroup::getS32(const LLString& name) U32 LLControlGroup::getU32(const LLString& name) { - LLControlBase* control = getControl(name); + LLControlVariable* control = getControl(name); if (control && control->isType(TYPE_U32)) return control->get().asInteger(); @@ -261,7 +342,7 @@ U32 LLControlGroup::getU32(const LLString& name) F32 LLControlGroup::getF32(const LLString& name) { - LLControlBase* control = getControl(name); + LLControlVariable* control = getControl(name); if (control && control->isType(TYPE_F32)) return (F32) control->get().asReal(); @@ -274,7 +355,7 @@ F32 LLControlGroup::getF32(const LLString& name) LLString LLControlGroup::findString(const LLString& name) { - LLControlBase* control = getControl(name); + LLControlVariable* control = getControl(name); if (control && control->isType(TYPE_STRING)) return control->get().asString(); @@ -283,7 +364,7 @@ LLString LLControlGroup::findString(const LLString& name) LLString LLControlGroup::getString(const LLString& name) { - LLControlBase* control = getControl(name); + LLControlVariable* control = getControl(name); if (control && control->isType(TYPE_STRING)) return control->get().asString(); @@ -309,7 +390,7 @@ LLString LLControlGroup::getText(const LLString& name) LLVector3 LLControlGroup::getVector3(const LLString& name) { - LLControlBase* control = getControl(name); + LLControlVariable* control = getControl(name); if (control && control->isType(TYPE_VEC3)) return control->get(); @@ -322,7 +403,7 @@ LLVector3 LLControlGroup::getVector3(const LLString& name) LLVector3d LLControlGroup::getVector3d(const LLString& name) { - LLControlBase* control = getControl(name); + LLControlVariable* control = getControl(name); if (control && control->isType(TYPE_VEC3D)) return control->get(); @@ -335,7 +416,7 @@ LLVector3d LLControlGroup::getVector3d(const LLString& name) LLRect LLControlGroup::getRect(const LLString& name) { - LLControlBase* control = getControl(name); + LLControlVariable* control = getControl(name); if (control && control->isType(TYPE_RECT)) return control->get(); @@ -353,7 +434,7 @@ LLColor4 LLControlGroup::getColor(const LLString& name) if (i != mNameTable.end()) { - LLControlBase* control = i->second; + LLControlVariable* control = i->second; switch(control->mType) { @@ -381,7 +462,7 @@ LLColor4 LLControlGroup::getColor(const LLString& name) LLColor4U LLControlGroup::getColor4U(const LLString& name) { - LLControlBase* control = getControl(name); + LLControlVariable* control = getControl(name); if (control && control->isType(TYPE_COL4U)) return control->get(); @@ -394,7 +475,7 @@ LLColor4U LLControlGroup::getColor4U(const LLString& name) LLColor4 LLControlGroup::getColor4(const LLString& name) { - LLControlBase* control = getControl(name); + LLControlVariable* control = getControl(name); if (control && control->isType(TYPE_COL4)) return control->get(); @@ -407,7 +488,7 @@ LLColor4 LLControlGroup::getColor4(const LLString& name) LLColor3 LLControlGroup::getColor3(const LLString& name) { - LLControlBase* control = getControl(name); + LLControlVariable* control = getControl(name); if (control && control->isType(TYPE_COL3)) return control->get(); @@ -418,6 +499,16 @@ LLColor3 LLControlGroup::getColor3(const LLString& name) } } +LLSD LLControlGroup::getLLSD(const LLString& name) +{ + LLControlVariable* control = getControl(name); + + if (control && control->isType(TYPE_LLSD)) + return control->getValue(); + CONTROL_ERRS << "Invalid LLSD control " << name << llendl; + return LLSD(); +} + BOOL LLControlGroup::controlExists(const LLString& name) { ctrl_name_table_t::iterator iter = mNameTable.find(name); @@ -430,7 +521,7 @@ BOOL LLControlGroup::controlExists(const LLString& name) void LLControlGroup::setBOOL(const LLString& name, BOOL val) { - LLControlBase* control = getControl(name); + LLControlVariable* control = getControl(name); if (control && control->isType(TYPE_BOOLEAN)) { @@ -445,7 +536,7 @@ void LLControlGroup::setBOOL(const LLString& name, BOOL val) void LLControlGroup::setS32(const LLString& name, S32 val) { - LLControlBase* control = getControl(name); + LLControlVariable* control = getControl(name); if (control && control->isType(TYPE_S32)) { @@ -460,7 +551,7 @@ void LLControlGroup::setS32(const LLString& name, S32 val) void LLControlGroup::setF32(const LLString& name, F32 val) { - LLControlBase* control = getControl(name); + LLControlVariable* control = getControl(name); if (control && control->isType(TYPE_F32)) { @@ -475,7 +566,7 @@ void LLControlGroup::setF32(const LLString& name, F32 val) void LLControlGroup::setU32(const LLString& name, U32 val) { - LLControlBase* control = getControl(name); + LLControlVariable* control = getControl(name); if (control && control->isType(TYPE_U32)) { @@ -490,7 +581,7 @@ void LLControlGroup::setU32(const LLString& name, U32 val) void LLControlGroup::setString(const LLString& name, const LLString &val) { - LLControlBase* control = getControl(name); + LLControlVariable* control = getControl(name); if (control && control->isType(TYPE_STRING)) { @@ -505,7 +596,7 @@ void LLControlGroup::setString(const LLString& name, const LLString &val) void LLControlGroup::setVector3(const LLString& name, const LLVector3 &val) { - LLControlBase* control = getControl(name); + LLControlVariable* control = getControl(name); if (control && control->isType(TYPE_VEC3)) { @@ -519,7 +610,7 @@ void LLControlGroup::setVector3(const LLString& name, const LLVector3 &val) void LLControlGroup::setVector3d(const LLString& name, const LLVector3d &val) { - LLControlBase* control = getControl(name); + LLControlVariable* control = getControl(name); if (control && control->isType(TYPE_VEC3D)) { @@ -533,7 +624,7 @@ void LLControlGroup::setVector3d(const LLString& name, const LLVector3d &val) void LLControlGroup::setRect(const LLString& name, const LLRect &val) { - LLControlBase* control = getControl(name); + LLControlVariable* control = getControl(name); if (control && control->isType(TYPE_RECT)) { @@ -547,7 +638,7 @@ void LLControlGroup::setRect(const LLString& name, const LLRect &val) void LLControlGroup::setColor4U(const LLString& name, const LLColor4U &val) { - LLControlBase* control = getControl(name); + LLControlVariable* control = getControl(name); if (control && control->isType(TYPE_COL4U)) { @@ -561,7 +652,7 @@ void LLControlGroup::setColor4U(const LLString& name, const LLColor4U &val) void LLControlGroup::setColor4(const LLString& name, const LLColor4 &val) { - LLControlBase* control = getControl(name); + LLControlVariable* control = getControl(name); if (control && control->isType(TYPE_COL4)) { @@ -573,6 +664,20 @@ void LLControlGroup::setColor4(const LLString& name, const LLColor4 &val) } } +void LLControlGroup::setLLSD(const LLString& 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; + } +} + void LLControlGroup::setValue(const LLString& name, const LLSD& val) { if (name.empty()) @@ -580,7 +685,7 @@ void LLControlGroup::setValue(const LLString& name, const LLSD& val) return; } - LLControlBase* control = getControl(name); + LLControlVariable* control = getControl(name); if (control) { @@ -596,238 +701,8 @@ void LLControlGroup::setValue(const LLString& name, const LLSD& val) // Load and save //--------------------------------------------------------------- -U32 LLControlGroup::loadFromFileLegacy(const LLString& filename, BOOL require_declaration, eControlType declare_as) -{ - U32 item = 0; - U32 validitems = 0; - llifstream file; - S32 version; - - file.open(filename.c_str()); /*Flawfinder: ignore*/ - - if (!file) - { - llinfos << "LLControlGroup::loadFromFile unable to open." << llendl; - return 0; - } - - // Check file version - LLString name; - file >> name; - file >> version; - if (name != "version" || version != CURRENT_VERSION) - { - llinfos << filename << " does not appear to be a version " << CURRENT_VERSION << " controls file" << llendl; - return 0; - } - - while (!file.eof()) - { - file >> name; - - if (name.empty()) - { - continue; - } - - if (name.substr(0,2) == "//") - { - // This is a comment. - char buffer[MAX_STRING]; /*Flawfinder: ignore*/ - file.getline(buffer, MAX_STRING); - continue; - } - - BOOL declared = mNameTable.find(name) != mNameTable.end(); - - if (require_declaration && !declared) - { - // Declaration required, but this name not declared. - // Complain about non-empty names. - if (!name.empty()) - { - //read in to end of line - char buffer[MAX_STRING]; /*Flawfinder: ignore*/ - file.getline(buffer, MAX_STRING); - llwarns << "LLControlGroup::loadFromFile() : Trying to set \"" << name << "\", setting doesn't exist." << llendl; - } - continue; - } - - // Got an item. Load it up. - item++; - - // If not declared, assume it's a string - if (!declared) - { - switch(declare_as) - { - case TYPE_COL4: - declareColor4(name, LLColor4::white, LLString::null, NO_PERSIST); - break; - case TYPE_COL4U: - declareColor4U(name, LLColor4U::white, LLString::null, NO_PERSIST); - break; - case TYPE_STRING: - default: - declareString(name, LLString::null, LLString::null, NO_PERSIST); - break; - } - } - - // Control name has been declared in code. - LLControlBase *control = getControl(name); - - llassert(control); - - mLoadedSettings.insert(name); - - switch(control->mType) - { - case TYPE_F32: - { - F32 initial; - - file >> initial; - - control->set(initial); - validitems++; - } - break; - case TYPE_S32: - { - S32 initial; - - file >> initial; - - control->set(initial); - validitems++; - } - break; - case TYPE_U32: - { - U32 initial; - - file >> initial; - control->set((LLSD::Integer) initial); - validitems++; - } - break; - case TYPE_BOOLEAN: - { - char boolstring[256]; /*Flawfinder: ignore*/ - BOOL valid = FALSE; - BOOL initial = FALSE; - - file >> boolstring; - if (!strcmp("TRUE", boolstring)) - { - initial = TRUE; - valid = TRUE; - } - else if (!strcmp("FALSE", boolstring)) - { - initial = FALSE; - valid = TRUE; - } - - if (valid) - { - control->set(initial); - } - else - { - llinfos << filename << "Item " << item << ": Invalid BOOL control " << name << ", " << boolstring << llendl; - } - - validitems++; - } - break; - case TYPE_STRING: - { - LLString string; - - file >> string; - - control->set(string); - validitems++; - } - break; - case TYPE_VEC3: - { - F32 x, y, z; - - file >> x >> y >> z; - - LLVector3 vector(x, y, z); - - control->set(vector.getValue()); - validitems++; - } - break; - case TYPE_VEC3D: - { - F64 x, y, z; - - file >> x >> y >> z; - - LLVector3d vector(x, y, z); - - control->set(vector.getValue()); - validitems++; - } - break; - case TYPE_RECT: - { - S32 left, bottom, width, height; - - file >> left >> bottom >> width >> height; - - LLRect rect; - rect.setOriginAndSize(left, bottom, width, height); - - control->set(rect.getValue()); - validitems++; - } - break; - case TYPE_COL4U: - { - S32 red, green, blue, alpha; - LLColor4U color; - file >> red >> green >> blue >> alpha; - color.setVec(red, green, blue, alpha); - control->set(color.getValue()); - validitems++; - } - break; - case TYPE_COL4: - { - LLColor4 color; - file >> color.mV[VRED] >> color.mV[VGREEN] - >> color.mV[VBLUE] >> color.mV[VALPHA]; - control->set(color.getValue()); - validitems++; - } - break; - case TYPE_COL3: - { - LLColor3 color; - file >> color.mV[VRED] >> color.mV[VGREEN] - >> color.mV[VBLUE]; - control->set(color.getValue()); - validitems++; - } - break; - } - } - - file.close(); - - return validitems; -} - // Returns number of controls loaded, so 0 if failure -U32 LLControlGroup::loadFromFile(const LLString& filename, BOOL require_declaration, eControlType declare_as) +U32 LLControlGroup::loadFromFileLegacy(const LLString& filename, BOOL require_declaration, eControlType declare_as) { LLString name; @@ -901,11 +776,9 @@ U32 LLControlGroup::loadFromFile(const LLString& filename, BOOL require_declarat } // Control name has been declared in code. - LLControlBase *control = getControl(name); + LLControlVariable *control = getControl(name); llassert(control); - - mLoadedSettings.insert(name); switch(control->mType) { @@ -1019,59 +892,43 @@ U32 LLControlGroup::loadFromFile(const LLString& filename, BOOL require_declarat LLVector3 color; child_nodep->getAttributeVector3("value", color); - control->set(LLColor3(color.mV).getValue()); + control->set(LLColor3(color.mV).getValue()); validitems++; } break; - } + default: + break; + + } + child_nodep = rootp->getNextChild(); } return validitems; } -struct compare_controls -{ - bool operator() (const LLControlBase* const a, const LLControlBase* const b) const - { - return a->getName() < b->getName(); - } -}; - U32 LLControlGroup::saveToFile(const LLString& filename, BOOL nondefault_only) { - const char ENDL = '\n'; - - llinfos << "Saving settings to file: " << filename << llendl; - - // place the objects in a temporary container that enforces a sort - // order to ease manual editing of the file - - typedef std::set< LLControlBase*, compare_controls > control_list_t; - control_list_t controls; - + LLSD settings; + int num_saved = 0; for (ctrl_name_table_t::iterator iter = mNameTable.begin(); iter != mNameTable.end(); iter++) { - LLString name = iter->first; - if (name.empty()) - { - CONTROL_ERRS << "Control with no name found!!!" << llendl; - break; - } - - LLControlBase* control = (LLControlBase *)iter->second; + LLControlVariable* control = iter->second; if (!control) { - llwarns << "Tried to save invalid control: " << name << llendl; + llwarns << "Tried to save invalid control: " << iter->first << llendl; } - if( control && control->mPersist ) + if( control && control->isPersisted() ) { - if (!(nondefault_only && (control->mIsDefault))) + if (!(nondefault_only && (control->isSaveValueDefault()))) { - controls.insert( control ); + settings[iter->first]["Type"] = typeEnumToString(control->type()); + settings[iter->first]["Comment"] = control->getComment(); + settings[iter->first]["Value"] = control->getSaveValue(); + ++num_saved; } else { @@ -1080,156 +937,58 @@ U32 LLControlGroup::saveToFile(const LLString& filename, BOOL nondefault_only) } } } - llofstream file; - file.open(filename.c_str()); /*Flawfinder: ignore*/ - - if (!file.is_open()) + file.open(filename.c_str()); + if (file.is_open()) { - // This is a warning because sometime we want to use settings files which can't be written... - llwarns << "LLControlGroup::saveToFile unable to open file for writing" << llendl; - return 0; + LLSDSerialize::toPrettyXML(settings, file); + file.close(); + llinfos << "Saved to " << filename << llendl; } - - // Write file version - file << "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>\n"; - file << "<settings version = \"" << CURRENT_VERSION << "\">\n"; - for (control_list_t::iterator iter = controls.begin(); - iter != controls.end(); ++iter) + else { - LLControlBase* control = *iter; - file << "\t<!--" << control->comment() << "-->" << ENDL; - LLString name = control->getName(); - switch (control->type()) - { - case TYPE_U32: - { - file << "\t<" << name << " value=\"" << (U32) control->get().asInteger() << "\"/>\n"; - break; - } - case TYPE_S32: - { - file << "\t<" << name << " value=\"" << (S32) control->get().asInteger() << "\"/>\n"; - break; - } - case TYPE_F32: - { - file << "\t<" << name << " value=\"" << (F32) control->get().asReal() << "\"/>\n"; - break; - } - case TYPE_VEC3: - { - LLVector3 vector(control->get()); - file << "\t<" << name << " value=\"" << vector.mV[VX] << " " << vector.mV[VY] << " " << vector.mV[VZ] << "\"/>\n"; - break; - } - case TYPE_VEC3D: - { - LLVector3d vector(control->get()); - file << "\t<" << name << " value=\"" << vector.mdV[VX] << " " << vector.mdV[VY] << " " << vector.mdV[VZ] << "\"/>\n"; - break; - } - case TYPE_RECT: - { - LLRect rect(control->get()); - file << "\t<" << name << " value=\"" << rect.mLeft << " " << rect.mBottom << " " << rect.getWidth() << " " << rect.getHeight() << "\"/>\n"; - break; - } - case TYPE_COL4: - { - LLColor4 color(control->get()); - file << "\t<" << name << " value=\"" << color.mV[VRED] << ", " << color.mV[VGREEN] << ", " << color.mV[VBLUE] << ", " << color.mV[VALPHA] << "\"/>\n"; - break; - } - case TYPE_COL3: - { - LLColor3 color(control->get()); - file << "\t<" << name << " value=\"" << color.mV[VRED] << ", " << color.mV[VGREEN] << ", " << color.mV[VBLUE] << "\"/>\n"; - break; - } - case TYPE_BOOLEAN: - { - file << "\t<" << name << " value=\"" << (control->get().asBoolean() ? "TRUE" : "FALSE") << "\"/>\n"; - break; - } - case TYPE_STRING: - { - file << "\t<" << name << " value=\"" << LLSDXMLFormatter::escapeString(control->get().asString()) << "\"/>\n"; - break; - } - default: - { - CONTROL_ERRS << "LLControlGroup::saveToFile - unknown control type!" << llendl; - break; - } - } - - // Debug spam - // llinfos << name << " " << control->getValue().asString() << llendl; - }// next - - file << "</settings>\n"; - file.close(); - - return controls.size(); + // This is a warning because sometime we want to use settings files which can't be written... + llwarns << "Unable to open settings file: " << filename << llendl; + return 0; + } + return num_saved; } -void LLControlGroup::applyOverrides(const std::map<std::string, std::string>& overrides) +U32 LLControlGroup::loadFromFile(const LLString& filename, BOOL require_declaration, eControlType declare_as) { - for (std::map<std::string, std::string>::const_iterator iter = overrides.begin(); - iter != overrides.end(); ++iter) + LLString name; + LLSD settings; + LLSD control_map; + llifstream infile; + infile.open(filename.c_str()); + if(!infile.is_open()) { - const std::string& command = iter->first; - const std::string& value = iter->second; - LLControlBase* control = (LLControlBase *)mNameTable[command]; - if (control) - { - switch(control->mType) - { - case TYPE_U32: - control->set((LLSD::Integer)atof(value.c_str())); - break; - case TYPE_S32: - control->set((S32)atof(value.c_str())); - break; - case TYPE_F32: - control->set((F32)atof(value.c_str())); - break; - case TYPE_BOOLEAN: - if (!LLString::compareInsensitive(value.c_str(), "TRUE")) - { - control->set(TRUE); - } - else if (!LLString::compareInsensitive(value.c_str(), "FALSE")) - { - control->set(FALSE); - } - else - { - control->set((BOOL)atof(value.c_str())); - } - break; - case TYPE_STRING: - control->set(value); - break; -// // *FIX: implement this given time and need. -// case TYPE_UUID: -// break; - // we don't support command line overrides of vec3 or col4 - // yet - requires parsing of multiple values - case TYPE_VEC3: - case TYPE_VEC3D: - case TYPE_COL4: - case TYPE_COL3: - default: - break; - } - } - else - { - llinfos << "There is no control variable " << command << llendl; - } + llwarns << "Cannot find file " << filename << " to load." << llendl; + return 0; + } + S32 ret = LLSDSerialize::fromXML(settings, infile); + if (ret <= 0) + { + infile.close(); + llwarns << "Unable to open LLSD control file " << filename << ". Trying Legacy Method." << llendl; + return loadFromFileLegacy(filename, require_declaration, declare_as); + } + + U32 validitems = 0; + int persist = 1; + for(LLSD::map_const_iterator itr = settings.beginMap(); itr != settings.endMap(); ++itr) + { + name = (*itr).first; + control_map = (*itr).second; + + if(control_map.has("Persist")) persist = control_map["Persist"].asInteger(); + + declareControl(name, typeStringToEnum(control_map["Type"].asString()), control_map["Value"], control_map["Comment"].asString(), persist); + + ++validitems; } + + return validitems; } void LLControlGroup::resetToDefaults() @@ -1239,11 +998,20 @@ void LLControlGroup::resetToDefaults() control_iter != mNameTable.end(); ++control_iter) { - LLControlBase* control = (*control_iter).second; + LLControlVariable* control = (*control_iter).second; control->resetToDefault(); } } +void LLControlGroup::applyToAll(ApplyFunctor* func) +{ + for (ctrl_name_table_t::iterator iter = mNameTable.begin(); + iter != mNameTable.end(); iter++) + { + func->apply(iter->first, iter->second); + } +} + //============================================================================ // First-use @@ -1264,7 +1032,7 @@ static LLString get_warn_name(const LLString& name) void LLControlGroup::addWarning(const LLString& name) { LLString warnname = get_warn_name(name); - if(!mNameTable[warnname]) + if(mNameTable.find(warnname) == mNameTable.end()) { LLString comment = LLString("Enables ") + name + LLString(" warning dialog"); declareBOOL(warnname, TRUE, comment); @@ -1293,91 +1061,6 @@ void LLControlGroup::resetWarnings() } } - - -//============================================================================= -// Listener ID generator/management - -void LLControlBase::releaseListenerID(S32 id) -{ - mFreeIDs.push_back(id); -} - -S32 LLControlBase::allocateListenerID() -{ - if(mFreeIDs.size() == 0) - { //Out of IDs so generate some new ones. - for(int t=0;t<32;t++) - { - mFreeIDs.push_back(mTopID++); - } - } - S32 rtn = mFreeIDs.front(); - mFreeIDs.pop_front(); - mUsedIDs.push_back(rtn); - return rtn; -} - -bool LLControlBase::handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) -{ - if (event->desc() == "value_changed") - { - setValue(((LLValueChangedEvent*)(LLEvent*)event)->mValue); - return TRUE; - } - return TRUE; -} - -void LLControlBase::firePropertyChanged() -{ - LLValueChangedEvent *evt = new LLValueChangedEvent(this, getValue()); - fireEvent(evt, ""); -} - -//============================================================================ -// Used to add a listener callback that will be called on the frame that the controls value changes - -S32 LLControl::addListener(LLControl::tListenerCallback* cbfn) -{ - S32 id = allocateListenerID(); - mListeners.push_back(cbfn); - mListenerIDs.push_back( id ); - return id; -} - -void LLControl::updateListeners() { - LLControl::tPropertyChangedListIter iter = mChangeEvents.begin(); - while(iter!=mChangeEvents.end()){ - LLControl::tPropertyChangedEvent& evt = *iter; - (*evt.mCBFN)(evt.mNewValue,evt.mID,*this); - iter++; - } - mChangeEvents.clear(); -} - -//static -void LLControlBase::updateAllListeners() -{ - std::set< LLControlBase* >::iterator iter = mChangedControls.begin(); - while(iter != mChangedControls.end()){ - (*iter)->updateListeners(); - iter++; - } - mChangedControls.clear(); -} - -LLControl::LLControl( - const LLString& name, - eControlType type, - LLSD initial, - const LLString& comment, - BOOL persist) : - LLControlBase(name, type, comment, persist), - mCurrent(initial), - mDefault(initial) -{ -} - //============================================================================ #ifdef TEST_HARNESS @@ -1393,17 +1076,17 @@ void main() llinfos << "Loaded " << count << " controls" << llendl; // test insertion - foo = new LLControl<F32>("gFoo", 5.f, 1.f, 20.f); + foo = new LLControlVariable<F32>("gFoo", 5.f, 1.f, 20.f); gGlobals.addEntry("gFoo", foo); - bar = new LLControl<S32>("gBar", 10, 2, 22); + bar = new LLControlVariable<S32>("gBar", 10, 2, 22); gGlobals.addEntry("gBar", bar); - baz = new LLControl<BOOL>("gBaz", FALSE); + baz = new LLControlVariable<BOOL>("gBaz", FALSE); gGlobals.addEntry("gBaz", baz); // test retrieval - getfoo = (LLControl<F32>*) gGlobals.resolveName("gFoo"); + getfoo = (LLControlVariable<F32>*) gGlobals.resolveName("gFoo"); getfoo->dump(); getbar = (S32_CONTROL) gGlobals.resolveName("gBar"); @@ -1416,10 +1099,10 @@ void main() // Failure modes // ...min > max - // badfoo = new LLControl<F32>("gFoo2", 100.f, 20.f, 5.f); + // badfoo = new LLControlVariable<F32>("gFoo2", 100.f, 20.f, 5.f); // ...initial > max - // badbar = new LLControl<S32>("gBar2", 10, 20, 100000); + // badbar = new LLControlVariable<S32>("gBar2", 10, 20, 100000); // ...misspelled name // getfoo = (F32_CONTROL) gGlobals.resolveName("fooMisspelled"); @@ -1441,3 +1124,4 @@ void main() } #endif + diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h index a1a2a4c851..7a638a7b73 100644 --- a/indra/llxml/llcontrol.h +++ b/indra/llxml/llcontrol.h @@ -38,6 +38,26 @@ #include "llstring.h" #include "llrect.h" +#include <vector> + +// *NOTE: boost::visit_each<> generates warning 4675 on .net 2003 +// Disable the warning for the boost includes. +#if LL_WINDOWS +# if (_MSC_VER >= 1300 && _MSC_VER < 1400) +# pragma warning(push) +# pragma warning( disable : 4675 ) +# endif +#endif + +#include <boost/bind.hpp> +#include <boost/signal.hpp> + +#if LL_WINDOWS +# if (_MSC_VER >= 1300 && _MSC_VER < 1400) +# pragma warning(pop) +# endif +#endif + class LLVector3; class LLVector3d; class LLColor4; @@ -48,7 +68,7 @@ const BOOL NO_PERSIST = FALSE; typedef enum e_control_type { - TYPE_U32, + TYPE_U32 = 0, TYPE_S32, TYPE_F32, TYPE_BOOLEAN, @@ -58,159 +78,82 @@ typedef enum e_control_type TYPE_RECT, TYPE_COL4, TYPE_COL3, - TYPE_COL4U + TYPE_COL4U, + TYPE_LLSD, + TYPE_COUNT } eControlType; -class LLControlBase : public LLSimpleListenerObservable +class LLControlVariable { -friend class LLControlGroup; -protected: + friend class LLControlGroup; + typedef boost::signal<void(const LLSD&)> signal_t; + +private: LLString mName; LLString mComment; eControlType mType; - BOOL mHasRange; BOOL mPersist; - BOOL mIsDefault; - - static std::set<LLControlBase*> mChangedControls; - static std::list<S32> mFreeIDs;//These lists are used to store the ID's of registered event listeners. - static std::list<S32> mUsedIDs; - static S32 mTopID;//This is the index of the highest ID event listener ID. When the free pool is exhausted, new IDs are allocated from here. - + std::vector<LLSD> mValues; + + signal_t mSignal; + public: - static void releaseListenerID(S32 id); - static S32 allocateListenerID(); - static void updateAllListeners(); - virtual void updateListeners() = 0; - - LLControlBase(const LLString& name, eControlType type, const LLString& comment, BOOL persist) - : mName(name), - mComment(comment), - mType(type), - mHasRange(FALSE), - mPersist(persist), - mIsDefault(TRUE) - { - if (mPersist && mComment.empty()) - { - llerrs << "Must supply a comment for control " << mName << llendl; - } - sMaxControlNameLength = llmax((U32)mName.size(), sMaxControlNameLength); - } - - virtual ~LLControlBase(); + LLControlVariable(const LLString& name, eControlType type, + LLSD initial, const LLString& comment, + BOOL persist = TRUE); + virtual ~LLControlVariable(); + const LLString& getName() const { return mName; } const LLString& getComment() const { return mComment; } eControlType type() { return mType; } - BOOL isType(eControlType tp) { return tp == mType; } - - // Defaults to no-op - virtual void resetToDefault(); - - LLSD registerListener(LLSimpleListenerObservable *listener, LLSD userdata = ""); - - virtual LLSD get() const = 0; - virtual LLSD getValue() const = 0; - virtual void setValue(LLSD value) = 0; - virtual void set(LLSD value) = 0; - - // From LLSimpleListener - virtual bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata); - - void firePropertyChanged(); - - static U32 sMaxControlNameLength; - -protected: - const char* name() { return mName.c_str(); } - const char* comment() { return mComment.c_str(); } -}; - -class LLControl -: public LLControlBase -{ -friend class LLControlGroup; -protected: - LLSD mCurrent; - LLSD mDefault; - -public: - - typedef void tListenerCallback(const LLSD& newValue,S32 listenerID, LLControl& control); - typedef struct{ - S32 mID; - LLSD mNewValue; - tListenerCallback* mCBFN; - }tPropertyChangedEvent; - - typedef std::list<tPropertyChangedEvent>::iterator tPropertyChangedListIter; - std::list<tPropertyChangedEvent> mChangeEvents; - std::list< tListenerCallback* > mListeners; - std::list< S32 > mListenerIDs; - - virtual void updateListeners(); - S32 addListener(tListenerCallback* cbfn); - - LLControl( - const LLString& name, - eControlType type, - LLSD initial, const - LLString& comment, - BOOL persist = TRUE); - - void set(LLSD val) { setValue(val); } - LLSD get() const { return getValue(); } - LLSD getdefault() const { return mDefault; } - LLSD getValue() const { return mCurrent; } - BOOL llsd_compare(const LLSD& a, const LLSD& b); - - void setValue(LLSD value) - { - if (llsd_compare(mCurrent, value) == FALSE) - { - mCurrent = value; - mIsDefault = llsd_compare(mCurrent, mDefault); - firePropertyChanged(); - } - } - - /*virtual*/ void resetToDefault() - { - setValue(mDefault); - } - - virtual ~LLControl() + BOOL isType(eControlType tp) { return tp == mType; } + + void resetToDefault(bool fire_signal = TRUE); + + signal_t* getSignal() { return &mSignal; } + + bool isDefault() { return (mValues.size() == 1); } + bool isSaveValueDefault(); + bool isPersisted() { return mPersist; } + void set(const LLSD& val) { setValue(val); } + LLSD get() const { return getValue(); } + LLSD getDefault() const { return mValues.front(); } + LLSD getValue() const { return mValues.back(); } + LLSD getSaveValue() const; + void setValue(const LLSD& value, bool saved_value = TRUE); + void firePropertyChanged() { - //Remove and deregister all listeners.. - while(mListenerIDs.size()) - { - S32 id = mListenerIDs.front(); - mListenerIDs.pop_front(); - releaseListenerID(id); - } + mSignal(mValues.back()); } + BOOL llsd_compare(const LLSD& a, const LLSD& b); }; //const U32 STRING_CACHE_SIZE = 10000; class LLControlGroup { -public: - typedef std::map<LLString, LLPointer<LLControlBase> > ctrl_name_table_t; +protected: + typedef std::map<LLString, LLControlVariable* > ctrl_name_table_t; ctrl_name_table_t mNameTable; std::set<LLString> mWarnings; - std::set<LLString> mLoadedSettings; // Filled in with names loaded from settings.xml + LLString mTypeString[TYPE_COUNT]; + eControlType typeStringToEnum(const LLString& typestr); + LLString typeEnumToString(eControlType typeenum); public: LLControlGroup(); ~LLControlGroup(); void cleanup(); - bool hasLoaded(const LLString& name) { return mLoadedSettings.find(name) != mLoadedSettings.end(); } - void clearLoaded() { mLoadedSettings.clear(); } // Call once we've done any settings tweaks which may need this data - LLControlBase* getControl(const LLString& name); - LLSD registerListener(const LLString& name, LLSimpleListenerObservable *listener); + LLControlVariable* getControl(const LLString& name); + + struct ApplyFunctor + { + virtual ~ApplyFunctor() {}; + virtual void apply(const LLString& name, LLControlVariable* control) = 0; + }; + void applyToAll(ApplyFunctor* func); BOOL declareControl(const LLString& name, eControlType type, const LLSD initial_val, const LLString& comment, BOOL persist); BOOL declareU32(const LLString& name, U32 initial_val, const LLString& comment, BOOL persist = TRUE); @@ -224,6 +167,7 @@ public: BOOL declareColor4U(const LLString& name, const LLColor4U &initial_val, const LLString& comment, BOOL persist = TRUE); BOOL declareColor4(const LLString& name, const LLColor4 &initial_val, const LLString& comment, BOOL persist = TRUE); BOOL declareColor3(const LLString& name, const LLColor3 &initial_val, const LLString& comment, BOOL persist = TRUE); + BOOL declareLLSD(const LLString& name, const LLSD &initial_val, const LLString& comment, BOOL persist = TRUE); LLString findString(const LLString& name); @@ -237,7 +181,7 @@ public: S32 getS32(const LLString& name); F32 getF32(const LLString& name); U32 getU32(const LLString& name); - LLSD getValue(const LLString& name); + LLSD getLLSD(const LLString& name); // Note: If an LLColor4U control exists, it will cast it to the correct @@ -258,19 +202,21 @@ public: void setColor4U(const LLString& name, const LLColor4U &val); void setColor4(const LLString& name, const LLColor4 &val); void setColor3(const LLString& name, const LLColor3 &val); + void setLLSD(const LLString& name, const LLSD& val); void setValue(const LLString& name, const LLSD& val); - + + BOOL controlExists(const LLString& name); // Returns number of controls loaded, 0 if failed // If require_declaration is false, will auto-declare controls it finds // as the given type. - U32 loadFromFileLegacy(const LLString& filename, BOOL require_declaration = TRUE, eControlType declare_as = TYPE_STRING); - U32 loadFromFile(const LLString& filename, BOOL require_declaration = TRUE, eControlType declare_as = TYPE_STRING); - U32 saveToFile(const LLString& filename, BOOL skip_if_default); - void applyOverrides(const std::map<std::string, std::string>& overrides); + U32 loadFromFileLegacy(const LLString& filename, BOOL require_declaration = TRUE, eControlType declare_as = TYPE_STRING); + U32 saveToFile(const LLString& filename, BOOL nondefault_only); + U32 loadFromFile(const LLString& filename, BOOL require_declaration = TRUE, eControlType declare_as = TYPE_STRING); void resetToDefaults(); + // Ignorable Warnings // Add a config variable to be reset on resetWarnings() |