PageRenderTime 18ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/llui/lluictrlfactory.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 311 lines | 195 code | 49 blank | 67 comment | 28 complexity | e737359c8b644f087bb913f1c1562298 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file lluictrlfactory.cpp
  3. * @brief Factory class for creating UI controls
  4. *
  5. * $LicenseInfo:firstyear=2003&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. #include "linden_common.h"
  27. #define LLUICTRLFACTORY_CPP
  28. #include "lluictrlfactory.h"
  29. #include "llxmlnode.h"
  30. #include <fstream>
  31. #include <boost/tokenizer.hpp>
  32. // other library includes
  33. #include "llcontrol.h"
  34. #include "lldir.h"
  35. #include "v4color.h"
  36. #include "v3dmath.h"
  37. #include "llquaternion.h"
  38. // this library includes
  39. #include "llpanel.h"
  40. LLFastTimer::DeclareTimer FTM_WIDGET_CONSTRUCTION("Widget Construction");
  41. LLFastTimer::DeclareTimer FTM_INIT_FROM_PARAMS("Widget InitFromParams");
  42. LLFastTimer::DeclareTimer FTM_WIDGET_SETUP("Widget Setup");
  43. //-----------------------------------------------------------------------------
  44. // UI Ctrl class for padding
  45. class LLUICtrlLocate : public LLUICtrl
  46. {
  47. public:
  48. struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
  49. {
  50. Params()
  51. {
  52. name = "locate";
  53. tab_stop = false;
  54. }
  55. };
  56. LLUICtrlLocate(const Params& p) : LLUICtrl(p) {}
  57. virtual void draw() { }
  58. };
  59. static LLDefaultChildRegistry::Register<LLUICtrlLocate> r1("locate");
  60. // Build time optimization, generate this once in .cpp file
  61. template class LLUICtrlFactory* LLSingleton<class LLUICtrlFactory>::getInstance();
  62. //-----------------------------------------------------------------------------
  63. // LLUICtrlFactory()
  64. //-----------------------------------------------------------------------------
  65. LLUICtrlFactory::LLUICtrlFactory()
  66. : mDummyPanel(NULL) // instantiated when first needed
  67. {
  68. }
  69. LLUICtrlFactory::~LLUICtrlFactory()
  70. {
  71. // go ahead and leak mDummyPanel since this is static destructor time
  72. //delete mDummyPanel;
  73. //mDummyPanel = NULL;
  74. }
  75. void LLUICtrlFactory::loadWidgetTemplate(const std::string& widget_tag, LLInitParam::BaseBlock& block)
  76. {
  77. std::string filename = std::string("widgets") + gDirUtilp->getDirDelimiter() + widget_tag + ".xml";
  78. LLXMLNodePtr root_node;
  79. std::string full_filename = gDirUtilp->findSkinnedFilename(LLUI::getXUIPaths().front(), filename);
  80. if (!full_filename.empty())
  81. {
  82. LLUICtrlFactory::instance().pushFileName(full_filename);
  83. LLSimpleXUIParser parser;
  84. parser.readXUI(full_filename, block);
  85. LLUICtrlFactory::instance().popFileName();
  86. }
  87. }
  88. static LLFastTimer::DeclareTimer FTM_CREATE_CHILDREN("Create XUI Children");
  89. //static
  90. void LLUICtrlFactory::createChildren(LLView* viewp, LLXMLNodePtr node, const widget_registry_t& registry, LLXMLNodePtr output_node)
  91. {
  92. LLFastTimer ft(FTM_CREATE_CHILDREN);
  93. if (node.isNull()) return;
  94. for (LLXMLNodePtr child_node = node->getFirstChild(); child_node.notNull(); child_node = child_node->getNextSibling())
  95. {
  96. LLXMLNodePtr outputChild;
  97. if (output_node)
  98. {
  99. outputChild = output_node->createChild("", FALSE);
  100. }
  101. if (!instance().createFromXML(child_node, viewp, LLStringUtil::null, registry, outputChild))
  102. {
  103. // child_node is not a valid child for the current parent
  104. std::string child_name = std::string(child_node->getName()->mString);
  105. if (LLDefaultChildRegistry::instance().getValue(child_name))
  106. {
  107. // This means that the registry assocaited with the parent widget does not have an entry
  108. // for the child widget
  109. // You might need to add something like:
  110. // static ParentWidgetRegistry::Register<ChildWidgetType> register("child_widget_name");
  111. llwarns << child_name << " is not a valid child of " << node->getName()->mString << llendl;
  112. }
  113. else
  114. {
  115. llwarns << "Could not create widget named " << child_node->getName()->mString << llendl;
  116. }
  117. }
  118. if (outputChild && !outputChild->mChildren && outputChild->mAttributes.empty() && outputChild->getValue().empty())
  119. {
  120. output_node->deleteChild(outputChild);
  121. }
  122. }
  123. }
  124. static LLFastTimer::DeclareTimer FTM_XML_PARSE("XML Reading/Parsing");
  125. //-----------------------------------------------------------------------------
  126. // getLayeredXMLNode()
  127. //-----------------------------------------------------------------------------
  128. bool LLUICtrlFactory::getLayeredXMLNode(const std::string &xui_filename, LLXMLNodePtr& root)
  129. {
  130. LLFastTimer timer(FTM_XML_PARSE);
  131. std::vector<std::string> paths;
  132. std::string path = gDirUtilp->findSkinnedFilename(LLUI::getSkinPath(), xui_filename);
  133. if (!path.empty())
  134. {
  135. paths.push_back(path);
  136. }
  137. std::string localize_path = gDirUtilp->findSkinnedFilename(LLUI::getLocalizedSkinPath(), xui_filename);
  138. if (!localize_path.empty() && localize_path != path)
  139. {
  140. paths.push_back(localize_path);
  141. }
  142. if (paths.empty())
  143. {
  144. // sometimes whole path is passed in as filename
  145. paths.push_back(xui_filename);
  146. }
  147. return LLXMLNode::getLayeredXMLNode(root, paths);
  148. }
  149. //-----------------------------------------------------------------------------
  150. // getLocalizedXMLNode()
  151. //-----------------------------------------------------------------------------
  152. bool LLUICtrlFactory::getLocalizedXMLNode(const std::string &xui_filename, LLXMLNodePtr& root)
  153. {
  154. LLFastTimer timer(FTM_XML_PARSE);
  155. std::string full_filename = gDirUtilp->findSkinnedFilename(LLUI::getLocalizedSkinPath(), xui_filename);
  156. if (!LLXMLNode::parseFile(full_filename, root, NULL))
  157. {
  158. return false;
  159. }
  160. else
  161. {
  162. return true;
  163. }
  164. }
  165. //-----------------------------------------------------------------------------
  166. // saveToXML()
  167. //-----------------------------------------------------------------------------
  168. S32 LLUICtrlFactory::saveToXML(LLView* viewp, const std::string& filename)
  169. {
  170. return 0;
  171. }
  172. //-----------------------------------------------------------------------------
  173. //-----------------------------------------------------------------------------
  174. static LLFastTimer::DeclareTimer FTM_CREATE_FROM_XML("Create child widget");
  175. LLView *LLUICtrlFactory::createFromXML(LLXMLNodePtr node, LLView* parent, const std::string& filename, const widget_registry_t& registry, LLXMLNodePtr output_node)
  176. {
  177. LLFastTimer timer(FTM_CREATE_FROM_XML);
  178. std::string ctrl_type = node->getName()->mString;
  179. LLStringUtil::toLower(ctrl_type);
  180. const LLWidgetCreatorFunc* funcp = registry.getValue(ctrl_type);
  181. if (funcp == NULL)
  182. {
  183. return NULL;
  184. }
  185. if (parent == NULL)
  186. {
  187. if (mDummyPanel == NULL)
  188. {
  189. LLPanel::Params p;
  190. mDummyPanel = create<LLPanel>(p);
  191. }
  192. parent = mDummyPanel;
  193. }
  194. LLView *view = (*funcp)(node, parent, output_node);
  195. return view;
  196. }
  197. std::string LLUICtrlFactory::getCurFileName()
  198. {
  199. return mFileNames.empty() ? "" : mFileNames.back();
  200. }
  201. void LLUICtrlFactory::pushFileName(const std::string& name)
  202. {
  203. mFileNames.push_back(gDirUtilp->findSkinnedFilename(LLUI::getSkinPath(), name));
  204. }
  205. void LLUICtrlFactory::popFileName()
  206. {
  207. mFileNames.pop_back();
  208. }
  209. //static
  210. void LLUICtrlFactory::setCtrlParent(LLView* view, LLView* parent, S32 tab_group)
  211. {
  212. if (tab_group == S32_MAX) tab_group = parent->getLastTabGroup();
  213. parent->addChild(view, tab_group);
  214. }
  215. // Avoid directly using LLUI and LLDir in the template code
  216. //static
  217. std::string LLUICtrlFactory::findSkinnedFilename(const std::string& filename)
  218. {
  219. return gDirUtilp->findSkinnedFilename(LLUI::getSkinPath(), filename);
  220. }
  221. //static
  222. void LLUICtrlFactory::copyName(LLXMLNodePtr src, LLXMLNodePtr dest)
  223. {
  224. dest->setName(src->getName()->mString);
  225. }
  226. template<typename T>
  227. const LLInitParam::BaseBlock& get_empty_param_block()
  228. {
  229. static typename T::Params params;
  230. return params;
  231. }
  232. // adds a widget and its param block to various registries
  233. //static
  234. void LLUICtrlFactory::registerWidget(const std::type_info* widget_type, const std::type_info* param_block_type, const std::string& tag)
  235. {
  236. // associate parameter block type with template .xml file
  237. std::string* existing_tag = LLWidgetNameRegistry::instance().getValue(param_block_type);
  238. if (existing_tag != NULL)
  239. {
  240. if(*existing_tag != tag)
  241. {
  242. std::cerr << "Duplicate entry for T::Params, try creating empty param block in derived classes that inherit T::Params" << std::endl;
  243. // forcing crash here
  244. char* foo = 0;
  245. *foo = 1;
  246. }
  247. else
  248. {
  249. // widget already registered
  250. return;
  251. }
  252. }
  253. LLWidgetNameRegistry::instance().defaultRegistrar().add(param_block_type, tag);
  254. //FIXME: comment this in when working on schema generation
  255. //LLWidgetTypeRegistry::instance().defaultRegistrar().add(tag, widget_type);
  256. //LLDefaultParamBlockRegistry::instance().defaultRegistrar().add(widget_type, &get_empty_param_block<T>);
  257. }
  258. //static
  259. const std::string* LLUICtrlFactory::getWidgetTag(const std::type_info* widget_type)
  260. {
  261. return LLWidgetNameRegistry::instance().getValue(widget_type);
  262. }