lluictrlfactory.h
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:13k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file lluictrlfactory.h
  3.  * @brief Factory class for creating UI controls
  4.  *
  5.  * $LicenseInfo:firstyear=2003&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2003-2010, 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 LLUICTRLFACTORY_H
  33. #define LLUICTRLFACTORY_H
  34. #include "llcallbackmap.h"
  35. #include "llinitparam.h"
  36. #include "llregistry.h"
  37. #include "v4color.h"
  38. #include "llfasttimer.h"
  39. #include "llxuiparser.h"
  40. #include <boost/function.hpp>
  41. #include <iosfwd>
  42. #include <stack>
  43. #include <set>
  44. class LLPanel;
  45. class LLFloater;
  46. class LLView;
  47. // sort functor for typeid maps
  48. struct LLCompareTypeID
  49. {
  50. bool operator()(const std::type_info* lhs, const std::type_info* rhs) const
  51. {
  52. return lhs->before(*rhs);
  53. }
  54. };
  55. // lookup widget constructor funcs by widget name
  56. template <typename DERIVED_TYPE>
  57. class LLChildRegistry : public LLRegistrySingleton<std::string, LLWidgetCreatorFunc, DERIVED_TYPE>
  58. {
  59. public:
  60. typedef LLRegistrySingleton<std::string, LLWidgetCreatorFunc, DERIVED_TYPE> super_t;
  61. // local static instance for registering a particular widget
  62. template<typename T>
  63. class Register : public super_t::StaticRegistrar
  64. {
  65. public:
  66. // register with either the provided builder, or the generic templated builder
  67. Register(const char* tag, LLWidgetCreatorFunc func = NULL);
  68. };
  69. protected:
  70. LLChildRegistry() {}
  71. };
  72. class LLDefaultChildRegistry : public LLChildRegistry<LLDefaultChildRegistry>
  73. {
  74. protected:
  75. LLDefaultChildRegistry(){}
  76. friend class LLSingleton<LLDefaultChildRegistry>;
  77. };
  78. // lookup widget name by type
  79. class LLWidgetNameRegistry 
  80. : public LLRegistrySingleton<const std::type_info*, std::string, LLWidgetNameRegistry , LLCompareTypeID>
  81. {};
  82. // lookup factory functions for default widget instances by widget type
  83. typedef LLView* (*dummy_widget_creator_func_t)(const std::string&);
  84. class LLDefaultWidgetRegistry
  85. : public LLRegistrySingleton<const std::type_info*, dummy_widget_creator_func_t, LLDefaultWidgetRegistry, LLCompareTypeID>
  86. {};
  87. // lookup function for generating empty param block by widget type
  88. // this is used for schema generation
  89. //typedef const LLInitParam::BaseBlock& (*empty_param_block_func_t)();
  90. //class LLDefaultParamBlockRegistry
  91. //: public LLRegistrySingleton<const std::type_info*, empty_param_block_func_t, LLDefaultParamBlockRegistry, LLCompareTypeID>
  92. //{};
  93. extern LLFastTimer::DeclareTimer FTM_WIDGET_SETUP;
  94. extern LLFastTimer::DeclareTimer FTM_WIDGET_CONSTRUCTION;
  95. extern LLFastTimer::DeclareTimer FTM_INIT_FROM_PARAMS;
  96. // Build time optimization, generate this once in .cpp file
  97. #ifndef LLUICTRLFACTORY_CPP
  98. extern template class LLUICtrlFactory* LLSingleton<class LLUICtrlFactory>::getInstance();
  99. #endif
  100. class LLUICtrlFactory : public LLSingleton<LLUICtrlFactory>
  101. {
  102. private:
  103. friend class LLSingleton<LLUICtrlFactory>;
  104. LLUICtrlFactory();
  105. ~LLUICtrlFactory();
  106. // only partial specialization allowed in inner classes, so use extra dummy parameter
  107. template <typename PARAM_BLOCK, int DUMMY>
  108. class ParamDefaults : public LLSingleton<ParamDefaults<PARAM_BLOCK, DUMMY> > 
  109. {
  110. public:
  111. ParamDefaults()
  112. {
  113. // recursively initialize from base class param block
  114. ((typename PARAM_BLOCK::base_block_t&)mPrototype).fillFrom(ParamDefaults<typename PARAM_BLOCK::base_block_t, DUMMY>::instance().get());
  115. // after initializing base classes, look up template file for this param block
  116. const std::string* param_block_tag = getWidgetTag(&typeid(PARAM_BLOCK));
  117. if (param_block_tag)
  118. {
  119. LLUICtrlFactory::loadWidgetTemplate(*param_block_tag, mPrototype);
  120. }
  121. }
  122. const PARAM_BLOCK& get() { return mPrototype; }
  123. private:
  124. PARAM_BLOCK mPrototype;
  125. };
  126. // base case for recursion, there are NO base classes of LLInitParam::BaseBlock
  127. template<int DUMMY>
  128. class ParamDefaults<LLInitParam::BaseBlock, DUMMY> : public LLSingleton<ParamDefaults<LLInitParam::BaseBlock, DUMMY> >
  129. {
  130. public:
  131. const LLInitParam::BaseBlock& get() { return mBaseBlock; }
  132. private:
  133. LLInitParam::BaseBlock mBaseBlock;
  134. };
  135. public:
  136. // get default parameter block for widget of a specific type
  137. template<typename T>
  138. static const typename T::Params& getDefaultParams()
  139. {
  140. //#pragma message("Generating ParamDefaults")
  141. return ParamDefaults<typename T::Params, 0>::instance().get();
  142. }
  143. bool buildFloater(LLFloater* floaterp, const std::string &filename, LLXMLNodePtr output_node);
  144. BOOL buildPanel(LLPanel* panelp, const std::string &filename, LLXMLNodePtr output_node = NULL);
  145. // Does what you want for LLFloaters and LLPanels
  146. // Returns 0 on success
  147. S32 saveToXML(LLView* viewp, const std::string& filename);
  148. std::string getCurFileName() { return mFileNames.empty() ? "" : mFileNames.back(); }
  149. static BOOL getAttributeColor(LLXMLNodePtr node, const std::string& name, LLColor4& color);
  150. LLPanel* createFactoryPanel(const std::string& name);
  151. void pushFactoryFunctions(const LLCallbackMap::map_t* map);
  152. void popFactoryFunctions();
  153. template<typename T>
  154. static T* createWidget(typename T::Params& params, LLView* parent = NULL)
  155. {
  156. T* widget = NULL;
  157. if (!params.validateBlock())
  158. {
  159. llwarns << getInstance()->getCurFileName() << ": Invalid parameter block for " << typeid(T).name() << llendl;
  160. //return NULL;
  161. }
  162. {
  163. LLFastTimer timer(FTM_WIDGET_CONSTRUCTION);
  164. widget = new T(params);
  165. }
  166. {
  167. LLFastTimer timer(FTM_INIT_FROM_PARAMS);
  168. widget->initFromParams(params);
  169. }
  170. if (parent)
  171. {
  172. S32 tab_group = params.tab_group.isProvided() ? params.tab_group() : S32_MAX;
  173. setCtrlParent(widget, parent, tab_group);
  174. }
  175. return widget;
  176. }
  177. template<typename T>
  178. static T* create(typename T::Params& params, LLView* parent = NULL)
  179. {
  180. params.fillFrom(ParamDefaults<typename T::Params, 0>::instance().get());
  181. T* widget = createWidget<T>(params, parent);
  182. if (widget)
  183. {
  184. widget->postBuild();
  185. }
  186. return widget;
  187. }
  188. LLView* createFromXML(LLXMLNodePtr node, LLView* parent, const std::string& filename, const widget_registry_t&, LLXMLNodePtr output_node );
  189. template<typename T>
  190. static T* createFromFile(const std::string &filename, LLView *parent, const widget_registry_t& registry, LLXMLNodePtr output_node = NULL)
  191. {
  192. T* widget = NULL;
  193. std::string skinned_filename = findSkinnedFilename(filename);
  194. getInstance()->mFileNames.push_back(skinned_filename);
  195. {
  196. LLXMLNodePtr root_node;
  197. //if exporting, only load the language being exported, 
  198. //instead of layering localized version on top of english
  199. if (output_node)
  200. {
  201. if (!LLUICtrlFactory::getLocalizedXMLNode(filename, root_node))
  202. {
  203. llwarns << "Couldn't parse XUI file: " <<  filename  << llendl;
  204. goto fail;
  205. }
  206. }
  207. else if (!LLUICtrlFactory::getLayeredXMLNode(filename, root_node))
  208. {
  209. llwarns << "Couldn't parse XUI file: " << skinned_filename << llendl;
  210. goto fail;
  211. }
  212. LLView* view = getInstance()->createFromXML(root_node, parent, filename, registry, output_node);
  213. if (view)
  214. {
  215. widget = dynamic_cast<T*>(view);
  216. // not of right type, so delete it
  217. if (!widget) 
  218. {
  219. delete view;
  220. view = NULL;
  221. }
  222. }
  223. }
  224. fail:
  225. getInstance()->mFileNames.pop_back();
  226. return widget;
  227. }
  228. template<class T>
  229. static T* getDefaultWidget(const std::string& name)
  230. {
  231. dummy_widget_creator_func_t* dummy_func = getDefaultWidgetFunc(&typeid(T));
  232. return dummy_func ? dynamic_cast<T*>((*dummy_func)(name)) : NULL;
  233. }
  234. template <class T> 
  235. static LLView* createDefaultWidget(const std::string& name) 
  236. {
  237. typename T::Params params;
  238. params.name(name);
  239. return create<T>(params);
  240. }
  241. static void copyName(LLXMLNodePtr src, LLXMLNodePtr dest);
  242. template<typename T>
  243. static T* defaultBuilder(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node)
  244. {
  245. LLFastTimer timer(FTM_WIDGET_SETUP);
  246. typename T::Params params(getDefaultParams<T>());
  247. LLXUIParser::instance().readXUI(node, params, LLUICtrlFactory::getInstance()->getCurFileName());
  248. if (output_node)
  249. {
  250. // We always want to output top-left coordinates
  251. typename T::Params output_params(params);
  252. T::setupParamsForExport(output_params, parent);
  253. // Export only the differences between this any default params
  254. typename T::Params default_params(getDefaultParams<T>());
  255. copyName(node, output_node);
  256. LLXUIParser::instance().writeXUI(
  257. output_node, output_params, &default_params);
  258. }
  259. // Apply layout transformations, usually munging rect
  260. params.from_xui = true;
  261. T::applyXUILayout(params, parent);
  262. T* widget = createWidget<T>(params, parent);
  263. typedef typename T::child_registry_t registry_t;
  264. createChildren(widget, node, registry_t::instance(), output_node);
  265. if (widget && !widget->postBuild())
  266. {
  267. delete widget;
  268. widget = NULL;
  269. }
  270. return widget;
  271. }
  272. static void createChildren(LLView* viewp, LLXMLNodePtr node, const widget_registry_t&, LLXMLNodePtr output_node = NULL);
  273. static bool getLayeredXMLNode(const std::string &filename, LLXMLNodePtr& root);
  274. static bool getLocalizedXMLNode(const std::string &xui_filename, LLXMLNodePtr& root);
  275. static void loadWidgetTemplate(const std::string& widget_tag, LLInitParam::BaseBlock& block);
  276. // helper function for adding widget type info to various registries
  277. static void registerWidget(const std::type_info* widget_type, const std::type_info* param_block_type, dummy_widget_creator_func_t creator_func, const std::string& tag);
  278. private:
  279. // return default widget instance factory func for a given type
  280. static dummy_widget_creator_func_t* getDefaultWidgetFunc(const std::type_info* widget_type);
  281. static const std::string* getWidgetTag(const std::type_info* widget_type);
  282. // this exists to get around dependency on llview
  283. static void setCtrlParent(LLView* view, LLView* parent, S32 tab_group);
  284. // Avoid directly using LLUI and LLDir in the template code
  285. static std::string findSkinnedFilename(const std::string& filename);
  286. typedef std::deque<const LLCallbackMap::map_t*> factory_stack_t;
  287. factory_stack_t mFactoryStack;
  288. LLPanel* mDummyPanel;
  289. std::vector<std::string> mFileNames;
  290. };
  291. template<typename T>
  292. const LLInitParam::BaseBlock& getEmptyParamBlock()
  293. {
  294. static typename T::Params params;
  295. return params;
  296. }
  297. // this is here to make gcc happy with reference to LLUICtrlFactory
  298. template<typename DERIVED>
  299. template<typename T> 
  300. LLChildRegistry<DERIVED>::Register<T>::Register(const char* tag, LLWidgetCreatorFunc func)
  301. : LLChildRegistry<DERIVED>::StaticRegistrar(tag, func.empty() ? (LLWidgetCreatorFunc)&LLUICtrlFactory::defaultBuilder<T> : func)
  302. {
  303. // add this widget to various registries
  304. LLUICtrlFactory::instance().registerWidget(&typeid(T), &typeid(typename T::Params), &LLUICtrlFactory::createDefaultWidget<T>, tag);
  305. // since registry_t depends on T, do this in line here
  306. typedef typename T::child_registry_t registry_t;
  307. LLChildRegistryRegistry::instance().defaultRegistrar().add(&typeid(T), registry_t::instance());
  308. }
  309. typedef boost::function<LLPanel* (void)> LLPanelClassCreatorFunc;
  310. // local static instance for registering a particular panel class
  311. class LLRegisterPanelClass
  312. : public LLSingleton< LLRegisterPanelClass >
  313. {
  314. public:
  315. // reigister with either the provided builder, or the generic templated builder
  316. void addPanelClass(const std::string& tag,LLPanelClassCreatorFunc func)
  317. {
  318. mPanelClassesNames[tag] = func;
  319. }
  320. LLPanel* createPanelClass(const std::string& tag)
  321. {
  322. param_name_map_t::iterator iT =  mPanelClassesNames.find(tag);
  323. if(iT == mPanelClassesNames.end())
  324. return 0;
  325. return iT->second();
  326. }
  327. template<typename T>
  328. static T* defaultPanelClassBuilder()
  329. {
  330. T* pT = new T();
  331. return pT;
  332. }
  333. private:
  334. typedef std::map< std::string, LLPanelClassCreatorFunc> param_name_map_t;
  335. param_name_map_t mPanelClassesNames;
  336. };
  337. // local static instance for registering a particular panel class
  338. template<typename T>
  339. class LLRegisterPanelClassWrapper
  340. : public LLRegisterPanelClass
  341. {
  342. public:
  343. // reigister with either the provided builder, or the generic templated builder
  344. LLRegisterPanelClassWrapper(const std::string& tag);
  345. };
  346. template<typename T>
  347. LLRegisterPanelClassWrapper<T>::LLRegisterPanelClassWrapper(const std::string& tag) 
  348. {
  349. LLRegisterPanelClass::instance().addPanelClass(tag,&LLRegisterPanelClass::defaultPanelClassBuilder<T>);
  350. }
  351. #endif //LLUICTRLFACTORY_H