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