PageRenderTime 48ms CodeModel.GetById 18ms RepoModel.GetById 0ms 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
Possible License(s): LGPL-2.1
  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. #ifndef LL_LLCONTROL_H
  27. #define LL_LLCONTROL_H
  28. #include "llboost.h"
  29. #include "llevent.h"
  30. #include "llnametable.h"
  31. #include "llmap.h"
  32. #include "llstring.h"
  33. #include "llrect.h"
  34. #include "llrefcount.h"
  35. #include "llinstancetracker.h"
  36. #include "llcontrolgroupreader.h"
  37. #include <vector>
  38. // *NOTE: boost::visit_each<> generates warning 4675 on .net 2003
  39. // Disable the warning for the boost includes.
  40. #if LL_WINDOWS
  41. # if (_MSC_VER >= 1300 && _MSC_VER < 1400)
  42. # pragma warning(push)
  43. # pragma warning( disable : 4675 )
  44. # endif
  45. #endif
  46. #include <boost/bind.hpp>
  47. #if LL_WINDOWS
  48. #pragma warning (push)
  49. #pragma warning (disable : 4263) // boost::signals2::expired_slot::what() has const mismatch
  50. #pragma warning (disable : 4264)
  51. #endif
  52. #include <boost/signals2.hpp>
  53. #if LL_WINDOWS
  54. #pragma warning (pop)
  55. #endif
  56. #if LL_WINDOWS
  57. # if (_MSC_VER >= 1300 && _MSC_VER < 1400)
  58. # pragma warning(pop)
  59. # endif
  60. #endif
  61. class LLVector3;
  62. class LLVector3d;
  63. class LLColor4;
  64. class LLColor3;
  65. const BOOL NO_PERSIST = FALSE;
  66. typedef enum e_control_type
  67. {
  68. TYPE_U32 = 0,
  69. TYPE_S32,
  70. TYPE_F32,
  71. TYPE_BOOLEAN,
  72. TYPE_STRING,
  73. TYPE_VEC3,
  74. TYPE_VEC3D,
  75. TYPE_RECT,
  76. TYPE_COL4,
  77. TYPE_COL3,
  78. TYPE_LLSD,
  79. TYPE_COUNT
  80. } eControlType;
  81. class LLControlVariable : public LLRefCount
  82. {
  83. friend class LLControlGroup;
  84. public:
  85. typedef boost::signals2::signal<bool(LLControlVariable* control, const LLSD&), boost_boolean_combiner> validate_signal_t;
  86. typedef boost::signals2::signal<void(LLControlVariable* control, const LLSD&)> commit_signal_t;
  87. private:
  88. std::string mName;
  89. std::string mComment;
  90. eControlType mType;
  91. bool mPersist;
  92. bool mHideFromSettingsEditor;
  93. std::vector<LLSD> mValues;
  94. commit_signal_t mCommitSignal;
  95. validate_signal_t mValidateSignal;
  96. public:
  97. LLControlVariable(const std::string& name, eControlType type,
  98. LLSD initial, const std::string& comment,
  99. bool persist = true, bool hidefromsettingseditor = false);
  100. virtual ~LLControlVariable();
  101. const std::string& getName() const { return mName; }
  102. const std::string& getComment() const { return mComment; }
  103. eControlType type() { return mType; }
  104. bool isType(eControlType tp) { return tp == mType; }
  105. void resetToDefault(bool fire_signal = false);
  106. commit_signal_t* getSignal() { return &mCommitSignal; } // shorthand for commit signal
  107. commit_signal_t* getCommitSignal() { return &mCommitSignal; }
  108. validate_signal_t* getValidateSignal() { return &mValidateSignal; }
  109. bool isDefault() { return (mValues.size() == 1); }
  110. bool isSaveValueDefault();
  111. bool isPersisted() { return mPersist; }
  112. bool isHiddenFromSettingsEditor() { return mHideFromSettingsEditor; }
  113. LLSD get() const { return getValue(); }
  114. LLSD getValue() const { return mValues.back(); }
  115. LLSD getDefault() const { return mValues.front(); }
  116. LLSD getSaveValue() const;
  117. void set(const LLSD& val) { setValue(val); }
  118. void setValue(const LLSD& value, bool saved_value = TRUE);
  119. void setDefaultValue(const LLSD& value);
  120. void setPersist(bool state);
  121. void setHiddenFromSettingsEditor(bool hide);
  122. void setComment(const std::string& comment);
  123. void firePropertyChanged()
  124. {
  125. mCommitSignal(this, mValues.back());
  126. }
  127. private:
  128. LLSD getComparableValue(const LLSD& value);
  129. bool llsd_compare(const LLSD& a, const LLSD & b);
  130. };
  131. typedef LLPointer<LLControlVariable> LLControlVariablePtr;
  132. //! Helper functions for converting between static types and LLControl values
  133. template <class T>
  134. eControlType get_control_type()
  135. {
  136. llwarns << "Usupported control type: " << typeid(T).name() << "." << llendl;
  137. return TYPE_COUNT;
  138. }
  139. template <class T>
  140. LLSD convert_to_llsd(const T& in)
  141. {
  142. // default implementation
  143. return LLSD(in);
  144. }
  145. template <class T>
  146. T convert_from_llsd(const LLSD& sd, eControlType type, const std::string& control_name)
  147. {
  148. // needs specialization
  149. return T(sd);
  150. }
  151. //const U32 STRING_CACHE_SIZE = 10000;
  152. class LLControlGroup : public LLInstanceTracker<LLControlGroup, std::string>
  153. {
  154. protected:
  155. typedef std::map<std::string, LLControlVariablePtr > ctrl_name_table_t;
  156. ctrl_name_table_t mNameTable;
  157. std::string mTypeString[TYPE_COUNT];
  158. public:
  159. eControlType typeStringToEnum(const std::string& typestr);
  160. std::string typeEnumToString(eControlType typeenum);
  161. LLControlGroup(const std::string& name);
  162. ~LLControlGroup();
  163. void cleanup();
  164. typedef LLInstanceTracker<LLControlGroup, std::string>::instance_iter instance_iter;
  165. LLControlVariablePtr getControl(const std::string& name);
  166. struct ApplyFunctor
  167. {
  168. virtual ~ApplyFunctor() {};
  169. virtual void apply(const std::string& name, LLControlVariable* control) = 0;
  170. };
  171. void applyToAll(ApplyFunctor* func);
  172. BOOL declareControl(const std::string& name, eControlType type, const LLSD initial_val, const std::string& comment, BOOL persist, BOOL hidefromsettingseditor = FALSE);
  173. BOOL declareU32(const std::string& name, U32 initial_val, const std::string& comment, BOOL persist = TRUE);
  174. BOOL declareS32(const std::string& name, S32 initial_val, const std::string& comment, BOOL persist = TRUE);
  175. BOOL declareF32(const std::string& name, F32 initial_val, const std::string& comment, BOOL persist = TRUE);
  176. BOOL declareBOOL(const std::string& name, BOOL initial_val, const std::string& comment, BOOL persist = TRUE);
  177. BOOL declareString(const std::string& name, const std::string &initial_val, const std::string& comment, BOOL persist = TRUE);
  178. BOOL declareVec3(const std::string& name, const LLVector3 &initial_val,const std::string& comment, BOOL persist = TRUE);
  179. BOOL declareVec3d(const std::string& name, const LLVector3d &initial_val, const std::string& comment, BOOL persist = TRUE);
  180. BOOL declareRect(const std::string& name, const LLRect &initial_val, const std::string& comment, BOOL persist = TRUE);
  181. BOOL declareColor4(const std::string& name, const LLColor4 &initial_val, const std::string& comment, BOOL persist = TRUE);
  182. BOOL declareColor3(const std::string& name, const LLColor3 &initial_val, const std::string& comment, BOOL persist = TRUE);
  183. BOOL declareLLSD(const std::string& name, const LLSD &initial_val, const std::string& comment, BOOL persist = TRUE);
  184. std::string getString(const std::string& name);
  185. std::string getText(const std::string& name);
  186. BOOL getBOOL(const std::string& name);
  187. S32 getS32(const std::string& name);
  188. F32 getF32(const std::string& name);
  189. U32 getU32(const std::string& name);
  190. LLWString getWString(const std::string& name);
  191. LLVector3 getVector3(const std::string& name);
  192. LLVector3d getVector3d(const std::string& name);
  193. LLRect getRect(const std::string& name);
  194. LLSD getLLSD(const std::string& name);
  195. LLColor4 getColor(const std::string& name);
  196. LLColor4 getColor4(const std::string& name);
  197. LLColor3 getColor3(const std::string& name);
  198. // generic getter
  199. template<typename T> T get(const std::string& name)
  200. {
  201. LLControlVariable* control = getControl(name);
  202. LLSD value;
  203. eControlType type = TYPE_COUNT;
  204. if (control)
  205. {
  206. value = control->get();
  207. type = control->type();
  208. }
  209. else
  210. {
  211. llwarns << "Control " << name << " not found." << llendl;
  212. }
  213. return convert_from_llsd<T>(value, type, name);
  214. }
  215. void setBOOL(const std::string& name, BOOL val);
  216. void setS32(const std::string& name, S32 val);
  217. void setF32(const std::string& name, F32 val);
  218. void setU32(const std::string& name, U32 val);
  219. void setString(const std::string& name, const std::string& val);
  220. void setVector3(const std::string& name, const LLVector3 &val);
  221. void setVector3d(const std::string& name, const LLVector3d &val);
  222. void setRect(const std::string& name, const LLRect &val);
  223. void setColor4(const std::string& name, const LLColor4 &val);
  224. void setLLSD(const std::string& name, const LLSD& val);
  225. // type agnostic setter that takes LLSD
  226. void setUntypedValue(const std::string& name, const LLSD& val);
  227. // generic setter
  228. template<typename T> void set(const std::string& name, const T& val)
  229. {
  230. LLControlVariable* control = getControl(name);
  231. if (control && control->isType(get_control_type<T>()))
  232. {
  233. control->set(convert_to_llsd(val));
  234. }
  235. else
  236. {
  237. llwarns << "Invalid control " << name << llendl;
  238. }
  239. }
  240. BOOL controlExists(const std::string& name);
  241. // Returns number of controls loaded, 0 if failed
  242. // If require_declaration is false, will auto-declare controls it finds
  243. // as the given type.
  244. U32 loadFromFileLegacy(const std::string& filename, BOOL require_declaration = TRUE, eControlType declare_as = TYPE_STRING);
  245. U32 saveToFile(const std::string& filename, BOOL nondefault_only);
  246. U32 loadFromFile(const std::string& filename, bool default_values = false, bool save_values = true);
  247. void resetToDefaults();
  248. };
  249. //! Publish/Subscribe object to interact with LLControlGroups.
  250. //! Use an LLCachedControl instance to connect to a LLControlVariable
  251. //! without have to manually create and bind a listener to a local
  252. //! object.
  253. template <class T>
  254. class LLControlCache : public LLRefCount, public LLInstanceTracker<LLControlCache<T>, std::string>
  255. {
  256. public:
  257. // This constructor will declare a control if it doesn't exist in the contol group
  258. LLControlCache(LLControlGroup& group,
  259. const std::string& name,
  260. const T& default_value,
  261. const std::string& comment)
  262. : LLInstanceTracker<LLControlCache<T>, std::string >(name)
  263. {
  264. if(!group.controlExists(name))
  265. {
  266. if(!declareTypedControl(group, name, default_value, comment))
  267. {
  268. llerrs << "The control could not be created!!!" << llendl;
  269. }
  270. }
  271. bindToControl(group, name);
  272. }
  273. LLControlCache(LLControlGroup& group,
  274. const std::string& name)
  275. : LLInstanceTracker<LLControlCache<T>, std::string >(name)
  276. {
  277. if(!group.controlExists(name))
  278. {
  279. llerrs << "Control named " << name << "not found." << llendl;
  280. }
  281. bindToControl(group, name);
  282. }
  283. ~LLControlCache()
  284. {
  285. }
  286. const T& getValue() const { return mCachedValue; }
  287. private:
  288. void bindToControl(LLControlGroup& group, const std::string& name)
  289. {
  290. LLControlVariablePtr controlp = group.getControl(name);
  291. mType = controlp->type();
  292. mCachedValue = convert_from_llsd<T>(controlp->get(), mType, name);
  293. // Add a listener to the controls signal...
  294. mConnection = controlp->getSignal()->connect(
  295. boost::bind(&LLControlCache<T>::handleValueChange, this, _2)
  296. );
  297. mType = controlp->type();
  298. }
  299. bool declareTypedControl(LLControlGroup& group,
  300. const std::string& name,
  301. const T& default_value,
  302. const std::string& comment)
  303. {
  304. LLSD init_value;
  305. eControlType type = get_control_type<T>();
  306. init_value = convert_to_llsd(default_value);
  307. if(type < TYPE_COUNT)
  308. {
  309. group.declareControl(name, type, init_value, comment, FALSE);
  310. return true;
  311. }
  312. return false;
  313. }
  314. bool handleValueChange(const LLSD& newvalue)
  315. {
  316. mCachedValue = convert_from_llsd<T>(newvalue, mType, "");
  317. return true;
  318. }
  319. private:
  320. T mCachedValue;
  321. eControlType mType;
  322. boost::signals2::scoped_connection mConnection;
  323. };
  324. template <typename T>
  325. class LLCachedControl
  326. {
  327. public:
  328. LLCachedControl(LLControlGroup& group,
  329. const std::string& name,
  330. const T& default_value,
  331. const std::string& comment = "Declared In Code")
  332. {
  333. mCachedControlPtr = LLControlCache<T>::getInstance(name);
  334. if (mCachedControlPtr.isNull())
  335. {
  336. mCachedControlPtr = new LLControlCache<T>(group, name, default_value, comment);
  337. }
  338. }
  339. LLCachedControl(LLControlGroup& group,
  340. const std::string& name)
  341. {
  342. mCachedControlPtr = LLControlCache<T>::getInstance(name);
  343. if (mCachedControlPtr.isNull())
  344. {
  345. mCachedControlPtr = new LLControlCache<T>(group, name);
  346. }
  347. }
  348. operator const T&() const { return mCachedControlPtr->getValue(); }
  349. operator boost::function<const T&()> () const { return boost::function<const T&()>(*this); }
  350. const T& operator()() { return mCachedControlPtr->getValue(); }
  351. private:
  352. LLPointer<LLControlCache<T> > mCachedControlPtr;
  353. };
  354. template <> eControlType get_control_type<U32>();
  355. template <> eControlType get_control_type<S32>();
  356. template <> eControlType get_control_type<F32>();
  357. template <> eControlType get_control_type<bool>();
  358. // Yay BOOL, its really an S32.
  359. //template <> eControlType get_control_type<BOOL> ()
  360. template <> eControlType get_control_type<std::string>();
  361. template <> eControlType get_control_type<LLVector3>();
  362. template <> eControlType get_control_type<LLVector3d>();
  363. template <> eControlType get_control_type<LLRect>();
  364. template <> eControlType get_control_type<LLColor4>();
  365. template <> eControlType get_control_type<LLColor3>();
  366. template <> eControlType get_control_type<LLSD>();
  367. template <> LLSD convert_to_llsd<U32>(const U32& in);
  368. template <> LLSD convert_to_llsd<LLVector3>(const LLVector3& in);
  369. template <> LLSD convert_to_llsd<LLVector3d>(const LLVector3d& in);
  370. template <> LLSD convert_to_llsd<LLRect>(const LLRect& in);
  371. template <> LLSD convert_to_llsd<LLColor4>(const LLColor4& in);
  372. template <> LLSD convert_to_llsd<LLColor3>(const LLColor3& in);
  373. template<> std::string convert_from_llsd<std::string>(const LLSD& sd, eControlType type, const std::string& control_name);
  374. template<> LLWString convert_from_llsd<LLWString>(const LLSD& sd, eControlType type, const std::string& control_name);
  375. template<> LLVector3 convert_from_llsd<LLVector3>(const LLSD& sd, eControlType type, const std::string& control_name);
  376. template<> LLVector3d convert_from_llsd<LLVector3d>(const LLSD& sd, eControlType type, const std::string& control_name);
  377. template<> LLRect convert_from_llsd<LLRect>(const LLSD& sd, eControlType type, const std::string& control_name);
  378. template<> bool convert_from_llsd<bool>(const LLSD& sd, eControlType type, const std::string& control_name);
  379. template<> S32 convert_from_llsd<S32>(const LLSD& sd, eControlType type, const std::string& control_name);
  380. template<> F32 convert_from_llsd<F32>(const LLSD& sd, eControlType type, const std::string& control_name);
  381. template<> U32 convert_from_llsd<U32>(const LLSD& sd, eControlType type, const std::string& control_name);
  382. template<> LLColor3 convert_from_llsd<LLColor3>(const LLSD& sd, eControlType type, const std::string& control_name);
  383. template<> LLColor4 convert_from_llsd<LLColor4>(const LLSD& sd, eControlType type, const std::string& control_name);
  384. template<> LLSD convert_from_llsd<LLSD>(const LLSD& sd, eControlType type, const std::string& control_name);
  385. //#define TEST_CACHED_CONTROL 1
  386. #ifdef TEST_CACHED_CONTROL
  387. void test_cached_control();
  388. #endif // TEST_CACHED_CONTROL
  389. #endif