diff options
| author | Steven Bennetts <steve@lindenlab.com> | 2008-03-15 01:18:27 +0000 | 
|---|---|---|
| committer | Steven Bennetts <steve@lindenlab.com> | 2008-03-15 01:18:27 +0000 | 
| commit | 672a76d0ea08a0d0fc824e103ee4c4242b7e03ec (patch) | |
| tree | b623a9c884383ad75ed755b2c373db2b90643671 /indra/llxml | |
| parent | 04611efae8a3291ceba8a29dd920bdae0d404830 (diff) | |
reverting premature commit at 82410.
Diffstat (limited to 'indra/llxml')
| -rw-r--r-- | indra/llxml/llcontrol.cpp | 816 | ||||
| -rw-r--r-- | indra/llxml/llcontrol.h | 210 | 
2 files changed, 698 insertions, 328 deletions
| diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp index 9de426fc03..4ad44f455f 100644 --- a/indra/llxml/llcontrol.cpp +++ b/indra/llxml/llcontrol.cpp @@ -57,9 +57,19 @@  #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 LLControlVariable::llsd_compare(const LLSD& a, const LLSD & b) +BOOL LLControl::llsd_compare(const LLSD& a, const LLSD & b)  {  	switch (mType)  	{ @@ -91,154 +101,58 @@ BOOL LLControlVariable::llsd_compare(const LLSD& a, const LLSD & b)  	return FALSE;  } -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);  -    } -} - -void LLControlVariable::resetToDefault(bool fire_signal) +LLControlBase::~LLControlBase()  { -	//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]));  } -LLSD LLControlVariable::getSaveValue() const +// virtual +void LLControlBase::resetToDefault()  { -	//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];  } -LLControlVariable*	LLControlGroup::getControl(const LLString& name) +LLControlGroup::LLControlGroup():	mNameTable()  { -	ctrl_name_table_t::iterator iter = mNameTable.find(name); -	return iter == mNameTable.end() ? NULL : iter->second; +	//mFreeStringOffset = 0;  } - -//////////////////////////////////////////////////////////////////////////// - -LLControlGroup::LLControlGroup() +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";  } -LLControlGroup::~LLControlGroup() +LLSD LLControlBase::registerListener(LLSimpleListenerObservable *listener, LLSD userdata)  { -	cleanup(); +	// Symmetric listener relationship +	addListener(listener, "", userdata); +	listener->addListener(this, "", userdata); +	return getValue();  }  void LLControlGroup::cleanup()  { -	for_each(mNameTable.begin(), mNameTable.end(), DeletePairedPointer());  	mNameTable.clear();  } -eControlType LLControlGroup::typeStringToEnum(const LLString& typestr) -{ -	for(int i = 0; i < (int)TYPE_COUNT; ++i) -	{ -		if(mTypeString[i] == typestr) return (eControlType)i; -	} -	return (eControlType)-1; -} - -LLString LLControlGroup::typeEnumToString(eControlType typeenum) +LLControlBase*	LLControlGroup::getControl(const LLString& name)  { -	return mTypeString[typeenum]; +	ctrl_name_table_t::iterator iter = mNameTable.find(name); +	return iter == mNameTable.end() ? NULL : (LLControlBase*)iter->second;  }  BOOL LLControlGroup::declareControl(const LLString& name, eControlType type, const LLSD initial_val, const LLString& comment, BOOL persist)  { -	if(mNameTable.find(name) != mNameTable.end()) +	if(!mNameTable[name])  	{ -		llwarns << "LLControlGroup::declareControl: Control named " << name << " already exists." << llendl; -		mNameTable[name]->setValue(initial_val); +		// 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;  	} -	// 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; +	else +	{ +		llwarns << "LLControlGroup::declareControl: Control named " << name << " already exists." << llendl; +		mNameTable.erase(name); +		return FALSE; +	}  }  BOOL LLControlGroup::declareU32(const LLString& name, const U32 initial_val, const LLString& comment, BOOL persist) @@ -296,14 +210,19 @@ BOOL LLControlGroup::declareColor3(const LLString& name, const LLColor3 &initial  	return declareControl(name, TYPE_COL3, initial_val.getValue(), comment, persist);  } -BOOL LLControlGroup::declareLLSD(const LLString& name, const LLSD &initial_val, const LLString& comment, BOOL persist ) +LLSD LLControlGroup::registerListener(const LLString& name, LLSimpleListenerObservable *listener)  { -	return declareControl(name, TYPE_LLSD, initial_val, comment, persist); +	LLControlBase *control = getControl(name); +	if (control) +	{ +		return control->registerListener(listener); +	} +	return LLSD();  }  BOOL LLControlGroup::getBOOL(const LLString& name)  { -	LLControlVariable* control = getControl(name); +	LLControlBase* control = getControl(name);  	if (control && control->isType(TYPE_BOOLEAN))  		return control->get().asBoolean(); @@ -316,7 +235,7 @@ BOOL LLControlGroup::getBOOL(const LLString& name)  S32 LLControlGroup::getS32(const LLString& name)  { -	LLControlVariable* control = getControl(name); +	LLControlBase* control = getControl(name);  	if (control && control->isType(TYPE_S32))  		return control->get().asInteger(); @@ -329,7 +248,7 @@ S32 LLControlGroup::getS32(const LLString& name)  U32 LLControlGroup::getU32(const LLString& name)  { -	LLControlVariable* control = getControl(name); +	LLControlBase* control = getControl(name);  	if (control && control->isType(TYPE_U32))		  		return control->get().asInteger(); @@ -342,7 +261,7 @@ U32 LLControlGroup::getU32(const LLString& name)  F32 LLControlGroup::getF32(const LLString& name)  { -	LLControlVariable* control = getControl(name); +	LLControlBase* control = getControl(name);  	if (control && control->isType(TYPE_F32))  		return (F32) control->get().asReal(); @@ -355,7 +274,7 @@ F32 LLControlGroup::getF32(const LLString& name)  LLString LLControlGroup::findString(const LLString& name)  { -	LLControlVariable* control = getControl(name); +	LLControlBase* control = getControl(name);  	if (control && control->isType(TYPE_STRING))  		return control->get().asString(); @@ -364,7 +283,7 @@ LLString LLControlGroup::findString(const LLString& name)  LLString LLControlGroup::getString(const LLString& name)  { -	LLControlVariable* control = getControl(name); +	LLControlBase* control = getControl(name);  	if (control && control->isType(TYPE_STRING))  		return control->get().asString(); @@ -390,7 +309,7 @@ LLString LLControlGroup::getText(const LLString& name)  LLVector3 LLControlGroup::getVector3(const LLString& name)  { -	LLControlVariable* control = getControl(name); +	LLControlBase* control = getControl(name);  	if (control && control->isType(TYPE_VEC3))  		return control->get(); @@ -403,7 +322,7 @@ LLVector3 LLControlGroup::getVector3(const LLString& name)  LLVector3d LLControlGroup::getVector3d(const LLString& name)  { -	LLControlVariable* control = getControl(name); +	LLControlBase* control = getControl(name);  	if (control && control->isType(TYPE_VEC3D))  		return control->get(); @@ -416,7 +335,7 @@ LLVector3d LLControlGroup::getVector3d(const LLString& name)  LLRect LLControlGroup::getRect(const LLString& name)  { -	LLControlVariable* control = getControl(name); +	LLControlBase* control = getControl(name);  	if (control && control->isType(TYPE_RECT))  		return control->get(); @@ -434,7 +353,7 @@ LLColor4 LLControlGroup::getColor(const LLString& name)  	if (i != mNameTable.end())  	{ -		LLControlVariable* control = i->second; +		LLControlBase* control = i->second;  		switch(control->mType)  		{ @@ -462,7 +381,7 @@ LLColor4 LLControlGroup::getColor(const LLString& name)  LLColor4U LLControlGroup::getColor4U(const LLString& name)  { -	LLControlVariable* control = getControl(name); +	LLControlBase* control = getControl(name);  	if (control && control->isType(TYPE_COL4U))  		return control->get(); @@ -475,7 +394,7 @@ LLColor4U LLControlGroup::getColor4U(const LLString& name)  LLColor4 LLControlGroup::getColor4(const LLString& name)  { -	LLControlVariable* control = getControl(name); +	LLControlBase* control = getControl(name);  	if (control && control->isType(TYPE_COL4))  		return control->get(); @@ -488,7 +407,7 @@ LLColor4 LLControlGroup::getColor4(const LLString& name)  LLColor3 LLControlGroup::getColor3(const LLString& name)  { -	LLControlVariable* control = getControl(name); +	LLControlBase* control = getControl(name);  	if (control && control->isType(TYPE_COL3))  		return control->get(); @@ -499,16 +418,6 @@ 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); @@ -521,7 +430,7 @@ BOOL LLControlGroup::controlExists(const LLString& name)  void LLControlGroup::setBOOL(const LLString& name, BOOL val)  { -	LLControlVariable* control = getControl(name); +	LLControlBase* control = getControl(name);  	if (control && control->isType(TYPE_BOOLEAN))  	{ @@ -536,7 +445,7 @@ void LLControlGroup::setBOOL(const LLString& name, BOOL val)  void LLControlGroup::setS32(const LLString& name, S32 val)  { -	LLControlVariable* control = getControl(name); +	LLControlBase* control = getControl(name);  	if (control && control->isType(TYPE_S32))  	{ @@ -551,7 +460,7 @@ void LLControlGroup::setS32(const LLString& name, S32 val)  void LLControlGroup::setF32(const LLString& name, F32 val)  { -	LLControlVariable* control = getControl(name); +	LLControlBase* control = getControl(name);  	if (control && control->isType(TYPE_F32))  	{ @@ -566,7 +475,7 @@ void LLControlGroup::setF32(const LLString& name, F32 val)  void LLControlGroup::setU32(const LLString& name, U32 val)  { -	LLControlVariable* control = getControl(name); +	LLControlBase* control = getControl(name);  	if (control && control->isType(TYPE_U32))  	{ @@ -581,7 +490,7 @@ void LLControlGroup::setU32(const LLString& name, U32 val)  void LLControlGroup::setString(const LLString& name, const LLString &val)  { -	LLControlVariable* control = getControl(name); +	LLControlBase* control = getControl(name);  	if (control && control->isType(TYPE_STRING))  	{ @@ -596,7 +505,7 @@ void LLControlGroup::setString(const LLString& name, const LLString &val)  void LLControlGroup::setVector3(const LLString& name, const LLVector3 &val)  { -	LLControlVariable* control = getControl(name); +	LLControlBase* control = getControl(name);  	if (control && control->isType(TYPE_VEC3))  	{ @@ -610,7 +519,7 @@ void LLControlGroup::setVector3(const LLString& name, const LLVector3 &val)  void LLControlGroup::setVector3d(const LLString& name, const LLVector3d &val)  { -	LLControlVariable* control = getControl(name); +	LLControlBase* control = getControl(name);  	if (control && control->isType(TYPE_VEC3D))  	{ @@ -624,7 +533,7 @@ void LLControlGroup::setVector3d(const LLString& name, const LLVector3d &val)  void LLControlGroup::setRect(const LLString& name, const LLRect &val)  { -	LLControlVariable* control = getControl(name); +	LLControlBase* control = getControl(name);  	if (control && control->isType(TYPE_RECT))  	{ @@ -638,7 +547,7 @@ void LLControlGroup::setRect(const LLString& name, const LLRect &val)  void LLControlGroup::setColor4U(const LLString& name, const LLColor4U &val)  { -	LLControlVariable* control = getControl(name); +	LLControlBase* control = getControl(name);  	if (control && control->isType(TYPE_COL4U))  	{ @@ -652,7 +561,7 @@ void LLControlGroup::setColor4U(const LLString& name, const LLColor4U &val)  void LLControlGroup::setColor4(const LLString& name, const LLColor4 &val)  { -	LLControlVariable* control = getControl(name); +	LLControlBase* control = getControl(name);  	if (control && control->isType(TYPE_COL4))  	{ @@ -664,20 +573,6 @@ 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()) @@ -685,7 +580,7 @@ void LLControlGroup::setValue(const LLString& name, const LLSD& val)  		return;  	} -	LLControlVariable* control = getControl(name); +	LLControlBase* control = getControl(name);  	if (control)  	{ @@ -701,9 +596,239 @@ void LLControlGroup::setValue(const LLString& name, const LLSD& val)  // Load and save  //--------------------------------------------------------------- -// Returns number of controls loaded, so 0 if failure  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) +{  	LLString name;  	LLXmlTree xml_controls; @@ -776,9 +901,11 @@ U32 LLControlGroup::loadFromFileLegacy(const LLString& filename, BOOL require_de  		}  		// Control name has been declared in code. -		LLControlVariable *control = getControl(name); +		LLControlBase *control = getControl(name);  		llassert(control); + +		mLoadedSettings.insert(name);  		switch(control->mType)  		{ @@ -892,43 +1019,59 @@ U32 LLControlGroup::loadFromFileLegacy(const LLString& filename, BOOL require_de  				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)  { -	LLSD settings; -	int num_saved = 0; +	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; +  	for (ctrl_name_table_t::iterator iter = mNameTable.begin();  		 iter != mNameTable.end(); iter++)  	{ -		LLControlVariable* control = iter->second; +		LLString name = iter->first; +		if (name.empty()) +		{ +			CONTROL_ERRS << "Control with no name found!!!" << llendl; +			break; +		} + +		LLControlBase* control = (LLControlBase *)iter->second;  		if (!control)  		{ -			llwarns << "Tried to save invalid control: " << iter->first << llendl; +			llwarns << "Tried to save invalid control: " << name << llendl;  		} -		if( control && control->isPersisted() ) +		if( control && control->mPersist )  		{ -			if (!(nondefault_only && (control->isSaveValueDefault()))) +			if (!(nondefault_only && (control->mIsDefault)))  			{ -				settings[iter->first]["Type"] = typeEnumToString(control->type()); -				settings[iter->first]["Comment"] = control->getComment(); -				settings[iter->first]["Value"] = control->getSaveValue(); -				++num_saved; +				controls.insert( control );  			}  			else  			{ @@ -937,58 +1080,156 @@ U32 LLControlGroup::saveToFile(const LLString& filename, BOOL nondefault_only)  			}  		}  	} +  	llofstream file; -	file.open(filename.c_str()); -	if (file.is_open()) -	{ -		LLSDSerialize::toPrettyXML(settings, file); -		file.close(); -		llinfos << "Saved to " << filename << llendl; -	} -	else -	{ -        // 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; -} +	file.open(filename.c_str());		/*Flawfinder: ignore*/ -U32 LLControlGroup::loadFromFile(const LLString& filename, BOOL require_declaration, eControlType declare_as) -{ -	LLString name; -	LLSD settings; -	LLSD control_map; -	llifstream infile; -	infile.open(filename.c_str()); -	if(!infile.is_open()) +	if (!file.is_open())  	{ -		llwarns << "Cannot find file " << filename << " to load." << llendl; +		// 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;  	} -	S32 ret = LLSDSerialize::fromXML(settings, infile); -	if (ret <= 0) + +	// 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)  	{ -		infile.close(); -		llwarns << "Unable to open LLSD control file " << filename << ". Trying Legacy Method." << llendl;		 -		return loadFromFileLegacy(filename, require_declaration, declare_as); -	} +		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; +			} +		} -	U32		validitems = 0; -	int persist = 1; -	for(LLSD::map_const_iterator itr = settings.beginMap(); itr != settings.endMap(); ++itr) +		// Debug spam +		// llinfos << name << " " << control->getValue().asString() << llendl; +	}// next + +	file << "</settings>\n"; +	file.close(); + +	return controls.size(); +} + +void LLControlGroup::applyOverrides(const std::map<std::string, std::string>& overrides) +{ +	for (std::map<std::string, std::string>::const_iterator iter = overrides.begin(); +		 iter != overrides.end(); ++iter)  	{ -		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; +		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; +		}  	} - -	return validitems;  }  void LLControlGroup::resetToDefaults() @@ -998,20 +1239,11 @@ void LLControlGroup::resetToDefaults()  		control_iter != mNameTable.end();  		++control_iter)  	{ -		LLControlVariable* control = (*control_iter).second; +		LLControlBase* 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 @@ -1032,7 +1264,7 @@ static LLString get_warn_name(const LLString& name)  void LLControlGroup::addWarning(const LLString& name)  {  	LLString warnname = get_warn_name(name); -	if(mNameTable.find(warnname) == mNameTable.end()) +	if(!mNameTable[warnname])  	{  		LLString comment = LLString("Enables ") + name + LLString(" warning dialog");  		declareBOOL(warnname, TRUE, comment); @@ -1061,6 +1293,91 @@ 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 @@ -1076,17 +1393,17 @@ void main()  	llinfos << "Loaded " << count << " controls" << llendl;  	// test insertion -	foo = new LLControlVariable<F32>("gFoo", 5.f, 1.f, 20.f); +	foo = new LLControl<F32>("gFoo", 5.f, 1.f, 20.f);  	gGlobals.addEntry("gFoo", foo); -	bar = new LLControlVariable<S32>("gBar", 10, 2, 22); +	bar = new LLControl<S32>("gBar", 10, 2, 22);  	gGlobals.addEntry("gBar", bar); -	baz = new LLControlVariable<BOOL>("gBaz", FALSE); +	baz = new LLControl<BOOL>("gBaz", FALSE);  	gGlobals.addEntry("gBaz", baz);  	// test retrieval -	getfoo = (LLControlVariable<F32>*) gGlobals.resolveName("gFoo"); +	getfoo = (LLControl<F32>*) gGlobals.resolveName("gFoo");  	getfoo->dump();  	getbar = (S32_CONTROL) gGlobals.resolveName("gBar"); @@ -1099,10 +1416,10 @@ void main()  	// Failure modes  	// ...min > max -	// badfoo = new LLControlVariable<F32>("gFoo2", 100.f, 20.f, 5.f); +	// badfoo = new LLControl<F32>("gFoo2", 100.f, 20.f, 5.f);  	// ...initial > max -	// badbar = new LLControlVariable<S32>("gBar2", 10, 20, 100000); +	// badbar = new LLControl<S32>("gBar2", 10, 20, 100000);  	// ...misspelled name  	// getfoo = (F32_CONTROL) gGlobals.resolveName("fooMisspelled"); @@ -1124,4 +1441,3 @@ void main()  }  #endif - diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h index 7a638a7b73..a1a2a4c851 100644 --- a/indra/llxml/llcontrol.h +++ b/indra/llxml/llcontrol.h @@ -38,26 +38,6 @@  #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; @@ -68,7 +48,7 @@ const BOOL NO_PERSIST = FALSE;  typedef enum e_control_type  { -	TYPE_U32 = 0, +	TYPE_U32,  	TYPE_S32,  	TYPE_F32,  	TYPE_BOOLEAN, @@ -78,82 +58,159 @@ typedef enum e_control_type  	TYPE_RECT,  	TYPE_COL4,  	TYPE_COL3, -	TYPE_COL4U, -	TYPE_LLSD, -	TYPE_COUNT +	TYPE_COL4U  } eControlType; -class LLControlVariable +class LLControlBase : public LLSimpleListenerObservable  { -	friend class LLControlGroup; -	typedef boost::signal<void(const LLSD&)> signal_t; - -private: +friend class LLControlGroup; +protected:  	LLString		mName;  	LLString		mComment;  	eControlType	mType; +	BOOL			mHasRange;  	BOOL			mPersist; -	std::vector<LLSD> mValues; -	 -	signal_t mSignal; -	 +	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. +  public: -	LLControlVariable(const LLString& name, eControlType type, -					  LLSD initial, const LLString& comment, -					  BOOL persist = TRUE); +	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(); -	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; } - -	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() +	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()  	{ -		mSignal(mValues.back()); +		//Remove and deregister all listeners.. +		while(mListenerIDs.size()) +		{ +			S32	id = mListenerIDs.front(); +			mListenerIDs.pop_front(); +			releaseListenerID(id); +		}  	} -	BOOL llsd_compare(const LLSD& a, const LLSD& b);  };  //const U32 STRING_CACHE_SIZE = 10000;  class LLControlGroup  { -protected: -	typedef std::map<LLString, LLControlVariable* > ctrl_name_table_t; +public: +	typedef std::map<LLString, LLPointer<LLControlBase> > ctrl_name_table_t;  	ctrl_name_table_t mNameTable;  	std::set<LLString> mWarnings; -	LLString mTypeString[TYPE_COUNT]; +	std::set<LLString> mLoadedSettings;	// Filled in with names loaded from settings.xml -	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 -	LLControlVariable*	getControl(const LLString& name); - -	struct ApplyFunctor -	{ -		virtual ~ApplyFunctor() {}; -		virtual void apply(const LLString& name, LLControlVariable* control) = 0; -	}; -	void applyToAll(ApplyFunctor* func); +	LLControlBase*	getControl(const LLString& name); +	LLSD registerListener(const LLString& name, LLSimpleListenerObservable *listener);  	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); @@ -167,7 +224,6 @@ 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); @@ -181,7 +237,7 @@ public:  	S32			getS32(const LLString& name);  	F32			getF32(const LLString& name);  	U32			getU32(const LLString& name); -	LLSD        getLLSD(const LLString& name); +	LLSD		getValue(const LLString& name);  	// Note: If an LLColor4U control exists, it will cast it to the correct @@ -202,21 +258,19 @@ 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 saveToFile(const LLString& filename, BOOL nondefault_only); - 	U32	loadFromFile(const LLString& filename, BOOL require_declaration = TRUE, eControlType declare_as = TYPE_STRING); +	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);  	void	resetToDefaults(); -	  	// Ignorable Warnings  	// Add a config variable to be reset on resetWarnings() | 
