PageRenderTime 47ms CodeModel.GetById 16ms app.highlight 26ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llxml/llcontrol.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 458 lines | 343 code | 69 blank | 46 comment | 15 complexity | 982eb1dd220e40ade092b8333b717edc MD5 | raw file
  1/** 
  2 * @file llcontrol.h
  3 * @brief A mechanism for storing "control state" for a program
  4 *
  5 * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6 * Second Life Viewer Source Code
  7 * Copyright (C) 2010, Linden Research, Inc.
  8 * 
  9 * This library is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU Lesser General Public
 11 * License as published by the Free Software Foundation;
 12 * version 2.1 of the License only.
 13 * 
 14 * This library is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17 * Lesser General Public License for more details.
 18 * 
 19 * You should have received a copy of the GNU Lesser General Public
 20 * License along with this library; if not, write to the Free Software
 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 22 * 
 23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 24 * $/LicenseInfo$
 25 */
 26
 27#ifndef LL_LLCONTROL_H
 28#define LL_LLCONTROL_H
 29
 30#include "llboost.h"
 31#include "llevent.h"
 32#include "llnametable.h"
 33#include "llmap.h"
 34#include "llstring.h"
 35#include "llrect.h"
 36#include "llrefcount.h"
 37#include "llinstancetracker.h"
 38
 39#include "llcontrolgroupreader.h"
 40
 41#include <vector>
 42
 43// *NOTE: boost::visit_each<> generates warning 4675 on .net 2003
 44// Disable the warning for the boost includes.
 45#if LL_WINDOWS
 46# if (_MSC_VER >= 1300 && _MSC_VER < 1400)
 47#   pragma warning(push)
 48#   pragma warning( disable : 4675 )
 49# endif
 50#endif
 51
 52#include <boost/bind.hpp>
 53
 54#if LL_WINDOWS
 55	#pragma warning (push)
 56	#pragma warning (disable : 4263) // boost::signals2::expired_slot::what() has const mismatch
 57	#pragma warning (disable : 4264) 
 58#endif
 59#include <boost/signals2.hpp>
 60#if LL_WINDOWS
 61	#pragma warning (pop)
 62#endif
 63
 64#if LL_WINDOWS
 65# if (_MSC_VER >= 1300 && _MSC_VER < 1400)
 66#   pragma warning(pop)
 67# endif
 68#endif
 69
 70class LLVector3;
 71class LLVector3d;
 72class LLColor4;
 73class LLColor3;
 74
 75const BOOL NO_PERSIST = FALSE;
 76
 77typedef enum e_control_type
 78{
 79	TYPE_U32 = 0,
 80	TYPE_S32,
 81	TYPE_F32,
 82	TYPE_BOOLEAN,
 83	TYPE_STRING,
 84	TYPE_VEC3,
 85	TYPE_VEC3D,
 86	TYPE_RECT,
 87	TYPE_COL4,
 88	TYPE_COL3,
 89	TYPE_LLSD,
 90	TYPE_COUNT
 91} eControlType;
 92
 93class LLControlVariable : public LLRefCount
 94{
 95	friend class LLControlGroup;
 96	
 97public:
 98	typedef boost::signals2::signal<bool(LLControlVariable* control, const LLSD&), boost_boolean_combiner> validate_signal_t;
 99	typedef boost::signals2::signal<void(LLControlVariable* control, const LLSD&)> commit_signal_t;
100
101private:
102	std::string		mName;
103	std::string		mComment;
104	eControlType	mType;
105	bool			mPersist;
106	bool			mHideFromSettingsEditor;
107	std::vector<LLSD> mValues;
108	
109	commit_signal_t mCommitSignal;
110	validate_signal_t mValidateSignal;
111	
112public:
113	LLControlVariable(const std::string& name, eControlType type,
114					  LLSD initial, const std::string& comment,
115					  bool persist = true, bool hidefromsettingseditor = false);
116
117	virtual ~LLControlVariable();
118	
119	const std::string& getName() const { return mName; }
120	const std::string& getComment() const { return mComment; }
121
122	eControlType type()		{ return mType; }
123	bool isType(eControlType tp) { return tp == mType; }
124
125	void resetToDefault(bool fire_signal = false);
126
127	commit_signal_t* getSignal() { return &mCommitSignal; } // shorthand for commit signal
128	commit_signal_t* getCommitSignal() { return &mCommitSignal; }
129	validate_signal_t* getValidateSignal() { return &mValidateSignal; }
130
131	bool isDefault() { return (mValues.size() == 1); }
132	bool isSaveValueDefault();
133	bool isPersisted() { return mPersist; }
134	bool isHiddenFromSettingsEditor() { return mHideFromSettingsEditor; }
135	LLSD get()			const	{ return getValue(); }
136	LLSD getValue()		const	{ return mValues.back(); }
137	LLSD getDefault()	const	{ return mValues.front(); }
138	LLSD getSaveValue() const;
139
140	void set(const LLSD& val)	{ setValue(val); }
141	void setValue(const LLSD& value, bool saved_value = TRUE);
142	void setDefaultValue(const LLSD& value);
143	void setPersist(bool state);
144	void setHiddenFromSettingsEditor(bool hide);
145	void setComment(const std::string& comment);
146
147	void firePropertyChanged()
148	{
149		mCommitSignal(this, mValues.back());
150	}
151private:
152	LLSD getComparableValue(const LLSD& value);
153	bool llsd_compare(const LLSD& a, const LLSD & b);
154};
155
156typedef LLPointer<LLControlVariable> LLControlVariablePtr;
157
158//! Helper functions for converting between static types and LLControl values
159template <class T> 
160eControlType get_control_type()
161{
162	llwarns << "Usupported control type: " << typeid(T).name() << "." << llendl;
163	return TYPE_COUNT;
164}
165
166template <class T> 
167LLSD convert_to_llsd(const T& in)
168{
169	// default implementation
170	return LLSD(in);
171}
172
173template <class T>
174T convert_from_llsd(const LLSD& sd, eControlType type, const std::string& control_name)
175{
176	// needs specialization
177	return T(sd);
178}
179
180//const U32 STRING_CACHE_SIZE = 10000;
181class LLControlGroup : public LLInstanceTracker<LLControlGroup, std::string>
182{
183protected:
184	typedef std::map<std::string, LLControlVariablePtr > ctrl_name_table_t;
185	ctrl_name_table_t mNameTable;
186	std::string mTypeString[TYPE_COUNT];
187
188public:
189	eControlType typeStringToEnum(const std::string& typestr);
190	std::string typeEnumToString(eControlType typeenum);	
191
192	LLControlGroup(const std::string& name);
193	~LLControlGroup();
194	void cleanup();
195	
196	typedef LLInstanceTracker<LLControlGroup, std::string>::instance_iter instance_iter;
197
198	LLControlVariablePtr getControl(const std::string& name);
199
200	struct ApplyFunctor
201	{
202		virtual ~ApplyFunctor() {};
203		virtual void apply(const std::string& name, LLControlVariable* control) = 0;
204	};
205	void applyToAll(ApplyFunctor* func);
206	
207	BOOL declareControl(const std::string& name, eControlType type, const LLSD initial_val, const std::string& comment, BOOL persist, BOOL hidefromsettingseditor = FALSE);
208	BOOL declareU32(const std::string& name, U32 initial_val, const std::string& comment, BOOL persist = TRUE);
209	BOOL declareS32(const std::string& name, S32 initial_val, const std::string& comment, BOOL persist = TRUE);
210	BOOL declareF32(const std::string& name, F32 initial_val, const std::string& comment, BOOL persist = TRUE);
211	BOOL declareBOOL(const std::string& name, BOOL initial_val, const std::string& comment, BOOL persist = TRUE);
212	BOOL declareString(const std::string& name, const std::string &initial_val, const std::string& comment, BOOL persist = TRUE);
213	BOOL declareVec3(const std::string& name, const LLVector3 &initial_val,const std::string& comment,  BOOL persist = TRUE);
214	BOOL declareVec3d(const std::string& name, const LLVector3d &initial_val, const std::string& comment, BOOL persist = TRUE);
215	BOOL declareRect(const std::string& name, const LLRect &initial_val, const std::string& comment, BOOL persist = TRUE);
216	BOOL declareColor4(const std::string& name, const LLColor4 &initial_val, const std::string& comment, BOOL persist = TRUE);
217	BOOL declareColor3(const std::string& name, const LLColor3 &initial_val, const std::string& comment, BOOL persist = TRUE);
218	BOOL declareLLSD(const std::string& name, const LLSD &initial_val, const std::string& comment, BOOL persist = TRUE);
219
220	std::string getString(const std::string& name);
221	std::string getText(const std::string& name);
222	BOOL		getBOOL(const std::string& name);
223	S32			getS32(const std::string& name);
224	F32			getF32(const std::string& name);
225	U32			getU32(const std::string& name);
226	
227	LLWString	getWString(const std::string& name);
228	LLVector3	getVector3(const std::string& name);
229	LLVector3d	getVector3d(const std::string& name);
230	LLRect		getRect(const std::string& name);
231	LLSD        getLLSD(const std::string& name);
232
233
234	LLColor4	getColor(const std::string& name);
235	LLColor4	getColor4(const std::string& name);
236	LLColor3	getColor3(const std::string& name);
237
238	// generic getter
239	template<typename T> T get(const std::string& name)
240	{
241		LLControlVariable* control = getControl(name);
242		LLSD value;
243		eControlType type = TYPE_COUNT;
244
245		if (control)		
246		{
247			value = control->get();
248			type = control->type();
249		}
250		else
251		{
252			llwarns << "Control " << name << " not found." << llendl;
253		}
254		return convert_from_llsd<T>(value, type, name);
255	}
256
257	void	setBOOL(const std::string& name, BOOL val);
258	void	setS32(const std::string& name, S32 val);
259	void	setF32(const std::string& name, F32 val);
260	void	setU32(const std::string& name, U32 val);
261	void	setString(const std::string&  name, const std::string& val);
262	void	setVector3(const std::string& name, const LLVector3 &val);
263	void	setVector3d(const std::string& name, const LLVector3d &val);
264	void	setRect(const std::string& name, const LLRect &val);
265	void	setColor4(const std::string& name, const LLColor4 &val);
266	void    setLLSD(const std::string& name, const LLSD& val);
267
268	// type agnostic setter that takes LLSD
269	void	setUntypedValue(const std::string& name, const LLSD& val);
270
271	// generic setter
272	template<typename T> void set(const std::string& name, const T& val)
273	{
274		LLControlVariable* control = getControl(name);
275	
276		if (control && control->isType(get_control_type<T>()))
277		{
278			control->set(convert_to_llsd(val));
279		}
280		else
281		{
282			llwarns << "Invalid control " << name << llendl;
283		}
284	}
285	
286	BOOL    controlExists(const std::string& name);
287
288	// Returns number of controls loaded, 0 if failed
289	// If require_declaration is false, will auto-declare controls it finds
290	// as the given type.
291	U32	loadFromFileLegacy(const std::string& filename, BOOL require_declaration = TRUE, eControlType declare_as = TYPE_STRING);
292 	U32 saveToFile(const std::string& filename, BOOL nondefault_only);
293 	U32	loadFromFile(const std::string& filename, bool default_values = false, bool save_values = true);
294	void	resetToDefaults();
295};
296
297
298//! Publish/Subscribe object to interact with LLControlGroups.
299
300//! Use an LLCachedControl instance to connect to a LLControlVariable
301//! without have to manually create and bind a listener to a local
302//! object.
303template <class T>
304class LLControlCache : public LLRefCount, public LLInstanceTracker<LLControlCache<T>, std::string>
305{
306public:
307	// This constructor will declare a control if it doesn't exist in the contol group
308	LLControlCache(LLControlGroup& group,
309					const std::string& name, 
310					const T& default_value, 
311					const std::string& comment)
312	:	LLInstanceTracker<LLControlCache<T>, std::string >(name)
313	{
314		if(!group.controlExists(name))
315		{
316			if(!declareTypedControl(group, name, default_value, comment))
317			{
318				llerrs << "The control could not be created!!!" << llendl;
319			}
320		}
321
322		bindToControl(group, name);
323	}
324
325	LLControlCache(LLControlGroup& group,
326					const std::string& name)
327	:	LLInstanceTracker<LLControlCache<T>, std::string >(name)
328	{
329		if(!group.controlExists(name))
330		{
331			llerrs << "Control named " << name << "not found." << llendl;
332		}
333
334		bindToControl(group, name);
335	}
336
337	~LLControlCache()
338	{
339	}
340
341	const T& getValue() const { return mCachedValue; }
342	
343private:
344	void bindToControl(LLControlGroup& group, const std::string& name)
345	{
346		LLControlVariablePtr controlp = group.getControl(name);
347		mType = controlp->type();
348		mCachedValue = convert_from_llsd<T>(controlp->get(), mType, name);
349
350		// Add a listener to the controls signal...
351		mConnection = controlp->getSignal()->connect(
352			boost::bind(&LLControlCache<T>::handleValueChange, this, _2)
353			);
354		mType = controlp->type();
355	}
356	bool declareTypedControl(LLControlGroup& group,
357							const std::string& name, 
358							 const T& default_value,
359							 const std::string& comment)
360	{
361		LLSD init_value;
362		eControlType type = get_control_type<T>();
363		init_value = convert_to_llsd(default_value);
364		if(type < TYPE_COUNT)
365		{
366			group.declareControl(name, type, init_value, comment, FALSE);
367			return true;
368		}
369		return false;
370	}
371
372	bool handleValueChange(const LLSD& newvalue)
373	{
374		mCachedValue = convert_from_llsd<T>(newvalue, mType, "");
375		return true;
376	}
377
378private:
379    T							mCachedValue;
380	eControlType				mType;
381    boost::signals2::scoped_connection	mConnection;
382};
383
384template <typename T>
385class LLCachedControl
386{
387public:
388	LLCachedControl(LLControlGroup& group,
389					const std::string& name,
390
391					const T& default_value, 
392					const std::string& comment = "Declared In Code")
393	{
394		mCachedControlPtr = LLControlCache<T>::getInstance(name);
395		if (mCachedControlPtr.isNull())
396		{
397			mCachedControlPtr = new LLControlCache<T>(group, name, default_value, comment);
398		}
399	}
400
401	LLCachedControl(LLControlGroup& group,
402					const std::string& name)
403	{
404		mCachedControlPtr = LLControlCache<T>::getInstance(name);
405		if (mCachedControlPtr.isNull())
406		{
407			mCachedControlPtr = new LLControlCache<T>(group, name);
408		}
409	}
410
411	operator const T&() const { return mCachedControlPtr->getValue(); }
412	operator boost::function<const T&()> () const { return boost::function<const T&()>(*this); }
413	const T& operator()() { return mCachedControlPtr->getValue(); }
414
415private:
416	LLPointer<LLControlCache<T> > mCachedControlPtr;
417};
418
419template <> eControlType get_control_type<U32>();
420template <> eControlType get_control_type<S32>();
421template <> eControlType get_control_type<F32>();
422template <> eControlType get_control_type<bool>(); 
423// Yay BOOL, its really an S32.
424//template <> eControlType get_control_type<BOOL> () 
425template <> eControlType get_control_type<std::string>();
426template <> eControlType get_control_type<LLVector3>();
427template <> eControlType get_control_type<LLVector3d>(); 
428template <> eControlType get_control_type<LLRect>();
429template <> eControlType get_control_type<LLColor4>();
430template <> eControlType get_control_type<LLColor3>();
431template <> eControlType get_control_type<LLSD>();
432
433template <> LLSD convert_to_llsd<U32>(const U32& in);
434template <> LLSD convert_to_llsd<LLVector3>(const LLVector3& in);
435template <> LLSD convert_to_llsd<LLVector3d>(const LLVector3d& in); 
436template <> LLSD convert_to_llsd<LLRect>(const LLRect& in);
437template <> LLSD convert_to_llsd<LLColor4>(const LLColor4& in);
438template <> LLSD convert_to_llsd<LLColor3>(const LLColor3& in);
439
440template<> std::string convert_from_llsd<std::string>(const LLSD& sd, eControlType type, const std::string& control_name);
441template<> LLWString convert_from_llsd<LLWString>(const LLSD& sd, eControlType type, const std::string& control_name);
442template<> LLVector3 convert_from_llsd<LLVector3>(const LLSD& sd, eControlType type, const std::string& control_name);
443template<> LLVector3d convert_from_llsd<LLVector3d>(const LLSD& sd, eControlType type, const std::string& control_name);
444template<> LLRect convert_from_llsd<LLRect>(const LLSD& sd, eControlType type, const std::string& control_name);
445template<> bool convert_from_llsd<bool>(const LLSD& sd, eControlType type, const std::string& control_name);
446template<> S32 convert_from_llsd<S32>(const LLSD& sd, eControlType type, const std::string& control_name);
447template<> F32 convert_from_llsd<F32>(const LLSD& sd, eControlType type, const std::string& control_name);
448template<> U32 convert_from_llsd<U32>(const LLSD& sd, eControlType type, const std::string& control_name);
449template<> LLColor3 convert_from_llsd<LLColor3>(const LLSD& sd, eControlType type, const std::string& control_name);
450template<> LLColor4 convert_from_llsd<LLColor4>(const LLSD& sd, eControlType type, const std::string& control_name);
451template<> LLSD convert_from_llsd<LLSD>(const LLSD& sd, eControlType type, const std::string& control_name);
452
453//#define TEST_CACHED_CONTROL 1
454#ifdef TEST_CACHED_CONTROL
455void test_cached_control();
456#endif // TEST_CACHED_CONTROL
457
458#endif