llcontrol.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. /**
  2. * @file llcontrol.h
  3. * @brief A mechanism for storing "control state" for a program
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewergpl$
  6. *
  7. * Copyright (c) 2001-2009, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #ifndef LL_LLCONTROL_H
  33. #define LL_LLCONTROL_H
  34. #include <vector>
  35. #include "boost/bind.hpp"
  36. #include "boost/signals2.hpp"
  37. #include "llpointer.h"
  38. #include "llpreprocessor.h"
  39. #include "llstring.h"
  40. #include "llrect.h"
  41. #include "llrefcount.h"
  42. #include "llinstancetracker.h"
  43. class LLVector3;
  44. class LLVector3d;
  45. class LLColor4;
  46. class LLColor3;
  47. class LLColor4U;
  48. constexpr bool NO_PERSIST = false;
  49. constexpr bool PERSIST_ALWAYS = true;
  50. typedef enum e_control_type
  51. {
  52. TYPE_U32 = 0,
  53. TYPE_S32,
  54. TYPE_F32,
  55. TYPE_BOOLEAN,
  56. TYPE_STRING,
  57. TYPE_VEC3,
  58. TYPE_VEC3D,
  59. TYPE_RECT,
  60. TYPE_COL4,
  61. TYPE_COL3,
  62. TYPE_COL4U,
  63. TYPE_LLSD,
  64. TYPE_COUNT
  65. } eControlType;
  66. // Useful combiner for boost signals that return a bool (e.g. validation)
  67. // returns false if any of the callbacks return false.
  68. struct boost_boolean_combiner
  69. {
  70. typedef bool result_type;
  71. template<typename InputIterator>
  72. bool operator()(InputIterator first, InputIterator last) const
  73. {
  74. bool res = true;
  75. while (first != last)
  76. {
  77. res &= *first++;
  78. }
  79. return res;
  80. }
  81. };
  82. class LLControlVariable : public LLRefCount
  83. {
  84. friend class LLControlGroup;
  85. public:
  86. typedef boost::signals2::signal<bool(LLControlVariable* controlp,
  87. const LLSD&),
  88. boost_boolean_combiner> validate_signal_t;
  89. typedef boost::signals2::signal<void(LLControlVariable* controlp,
  90. const LLSD&)> commit_signal_t;
  91. public:
  92. LLControlVariable(const char* name, eControlType type,
  93. LLSD initial, const std::string& comment,
  94. bool persist = true, bool hide_from_user = false);
  95. LL_INLINE const std::string& getName() const { return mName; }
  96. LL_INLINE const std::string& getComment() const { return mComment; }
  97. LL_INLINE eControlType type() { return mType; }
  98. LL_INLINE bool isType(eControlType tp) { return tp == mType; }
  99. void resetToDefault(bool fire_signal = false);
  100. LL_INLINE commit_signal_t* getSignal() { return &mCommitSignal; }
  101. LL_INLINE validate_signal_t* getValidateSignal() { return &mValidateSignal; }
  102. LL_INLINE bool isDefault() { return mValues.size() == 1; }
  103. bool isSaveValueDefault();
  104. LL_INLINE bool isPersisted() { return mPersist; }
  105. LL_INLINE bool isHiddenFromUser() { return mHideFromUser; }
  106. LL_INLINE const LLSD& getValue() const { return mValues.back(); }
  107. LL_INLINE const LLSD& getDefault() const { return mValues.front(); }
  108. LLSD getSaveValue(bool user_value = true) const;
  109. void setValue(const LLSD& value, bool saved_value = true);
  110. void setDefaultValue(const LLSD& value);
  111. void setPersist(bool state);
  112. void setHiddenFromUser(bool hide);
  113. void setComment(const std::string& comment);
  114. LL_INLINE void firePropertyChanged() { mCommitSignal(this, mValues.back()); }
  115. private:
  116. LLSD getComparableValue(const LLSD& value);
  117. bool llsd_compare(const LLSD& a, const LLSD & b);
  118. private:
  119. // Note: the first member variable is 32 bits in order to align on 64 bits
  120. // for the next variables, counting the 32 bits counter from LLRefCount. HB
  121. eControlType mType;
  122. std::string mName;
  123. std::string mComment;
  124. commit_signal_t mCommitSignal;
  125. validate_signal_t mValidateSignal;
  126. std::vector<LLSD> mValues;
  127. bool mPersist;
  128. bool mHideFromUser;
  129. };
  130. typedef LLPointer<LLControlVariable> LLControlVariablePtr;
  131. // Helper functions for converting between static types and LLControl values
  132. template <class T>
  133. eControlType get_control_type()
  134. {
  135. llwarns << "Usupported control type: " << typeid(T).name() << "."
  136. << 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,
  147. const char* control_name)
  148. {
  149. // Needs specialization
  150. return T(sd);
  151. }
  152. class LLControlGroup : public LLInstanceTracker<LLControlGroup, std::string>
  153. {
  154. protected:
  155. LOG_CLASS(LLControlGroup);
  156. eControlType typeStringToEnum(const std::string& typestr);
  157. std::string typeEnumToString(eControlType typeenum);
  158. public:
  159. LLControlGroup(const std::string& name);
  160. ~LLControlGroup();
  161. void cleanup();
  162. LLControlVariablePtr getControl(const char* name);
  163. struct ApplyFunctor
  164. {
  165. virtual ~ApplyFunctor() {}
  166. virtual void apply(const std::string& name,
  167. LLControlVariable* controlp) = 0;
  168. };
  169. void applyToAll(ApplyFunctor* func);
  170. LLControlVariable* declareControl(const char* name, eControlType type,
  171. const LLSD initial_val,
  172. const std::string& comment, bool persist,
  173. bool hide_from_settings_editor = false);
  174. LLControlVariable* declareBool(const char* name, bool initial_val,
  175. const std::string& comment,
  176. bool persist = true);
  177. LLControlVariable* declareString(const char* name,
  178. const std::string& initial_val,
  179. const std::string& comment,
  180. bool persist = true);
  181. LLControlVariable* declareColor4(const char* name,
  182. const LLColor4& initial_val,
  183. const std::string& comment,
  184. bool persist = true);
  185. LLControlVariable* declareColor4U(const char* name,
  186. const LLColor4U& initial_val,
  187. const std::string& comment,
  188. bool persist = true);
  189. LLControlVariable* declareLLSD(const char* name,
  190. const LLSD& initial_val,
  191. const std::string& comment,
  192. bool persist = true);
  193. #if 0 // Not used
  194. LLControlVariable* declareU32(const char* name, U32 initial_val,
  195. const std::string& comment,
  196. bool persist = true);
  197. LLControlVariable* declareS32(const char* name,
  198. S32 initial_val,
  199. const std::string& comment,
  200. bool persist = true);
  201. LLControlVariable* declareF32(const char* name, F32 initial_val,
  202. const std::string& comment,
  203. bool persist = true);
  204. LLControlVariable* declareVec3(const char* name,
  205. const LLVector3& initial_val,
  206. const std::string& comment,
  207. bool persist = true);
  208. LLControlVariable* declareVec3d(const char* name,
  209. const LLVector3d& initial_val,
  210. const std::string& comment,
  211. bool persist = true);
  212. LLControlVariable* declareRect(const char* name,
  213. const LLRect& initial_val,
  214. const std::string& comment,
  215. bool persist = true);
  216. LLControlVariable* declareColor3(const char* name,
  217. const LLColor3& initial_val,
  218. const std::string& comment,
  219. bool persist = true);
  220. #endif
  221. std::string getString(const char* name);
  222. std::string getText(const char* name);
  223. bool getBool(const char* name);
  224. S32 getS32(const char* name);
  225. F32 getF32(const char* name);
  226. U32 getU32(const char* name);
  227. LLWString getWString(const char* name);
  228. LLVector3 getVector3(const char* name);
  229. LLVector3d getVector3d(const char* name);
  230. LLRect getRect(const char* name);
  231. LLSD getLLSD(const char* name);
  232. LLColor4 getColor(const char* name);
  233. LLColor4 getColor4(const char* name);
  234. LLColor4U getColor4U(const char* name);
  235. LLColor3 getColor3(const char* name);
  236. // Generic getter
  237. template<typename T> T get(const char* name)
  238. {
  239. LL_DEBUGS("GetControlCalls") << "Requested control: " << name
  240. << LL_ENDL;
  241. LLControlVariable* ctrlp = getControl(name);
  242. if (!ctrlp)
  243. {
  244. llwarns << "Control " << name << " not found." << llendl;
  245. return T();
  246. }
  247. return convert_from_llsd<T>(ctrlp->getValue(), ctrlp->type(), name);
  248. }
  249. void setBool(const char* name, bool val);
  250. void setS32(const char* name, S32 val);
  251. void setF32(const char* name, F32 val);
  252. void setU32(const char* name, U32 val);
  253. void setString(const char* name, const std::string& val);
  254. void setVector3(const char* name, const LLVector3& val);
  255. void setVector3d(const char* name, const LLVector3d& val);
  256. void setRect(const char* name, const LLRect& val);
  257. void setColor4(const char* name, const LLColor4& val);
  258. void setLLSD(const char* name, const LLSD& val);
  259. // Type agnostic setter that takes LLSD
  260. void setUntypedValue(const char* name, const LLSD& val);
  261. // Generic setter
  262. template<typename T> void set(const char* name, const T& val)
  263. {
  264. LLControlVariable* ctrlp = getControl(name);
  265. if (!ctrlp || !ctrlp->isType(get_control_type<T>()))
  266. {
  267. llwarns << "Invalid control " << name << llendl;
  268. return;
  269. }
  270. ctrlp->setValue(convert_to_llsd(val));
  271. }
  272. bool controlExists(const char* name);
  273. // Returns number of controls loaded, 0 if failed
  274. // If require_declaration is false, will auto-declare controls it finds
  275. // as the given type.
  276. U32 loadFromFileLegacy(const std::string& filename,
  277. bool require_declaration = true,
  278. eControlType declare_as = TYPE_STRING);
  279. U32 saveToFile(const std::string& filename, bool nondefault_only = true,
  280. bool save_default = false);
  281. U32 loadFromFile(const std::string& filename, bool default_values = false,
  282. bool save_values = true);
  283. void resetToDefaults();
  284. // Ignorable Warnings
  285. // Add a config variable to be reset on resetWarnings()
  286. void addWarning(const std::string& name);
  287. bool getWarning(const std::string& name);
  288. void setWarning(const std::string& name, bool val);
  289. // Resets all ignorables
  290. void resetWarnings();
  291. protected:
  292. typedef std::map<std::string, LLControlVariablePtr> ctrl_name_table_t;
  293. ctrl_name_table_t mNameTable;
  294. std::set<std::string> mWarnings;
  295. std::string mTypeString[TYPE_COUNT];
  296. };
  297. // Publish/Subscribe object to interact with LLControlGroups.
  298. static const std::string sCachedControlComment = "Cached control";
  299. // Use an LLCachedControl instance to connect to a LLControlVariable without
  300. // having to manually create and bind a listener to a local object.
  301. template <class T>
  302. class LLControlCache : public LLRefCount,
  303. public LLInstanceTracker<LLControlCache<T>, std::string>
  304. {
  305. public:
  306. LLControlCache(LLControlGroup& group, const char* name)
  307. : LLInstanceTracker<LLControlCache<T>, std::string >(name)
  308. {
  309. bindToControl(group, name);
  310. }
  311. LL_INLINE const T& getValue() const { return mCachedValue; }
  312. private:
  313. LL_NO_INLINE void bindToControl(LLControlGroup& group, const char* name)
  314. {
  315. if (!group.controlExists(name))
  316. {
  317. llerrs << "Control named " << name << " not found." << llendl;
  318. }
  319. LLControlVariablePtr ctrlp = group.getControl(name);
  320. mType = ctrlp->type();
  321. mCachedValue = convert_from_llsd<T>(ctrlp->getValue(), mType, name);
  322. // Add a listener to the controls signal...
  323. mConnection =
  324. ctrlp->getSignal()->connect(boost::bind(&LLControlCache<T>::handleValueChange,
  325. this, _2),
  326. boost::signals2::at_front);
  327. }
  328. bool handleValueChange(const LLSD& newvalue)
  329. {
  330. mCachedValue = convert_from_llsd<T>(newvalue, mType, "");
  331. return true;
  332. }
  333. private:
  334. T mCachedValue;
  335. eControlType mType;
  336. boost::signals2::scoped_connection mConnection;
  337. };
  338. template <typename T>
  339. class LLCachedControl
  340. {
  341. public:
  342. LLCachedControl(LLControlGroup& group, const char* name)
  343. {
  344. mCachedControlPtr = LLControlCache<T>::getNamedInstance(name).get();
  345. if (mCachedControlPtr.isNull())
  346. {
  347. mCachedControlPtr = new LLControlCache<T>(group, name);
  348. }
  349. }
  350. LL_INLINE operator const T&() const
  351. {
  352. return mCachedControlPtr->getValue();
  353. }
  354. LL_INLINE operator boost::function<const T&()>() const
  355. {
  356. return boost::function<const T&()>(*this);
  357. }
  358. LL_INLINE const T& operator()()
  359. {
  360. return mCachedControlPtr->getValue();
  361. }
  362. private:
  363. LLPointer<LLControlCache<T> > mCachedControlPtr;
  364. };
  365. template<>eControlType get_control_type<U32>();
  366. template<>eControlType get_control_type<S32>();
  367. template<>eControlType get_control_type<F32>();
  368. template<>eControlType get_control_type<bool>();
  369. template<>eControlType get_control_type<std::string>();
  370. template<>eControlType get_control_type<LLVector3>();
  371. template<>eControlType get_control_type<LLVector3d>();
  372. template<>eControlType get_control_type<LLRect>();
  373. template<>eControlType get_control_type<LLColor4>();
  374. template<>eControlType get_control_type<LLColor4U>();
  375. template<>eControlType get_control_type<LLColor3>();
  376. template<>eControlType get_control_type<LLSD>();
  377. template<>LLSD convert_to_llsd<U32>(const U32& in);
  378. template<>LLSD convert_to_llsd<LLVector3>(const LLVector3& in);
  379. template<>LLSD convert_to_llsd<LLVector3d>(const LLVector3d& in);
  380. template<>LLSD convert_to_llsd<LLRect>(const LLRect& in);
  381. template<>LLSD convert_to_llsd<LLColor4>(const LLColor4& in);
  382. template<>LLSD convert_to_llsd<LLColor4U>(const LLColor4U& in);
  383. template<>LLSD convert_to_llsd<LLColor3>(const LLColor3& in);
  384. template<>std::string convert_from_llsd<std::string>(const LLSD& sd, eControlType type, const char* control_name);
  385. template<>LLWString convert_from_llsd<LLWString>(const LLSD& sd, eControlType type, const char* control_name);
  386. template<>LLVector3 convert_from_llsd<LLVector3>(const LLSD& sd, eControlType type, const char* control_name);
  387. template<>LLVector3d convert_from_llsd<LLVector3d>(const LLSD& sd, eControlType type, const char* control_name);
  388. template<>LLRect convert_from_llsd<LLRect>(const LLSD& sd, eControlType type, const char* control_name);
  389. template<>bool convert_from_llsd<bool>(const LLSD& sd, eControlType type, const char* control_name);
  390. template<>S32 convert_from_llsd<S32>(const LLSD& sd, eControlType type, const char* control_name);
  391. template<>F32 convert_from_llsd<F32>(const LLSD& sd, eControlType type, const char* control_name);
  392. template<>U32 convert_from_llsd<U32>(const LLSD& sd, eControlType type, const char* control_name);
  393. template<>LLColor3 convert_from_llsd<LLColor3>(const LLSD& sd, eControlType type, const char* control_name);
  394. template<>LLColor4 convert_from_llsd<LLColor4>(const LLSD& sd, eControlType type, const char* control_name);
  395. template<>LLColor4U convert_from_llsd<LLColor4U>(const LLSD& sd, eControlType type, const char* control_name);
  396. template<>LLSD convert_from_llsd<LLSD>(const LLSD& sd, eControlType type, const char* control_name);
  397. #endif