summaryrefslogtreecommitdiff
path: root/indra/llui/lluictrlfactory.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llui/lluictrlfactory.cpp')
-rw-r--r--indra/llui/lluictrlfactory.cpp849
1 files changed, 119 insertions, 730 deletions
diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp
index 24e4ad18e6..15a382660e 100644
--- a/indra/llui/lluictrlfactory.cpp
+++ b/indra/llui/lluictrlfactory.cpp
@@ -2,38 +2,35 @@
* @file lluictrlfactory.cpp
* @brief Factory class for creating UI controls
*
- * $LicenseInfo:firstyear=2003&license=viewergpl$
- *
- * Copyright (c) 2003-2009, Linden Research, Inc.
- *
+ * $LicenseInfo:firstyear=2003&license=viewerlgpl$
* Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
*
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "linden_common.h"
+#define LLUICTRLFACTORY_CPP
#include "lluictrlfactory.h"
+#include "llxmlnode.h"
+
#include <fstream>
#include <boost/tokenizer.hpp>
@@ -45,49 +42,13 @@
#include "llquaternion.h"
// this library includes
-#include "llbutton.h"
-#include "llcheckboxctrl.h"
-//#include "llcolorswatch.h"
-#include "llcombobox.h"
-#include "llcontrol.h"
-#include "lldir.h"
-#include "llevent.h"
#include "llfloater.h"
-#include "lliconctrl.h"
-#include "lllineeditor.h"
-#include "llmenugl.h"
-#include "llradiogroup.h"
-#include "llscrollcontainer.h"
-#include "llscrollingpanellist.h"
-#include "llscrolllistctrl.h"
-#include "llslider.h"
-#include "llsliderctrl.h"
-#include "llmultislider.h"
-#include "llmultisliderctrl.h"
-#include "llspinctrl.h"
-#include "lltabcontainer.h"
-#include "lltextbox.h"
-#include "lltexteditor.h"
-#include "llui.h"
-#include "llviewborder.h"
-
-const char XML_HEADER[] = "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>\n";
-
-const S32 HPAD = 4;
-const S32 VPAD = 4;
-const S32 FLOATER_H_MARGIN = 15;
-const S32 MIN_WIDGET_HEIGHT = 10;
LLFastTimer::DeclareTimer FTM_WIDGET_CONSTRUCTION("Widget Construction");
LLFastTimer::DeclareTimer FTM_INIT_FROM_PARAMS("Widget InitFromParams");
LLFastTimer::DeclareTimer FTM_WIDGET_SETUP("Widget Setup");
//-----------------------------------------------------------------------------
-// Register widgets that are purely data driven here so they get linked in
-#include "llstatview.h"
-static LLDefaultWidgetRegistry::Register<LLStatView> register_stat_view("stat_view");
-
-//-----------------------------------------------------------------------------
// UI Ctrl class for padding
class LLUICtrlLocate : public LLUICtrl
@@ -107,7 +68,10 @@ public:
};
-static LLDefaultWidgetRegistry::Register<LLUICtrlLocate> r1("locate");
+static LLDefaultChildRegistry::Register<LLUICtrlLocate> r1("locate");
+
+// Build time optimization, generate this once in .cpp file
+template class LLUICtrlFactory* LLSingleton<class LLUICtrlFactory>::getInstance();
//-----------------------------------------------------------------------------
// LLUICtrlFactory()
@@ -119,8 +83,9 @@ LLUICtrlFactory::LLUICtrlFactory()
LLUICtrlFactory::~LLUICtrlFactory()
{
- delete mDummyPanel;
- mDummyPanel = NULL;
+ // go ahead and leak mDummyPanel since this is static destructor time
+ //delete mDummyPanel;
+ //mDummyPanel = NULL;
}
void LLUICtrlFactory::loadWidgetTemplate(const std::string& widget_tag, LLInitParam::BaseBlock& block)
@@ -130,13 +95,18 @@ void LLUICtrlFactory::loadWidgetTemplate(const std::string& widget_tag, LLInitPa
if (LLUICtrlFactory::getLayeredXMLNode(filename, root_node))
{
- LLXUIParser::instance().readXUI(root_node, block);
+ LLUICtrlFactory::instance().pushFileName(filename);
+ LLXUIParser::instance().readXUI(root_node, block, filename);
+ LLUICtrlFactory::instance().popFileName();
}
}
+static LLFastTimer::DeclareTimer FTM_CREATE_CHILDREN("Create XUI Children");
+
//static
-void LLUICtrlFactory::createChildren(LLView* viewp, LLXMLNodePtr node, LLXMLNodePtr output_node)
+void LLUICtrlFactory::createChildren(LLView* viewp, LLXMLNodePtr node, const widget_registry_t& registry, LLXMLNodePtr output_node)
{
+ LLFastTimer ft(FTM_CREATE_CHILDREN);
if (node.isNull()) return;
for (LLXMLNodePtr child_node = node->getFirstChild(); child_node.notNull(); child_node = child_node->getNextSibling())
@@ -147,10 +117,22 @@ void LLUICtrlFactory::createChildren(LLView* viewp, LLXMLNodePtr node, LLXMLNode
outputChild = output_node->createChild("", FALSE);
}
- if (!instance().createFromXML(child_node, viewp, LLStringUtil::null, outputChild, viewp->getChildRegistry()))
+ if (!instance().createFromXML(child_node, viewp, LLStringUtil::null, registry, outputChild))
{
+ // child_node is not a valid child for the current parent
std::string child_name = std::string(child_node->getName()->mString);
- llwarns << "Could not create widget named " << child_node->getName()->mString << llendl;
+ if (LLDefaultChildRegistry::instance().getValue(child_name))
+ {
+ // This means that the registry assocaited with the parent widget does not have an entry
+ // for the child widget
+ // You might need to add something like:
+ // static ParentWidgetRegistry::Register<ChildWidgetType> register("child_widget_name");
+ llwarns << child_name << " is not a valid child of " << node->getName()->mString << llendl;
+ }
+ else
+ {
+ llwarns << "Could not create widget named " << child_node->getName()->mString << llendl;
+ }
}
if (outputChild && !outputChild->mChildren && outputChild->mAttributes.empty() && outputChild->getValue().empty())
@@ -161,7 +143,7 @@ void LLUICtrlFactory::createChildren(LLView* viewp, LLXMLNodePtr node, LLXMLNode
}
-LLFastTimer::DeclareTimer FTM_XML_PARSE("XML Reading/Parsing");
+static LLFastTimer::DeclareTimer FTM_XML_PARSE("XML Reading/Parsing");
//-----------------------------------------------------------------------------
// getLayeredXMLNode()
//-----------------------------------------------------------------------------
@@ -189,14 +171,14 @@ bool LLUICtrlFactory::getLocalizedXMLNode(const std::string &xui_filename, LLXML
}
}
-static LLFastTimer::DeclareTimer BUILD_FLOATERS("Build Floaters");
+static LLFastTimer::DeclareTimer FTM_BUILD_FLOATERS("Build Floaters");
//-----------------------------------------------------------------------------
// buildFloater()
//-----------------------------------------------------------------------------
-void LLUICtrlFactory::buildFloater(LLFloater* floaterp, const std::string& filename, BOOL open_floater, LLXMLNodePtr output_node)
+bool LLUICtrlFactory::buildFloater(LLFloater* floaterp, const std::string& filename, LLXMLNodePtr output_node)
{
- LLFastTimer timer(BUILD_FLOATERS);
+ LLFastTimer timer(FTM_BUILD_FLOATERS);
LLXMLNodePtr root;
//if exporting, only load the language being exported,
@@ -206,24 +188,26 @@ void LLUICtrlFactory::buildFloater(LLFloater* floaterp, const std::string& filen
if (!LLUICtrlFactory::getLocalizedXMLNode(filename, root))
{
llwarns << "Couldn't parse floater from: " << LLUI::getLocalizedSkinPath() + gDirUtilp->getDirDelimiter() + filename << llendl;
- return;
+ return false;
}
}
else if (!LLUICtrlFactory::getLayeredXMLNode(filename, root))
{
llwarns << "Couldn't parse floater from: " << LLUI::getSkinPath() + gDirUtilp->getDirDelimiter() + filename << llendl;
- return;
+ return false;
}
// root must be called floater
if( !(root->hasName("floater") || root->hasName("multi_floater")) )
{
llwarns << "Root node should be named floater in: " << filename << llendl;
- return;
+ return false;
}
-
+
+ bool res = true;
+
lldebugs << "Building floater " << filename << llendl;
- mFileNames.push_back(gDirUtilp->findSkinnedFilename(LLUI::getSkinPath(), filename));
+ pushFileName(filename);
{
if (!floaterp->getFactoryMap().empty())
{
@@ -234,12 +218,9 @@ void LLUICtrlFactory::buildFloater(LLFloater* floaterp, const std::string& filen
floaterp->getCommitCallbackRegistrar().pushScope();
floaterp->getEnableCallbackRegistrar().pushScope();
- floaterp->initFloaterXML(root, floaterp->getParent(), open_floater, output_node);
+ res = floaterp->initFloaterXML(root, floaterp->getParent(), filename, output_node);
- if (LLUI::sShowXUINames)
- {
- floaterp->setToolTip(filename);
- }
+ floaterp->setXMLFilename(filename);
floaterp->getCommitCallbackRegistrar().popScope();
floaterp->getEnableCallbackRegistrar().popScope();
@@ -249,14 +230,9 @@ void LLUICtrlFactory::buildFloater(LLFloater* floaterp, const std::string& filen
mFactoryStack.pop_front();
}
}
- mFileNames.pop_back();
-}
-
-LLFloater* LLUICtrlFactory::buildFloaterFromXML(const std::string& filename, BOOL open_floater)
-{
- LLFloater* floater = new LLFloater();
- buildFloater(floater, filename, open_floater);
- return floater;
+ popFileName();
+
+ return res;
}
//-----------------------------------------------------------------------------
@@ -267,14 +243,14 @@ S32 LLUICtrlFactory::saveToXML(LLView* viewp, const std::string& filename)
return 0;
}
-static LLFastTimer::DeclareTimer BUILD_PANELS("Build Panels");
+static LLFastTimer::DeclareTimer FTM_BUILD_PANELS("Build Panels");
//-----------------------------------------------------------------------------
// buildPanel()
//-----------------------------------------------------------------------------
BOOL LLUICtrlFactory::buildPanel(LLPanel* panelp, const std::string& filename, LLXMLNodePtr output_node)
{
- LLFastTimer timer(BUILD_PANELS);
+ LLFastTimer timer(FTM_BUILD_PANELS);
BOOL didPost = FALSE;
LLXMLNodePtr root;
@@ -303,7 +279,7 @@ BOOL LLUICtrlFactory::buildPanel(LLPanel* panelp, const std::string& filename, L
lldebugs << "Building panel " << filename << llendl;
- mFileNames.push_back(gDirUtilp->findSkinnedFilename(LLUI::getSkinPath(), filename));
+ pushFileName(filename);
{
if (!panelp->getFactoryMap().empty())
{
@@ -319,31 +295,28 @@ BOOL LLUICtrlFactory::buildPanel(LLPanel* panelp, const std::string& filename, L
panelp->getCommitCallbackRegistrar().popScope();
panelp->getEnableCallbackRegistrar().popScope();
- if (LLUI::sShowXUINames)
- {
- panelp->setToolTip(filename);
- }
+ panelp->setXMLFilename(filename);
if (!panelp->getFactoryMap().empty())
{
mFactoryStack.pop_front();
}
}
- mFileNames.pop_back();
+ popFileName();
return didPost;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
-LLFastTimer::DeclareTimer FTM_CREATE_FROM_XML("Create child widget");
+static LLFastTimer::DeclareTimer FTM_CREATE_FROM_XML("Create child widget");
-LLView *LLUICtrlFactory::createFromXML(LLXMLNodePtr node, LLView* parent, const std::string& filename, LLXMLNodePtr output_node, const widget_registry_t& registry)
+LLView *LLUICtrlFactory::createFromXML(LLXMLNodePtr node, LLView* parent, const std::string& filename, const widget_registry_t& registry, LLXMLNodePtr output_node)
{
LLFastTimer timer(FTM_CREATE_FROM_XML);
std::string ctrl_type = node->getName()->mString;
LLStringUtil::toLower(ctrl_type);
-
+
const LLWidgetCreatorFunc* funcp = registry.getValue(ctrl_type);
if (funcp == NULL)
{
@@ -360,10 +333,6 @@ LLView *LLUICtrlFactory::createFromXML(LLXMLNodePtr node, LLView* parent, const
parent = mDummyPanel;
}
LLView *view = (*funcp)(node, parent, output_node);
- if (LLUI::sShowXUINames && view && !filename.empty())
- {
- view->setToolTip(filename);
- }
return view;
}
@@ -391,6 +360,23 @@ LLPanel* LLUICtrlFactory::createFactoryPanel(const std::string& name)
return create<LLPanel>(panel_p);
}
+std::string LLUICtrlFactory::getCurFileName()
+{
+ return mFileNames.empty() ? "" : gDirUtilp->getWorkingDir() + gDirUtilp->getDirDelimiter() + mFileNames.back();
+}
+
+
+void LLUICtrlFactory::pushFileName(const std::string& name)
+{
+ mFileNames.push_back(gDirUtilp->findSkinnedFilename(LLUI::getSkinPath(), name));
+}
+
+void LLUICtrlFactory::popFileName()
+{
+ mFileNames.pop_back();
+}
+
+
//-----------------------------------------------------------------------------
//static
@@ -398,11 +384,11 @@ BOOL LLUICtrlFactory::getAttributeColor(LLXMLNodePtr node, const std::string& na
{
std::string colorstring;
BOOL res = node->getAttributeString(name.c_str(), colorstring);
- if (res && LLUI::sSettingGroups["color"])
+ if (res)
{
- if (LLUI::sSettingGroups["color"]->controlExists(colorstring))
+ if (LLUIColorTable::instance().colorExists(colorstring))
{
- color.setVec(LLUI::sSettingGroups["color"]->getColor(colorstring));
+ color.setVec(LLUIColorTable::instance().getColor(colorstring));
}
else
{
@@ -423,7 +409,7 @@ BOOL LLUICtrlFactory::getAttributeColor(LLXMLNodePtr node, const std::string& na
//static
void LLUICtrlFactory::setCtrlParent(LLView* view, LLView* parent, S32 tab_group)
{
- if (tab_group < 0) tab_group = parent->getLastTabGroup();
+ if (tab_group == S32_MAX) tab_group = parent->getLastTabGroup();
parent->addChild(view, tab_group);
}
@@ -448,647 +434,50 @@ void LLUICtrlFactory::popFactoryFunctions()
}
}
-const widget_registry_t& LLUICtrlFactory::getWidgetRegistry(LLView* viewp)
-{
- return viewp->getChildRegistry();
-}
-
-
-//
-// LLXUIParser
-//
-LLXUIParser::LLXUIParser()
-: mLastWriteGeneration(-1),
- mCurReadDepth(0)
-{
- registerParserFuncs<bool>(boost::bind(&LLXUIParser::readBoolValue, this, _1),
- boost::bind(&LLXUIParser::writeBoolValue, this, _1, _2));
- registerParserFuncs<std::string>(boost::bind(&LLXUIParser::readStringValue, this, _1),
- boost::bind(&LLXUIParser::writeStringValue, this, _1, _2));
- registerParserFuncs<U8>(boost::bind(&LLXUIParser::readU8Value, this, _1),
- boost::bind(&LLXUIParser::writeU8Value, this, _1, _2));
- registerParserFuncs<S8>(boost::bind(&LLXUIParser::readS8Value, this, _1),
- boost::bind(&LLXUIParser::writeS8Value, this, _1, _2));
- registerParserFuncs<U16>(boost::bind(&LLXUIParser::readU16Value, this, _1),
- boost::bind(&LLXUIParser::writeU16Value, this, _1, _2));
- registerParserFuncs<S16>(boost::bind(&LLXUIParser::readS16Value, this, _1),
- boost::bind(&LLXUIParser::writeS16Value, this, _1, _2));
- registerParserFuncs<U32>(boost::bind(&LLXUIParser::readU32Value, this, _1),
- boost::bind(&LLXUIParser::writeU32Value, this, _1, _2));
- registerParserFuncs<S32>(boost::bind(&LLXUIParser::readS32Value, this, _1),
- boost::bind(&LLXUIParser::writeS32Value, this, _1, _2));
- registerParserFuncs<F32>(boost::bind(&LLXUIParser::readF32Value, this, _1),
- boost::bind(&LLXUIParser::writeF32Value, this, _1, _2));
- registerParserFuncs<F64>(boost::bind(&LLXUIParser::readF64Value, this, _1),
- boost::bind(&LLXUIParser::writeF64Value, this, _1, _2));
- registerParserFuncs<LLColor4>(boost::bind(&LLXUIParser::readColor4Value, this, _1),
- boost::bind(&LLXUIParser::writeColor4Value, this, _1, _2));
- registerParserFuncs<LLUIColor>(boost::bind(&LLXUIParser::readUIColorValue, this, _1),
- boost::bind(&LLXUIParser::writeUIColorValue, this, _1, _2));
- registerParserFuncs<LLUUID>(boost::bind(&LLXUIParser::readUUIDValue, this, _1),
- boost::bind(&LLXUIParser::writeUUIDValue, this, _1, _2));
- registerParserFuncs<LLSD>(boost::bind(&LLXUIParser::readSDValue, this, _1),
- boost::bind(&LLXUIParser::writeSDValue, this, _1, _2));
-}
-
-static LLFastTimer::DeclareTimer PARSE_XUI("XUI Parsing");
-
-void LLXUIParser::readXUI(LLXMLNodePtr node, LLInitParam::BaseBlock& block, bool silent)
-{
- LLFastTimer timer(PARSE_XUI);
- mNameStack.clear();
- mCurReadDepth = 0;
- setParseSilently(silent);
-
- if (node.isNull())
- {
- parserWarning("Invalid node");
- }
- else
- {
- readXUIImpl(node, std::string(node->getName()->mString), block);
- }
-}
-
-void LLXUIParser::writeXUI(LLXMLNodePtr node, const LLInitParam::BaseBlock &block, const LLInitParam::BaseBlock* diff_block)
-{
- mLastWriteGeneration = -1;
- mWriteRootNode = node;
- block.serializeBlock(*this, Parser::name_stack_t(), diff_block);
-}
-
-// go from a stack of names to a specific XML node
-LLXMLNodePtr LLXUIParser::getNode(const name_stack_t& stack)
+//static
+void LLUICtrlFactory::copyName(LLXMLNodePtr src, LLXMLNodePtr dest)
{
- name_stack_t name_stack;
-
- for (name_stack_t::const_iterator it = stack.begin();
- it != stack.end();
- ++it)
- {
- if (!it->first.empty())
- {
- name_stack.push_back(*it);
- }
- }
-
- if (name_stack.empty() || mWriteRootNode.isNull()) return NULL;
-
- std::string attribute_name = name_stack.front().first;
-
- // heuristic to make font always attribute of parent node
- bool is_font = (attribute_name == "font");
- // XML spec says that attributes have their whitespace normalized
- // on parse: http://www.w3.org/TR/REC-xml/#AVNormalize
- // Therefore text-oriented widgets that might have carriage returns
- // have their values serialized as text contents, not the
- // initial_value attribute. JC
- if (attribute_name == "initial_value")
- {
- const char* root_node_name = mWriteRootNode->getName()->mString;
- if (!strcmp(root_node_name, "text") // LLTextBox
- || !strcmp(root_node_name, "text_editor")
- || !strcmp(root_node_name, "line_editor")) // for consistency
- {
- // writeStringValue will write to this node
- return mWriteRootNode;
- }
- }
-
- for (name_stack_t::const_iterator it = ++name_stack.begin();
- it != name_stack.end();
- ++it)
- {
- attribute_name += ".";
- attribute_name += it->first;
- }
-
- // *NOTE: <string> elements for translation need to have whitespace
- // preserved like "initial_value" above, however, the <string> node
- // becomes an attribute of the containing floater or panel.
- // Because all <string> elements must have a "name" attribute, and
- // "name" is parsed first, just put the value into the last written
- // child.
- if (attribute_name == "string.value")
- {
- // The caller of will shortly call writeStringValue(), which sets
- // this node's type to string, but we don't want to export type="string".
- // Set the default for this node to suppress the export.
- static LLXMLNodePtr default_node;
- if (default_node.isNull())
- {
- default_node = new LLXMLNode();
- // Force the node to have a string type
- default_node->setStringValue( std::string() );
- }
- mLastWrittenChild->setDefault(default_node);
- // mLastWrittenChild is the "string" node part of "string.value",
- // so the caller will call writeStringValue() into that node,
- // setting the node text contents.
- return mLastWrittenChild;
- }
-
- LLXMLNodePtr attribute_node;
-
- const char* attribute_cstr = attribute_name.c_str();
- if (name_stack.size() != 1
- && !is_font)
- {
- std::string child_node_name(mWriteRootNode->getName()->mString);
- child_node_name += ".";
- child_node_name += name_stack.front().first;
-
- LLXMLNodePtr child_node;
-
- if (mLastWriteGeneration == name_stack.front().second)
- {
- child_node = mLastWrittenChild;
- }
- else
- {
- mLastWriteGeneration = name_stack.front().second;
- child_node = mWriteRootNode->createChild(child_node_name.c_str(), false);
- }
-
- mLastWrittenChild = child_node;
-
- name_stack_t::const_iterator it = ++name_stack.begin();
- std::string short_attribute_name(it->first);
-
- for (++it;
- it != name_stack.end();
- ++it)
- {
- short_attribute_name += ".";
- short_attribute_name += it->first;
- }
-
- if (child_node->hasAttribute(short_attribute_name.c_str()))
- {
- llerrs << "Attribute " << short_attribute_name << " already exists!" << llendl;
- }
-
- attribute_node = child_node->createChild(short_attribute_name.c_str(), true);
- }
- else
- {
- if (mWriteRootNode->hasAttribute(attribute_cstr))
- {
- mWriteRootNode->getAttribute(attribute_cstr, attribute_node);
- }
- else
- {
- attribute_node = mWriteRootNode->createChild(attribute_name.c_str(), true);
- }
- }
-
- return attribute_node;
+ dest->setName(src->getName()->mString);
}
-
-bool LLXUIParser::readXUIImpl(LLXMLNodePtr nodep, const std::string& scope, LLInitParam::BaseBlock& block)
+// adds a widget and its param block to various registries
+//static
+void LLUICtrlFactory::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)
{
- typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
- boost::char_separator<char> sep(".");
-
- bool values_parsed = false;
-
- // submit attributes for current node
- values_parsed |= readAttributes(nodep, block);
-
- // treat text contents of xml node as "value" parameter
- std::string text_contents = nodep->getSanitizedValue();
- if (!text_contents.empty())
+ // associate parameter block type with template .xml file
+ std::string* existing_tag = LLWidgetNameRegistry::instance().getValue(param_block_type);
+ if (existing_tag != NULL)
{
- mCurReadNode = nodep;
- mNameStack.push_back(std::make_pair(std::string("value"), newParseGeneration()));
- // child nodes are not necessarily valid parameters (could be a child widget)
- // so don't complain once we've recursed
- bool silent = mCurReadDepth > 0;
- block.submitValue(mNameStack, *this, silent);
- mNameStack.pop_back();
- }
-
- // then traverse children
- // child node must start with last name of parent node (our "scope")
- // for example: "<button><button.param nested_param1="foo"><param.nested_param2 nested_param3="bar"/></button.param></button>"
- // which equates to the following nesting:
- // button
- // param
- // nested_param1
- // nested_param2
- // nested_param3
- mCurReadDepth++;
- for(LLXMLNodePtr childp = nodep->getFirstChild(); childp.notNull();)
- {
- std::string child_name(childp->getName()->mString);
- S32 num_tokens_pushed = 0;
-
- // for non "dotted" child nodes check to see if child node maps to another widget type
- // and if not, treat as a child element of the current node
- // e.g. <button><rect left="10"/></button> will interpret <rect> as "button.rect"
- // since there is no widget named "rect"
- if (child_name.find(".") == std::string::npos)
- {
- mNameStack.push_back(std::make_pair(child_name, newParseGeneration()));
- num_tokens_pushed++;
- }
- else
- {
- // parse out "dotted" name into individual tokens
- tokenizer name_tokens(child_name, sep);
-
- tokenizer::iterator name_token_it = name_tokens.begin();
- if(name_token_it == name_tokens.end())
- {
- childp = childp->getNextSibling();
- continue;
- }
-
- // check for proper nesting
- if(!scope.empty() && *name_token_it != scope)
- {
- childp = childp->getNextSibling();
- continue;
- }
-
- // now ignore first token
- ++name_token_it;
-
- // copy remaining tokens on to our running token list
- for(tokenizer::iterator token_to_push = name_token_it; token_to_push != name_tokens.end(); ++token_to_push)
- {
- mNameStack.push_back(std::make_pair(*token_to_push, newParseGeneration()));
- num_tokens_pushed++;
- }
- }
-
- // recurse and visit children XML nodes
- if(readXUIImpl(childp, mNameStack.empty() ? scope : mNameStack.back().first, block))
+ if(*existing_tag != tag)
{
- // child node successfully parsed, remove from DOM
-
- values_parsed = true;
- LLXMLNodePtr node_to_remove = childp;
- childp = childp->getNextSibling();
-
- nodep->deleteChild(node_to_remove);
+ std::cerr << "Duplicate entry for T::Params, try creating empty param block in derived classes that inherit T::Params" << std::endl;
+ // forcing crash here
+ char* foo = 0;
+ *foo = 1;
}
else
{
- childp = childp->getNextSibling();
- }
-
- while(num_tokens_pushed-- > 0)
- {
- mNameStack.pop_back();
- }
- }
- mCurReadDepth--;
- return values_parsed;
-}
-
-bool LLXUIParser::readAttributes(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block)
-{
- typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
- boost::char_separator<char> sep(".");
-
- bool any_parsed = false;
-
- for(LLXMLAttribList::const_iterator attribute_it = nodep->mAttributes.begin();
- attribute_it != nodep->mAttributes.end();
- ++attribute_it)
- {
- S32 num_tokens_pushed = 0;
- std::string attribute_name(attribute_it->first->mString);
- mCurReadNode = attribute_it->second;
-
- tokenizer name_tokens(attribute_name, sep);
- // copy remaining tokens on to our running token list
- for(tokenizer::iterator token_to_push = name_tokens.begin(); token_to_push != name_tokens.end(); ++token_to_push)
- {
- mNameStack.push_back(std::make_pair(*token_to_push, newParseGeneration()));
- num_tokens_pushed++;
- }
-
- // child nodes are not necessarily valid attributes, so don't complain once we've recursed
- bool silent = mCurReadDepth > 0;
- any_parsed |= block.submitValue(mNameStack, *this, silent);
-
- while(num_tokens_pushed-- > 0)
- {
- mNameStack.pop_back();
+ // widget already registered
+ return;
}
}
-
- return any_parsed;
-}
-
-bool LLXUIParser::readBoolValue(void* val_ptr)
-{
- S32 value;
- bool success = mCurReadNode->getBoolValue(1, &value);
- *((bool*)val_ptr) = (value != FALSE);
- return success;
-}
-
-bool LLXUIParser::writeBoolValue(const void* val_ptr, const name_stack_t& stack)
-{
- LLXMLNodePtr node = getNode(stack);
- if (node.notNull())
- {
- node->setBoolValue(*((bool*)val_ptr));
- return true;
- }
- return false;
-}
-
-bool LLXUIParser::readStringValue(void* val_ptr)
-{
- *((std::string*)val_ptr) = mCurReadNode->getSanitizedValue();
- return true;
-}
-
-bool LLXUIParser::writeStringValue(const void* val_ptr, const name_stack_t& stack)
-{
- LLXMLNodePtr node = getNode(stack);
- if (node.notNull())
- {
- node->setStringValue(*((std::string*)val_ptr));
- return true;
- }
- return false;
-}
-
-bool LLXUIParser::readU8Value(void* val_ptr)
-{
- return mCurReadNode->getByteValue(1, (U8*)val_ptr);
-}
-
-bool LLXUIParser::writeU8Value(const void* val_ptr, const name_stack_t& stack)
-{
- LLXMLNodePtr node = getNode(stack);
- if (node.notNull())
- {
- node->setUnsignedValue(*((U8*)val_ptr));
- return true;
- }
- return false;
-}
-
-bool LLXUIParser::readS8Value(void* val_ptr)
-{
- S32 value;
- if(mCurReadNode->getIntValue(1, &value))
- {
- *((S8*)val_ptr) = value;
- return true;
- }
- return false;
-}
-
-bool LLXUIParser::writeS8Value(const void* val_ptr, const name_stack_t& stack)
-{
- LLXMLNodePtr node = getNode(stack);
- if (node.notNull())
- {
- node->setIntValue(*((S8*)val_ptr));
- return true;
- }
- return false;
-}
-
-bool LLXUIParser::readU16Value(void* val_ptr)
-{
- U32 value;
- if(mCurReadNode->getUnsignedValue(1, &value))
- {
- *((U16*)val_ptr) = value;
- return true;
- }
- return false;
-}
-
-bool LLXUIParser::writeU16Value(const void* val_ptr, const name_stack_t& stack)
-{
- LLXMLNodePtr node = getNode(stack);
- if (node.notNull())
- {
- node->setUnsignedValue(*((U16*)val_ptr));
- return true;
- }
- return false;
-}
-
-bool LLXUIParser::readS16Value(void* val_ptr)
-{
- S32 value;
- if(mCurReadNode->getIntValue(1, &value))
- {
- *((S16*)val_ptr) = value;
- return true;
- }
- return false;
-}
-
-bool LLXUIParser::writeS16Value(const void* val_ptr, const name_stack_t& stack)
-{
- LLXMLNodePtr node = getNode(stack);
- if (node.notNull())
- {
- node->setIntValue(*((S16*)val_ptr));
- return true;
- }
- return false;
-}
-
-bool LLXUIParser::readU32Value(void* val_ptr)
-{
- return mCurReadNode->getUnsignedValue(1, (U32*)val_ptr);
-}
-
-bool LLXUIParser::writeU32Value(const void* val_ptr, const name_stack_t& stack)
-{
- LLXMLNodePtr node = getNode(stack);
- if (node.notNull())
- {
- node->setUnsignedValue(*((U32*)val_ptr));
- return true;
- }
- return false;
-}
-
-bool LLXUIParser::readS32Value(void* val_ptr)
-{
- return mCurReadNode->getIntValue(1, (S32*)val_ptr);
-}
-
-bool LLXUIParser::writeS32Value(const void* val_ptr, const name_stack_t& stack)
-{
- LLXMLNodePtr node = getNode(stack);
- if (node.notNull())
- {
- node->setIntValue(*((S32*)val_ptr));
- return true;
- }
- return false;
-}
-
-bool LLXUIParser::readF32Value(void* val_ptr)
-{
- return mCurReadNode->getFloatValue(1, (F32*)val_ptr);
-}
-
-bool LLXUIParser::writeF32Value(const void* val_ptr, const name_stack_t& stack)
-{
- LLXMLNodePtr node = getNode(stack);
- if (node.notNull())
- {
- node->setFloatValue(*((F32*)val_ptr));
- return true;
- }
- return false;
+ LLWidgetNameRegistry::instance().defaultRegistrar().add(param_block_type, tag);
+ // associate widget type with factory function
+ LLDefaultWidgetRegistry::instance().defaultRegistrar().add(widget_type, creator_func);
+ //FIXME: comment this in when working on schema generation
+ //LLWidgetTypeRegistry::instance().defaultRegistrar().add(tag, widget_type);
+ //LLDefaultParamBlockRegistry::instance().defaultRegistrar().add(widget_type, &getEmptyParamBlock<T>);
}
-bool LLXUIParser::readF64Value(void* val_ptr)
-{
- return mCurReadNode->getDoubleValue(1, (F64*)val_ptr);
-}
-
-bool LLXUIParser::writeF64Value(const void* val_ptr, const name_stack_t& stack)
-{
- LLXMLNodePtr node = getNode(stack);
- if (node.notNull())
- {
- node->setDoubleValue(*((F64*)val_ptr));
- return true;
- }
- return false;
-}
-
-bool LLXUIParser::readColor4Value(void* val_ptr)
-{
- LLColor4* colorp = (LLColor4*)val_ptr;
- if(mCurReadNode->getFloatValue(4, colorp->mV) >= 3)
- {
- return true;
- }
-
- return false;
-}
-
-bool LLXUIParser::writeColor4Value(const void* val_ptr, const name_stack_t& stack)
-{
- LLXMLNodePtr node = getNode(stack);
- if (node.notNull())
- {
- LLColor4 color = *((LLColor4*)val_ptr);
- node->setFloatValue(4, color.mV);
- return true;
- }
- return false;
-}
-
-bool LLXUIParser::readUIColorValue(void* val_ptr)
-{
- LLUIColor* param = (LLUIColor*)val_ptr;
- LLColor4 color;
- bool success = mCurReadNode->getFloatValue(4, color.mV) >= 3;
- if (success)
- {
- param->set(color);
- return true;
- }
- return false;
-}
-
-bool LLXUIParser::writeUIColorValue(const void* val_ptr, const name_stack_t& stack)
-{
- LLXMLNodePtr node = getNode(stack);
- if (node.notNull())
- {
- LLUIColor color = *((LLUIColor*)val_ptr);
- //RN: don't write out the color that is represented by a function
- // rely on param block exporting to get the reference to the color settings
- if (color.isUsingFunction()) return false;
- node->setFloatValue(4, color.get().mV);
- return true;
- }
- return false;
-}
-
-bool LLXUIParser::readUUIDValue(void* val_ptr)
-{
- LLUUID temp_id;
- // LLUUID::set is destructive, so use temporary value
- if (temp_id.set(mCurReadNode->getSanitizedValue()))
- {
- *(LLUUID*)(val_ptr) = temp_id;
- return true;
- }
- return false;
-}
-
-bool LLXUIParser::writeUUIDValue(const void* val_ptr, const name_stack_t& stack)
-{
- LLXMLNodePtr node = getNode(stack);
- if (node.notNull())
- {
- node->setStringValue(((LLUUID*)val_ptr)->asString());
- return true;
- }
- return false;
-}
-
-bool LLXUIParser::readSDValue(void* val_ptr)
-{
- *((LLSD*)val_ptr) = LLSD(mCurReadNode->getSanitizedValue());
- return true;
-}
-
-bool LLXUIParser::writeSDValue(const void* val_ptr, const name_stack_t& stack)
-{
- LLXMLNodePtr node = getNode(stack);
- if (node.notNull())
- {
- node->setStringValue(((LLSD*)val_ptr)->asString());
- return true;
- }
- return false;
-}
-
-/*virtual*/ std::string LLXUIParser::getCurrentElementName()
+//static
+dummy_widget_creator_func_t* LLUICtrlFactory::getDefaultWidgetFunc(const std::type_info* widget_type)
{
- std::string full_name;
- for (name_stack_t::iterator it = mNameStack.begin();
- it != mNameStack.end();
- ++it)
- {
- full_name += it->first + "."; // build up dotted names: "button.param.nestedparam."
- }
-
- return full_name;
+ return LLDefaultWidgetRegistry::instance().getValue(widget_type);
}
-void LLXUIParser::parserWarning(const std::string& message)
+//static
+const std::string* LLUICtrlFactory::getWidgetTag(const std::type_info* widget_type)
{
-#ifdef LL_WINDOWS
- // use Visual Studo friendly formatting of output message for easy access to originating xml
- llutf16string utf16str = utf8str_to_utf16str(llformat("%s(%d):\t%s", LLUICtrlFactory::getInstance()->getCurFileName().c_str(), mCurReadNode->getLineNumber(), message.c_str()).c_str());
- utf16str += '\n';
- OutputDebugString(utf16str.c_str());
-#else
- Parser::parserWarning(message);
-#endif
+ return LLWidgetNameRegistry::instance().getValue(widget_type);
}
-void LLXUIParser::parserError(const std::string& message)
-{
-#ifdef LL_WINDOWS
- llutf16string utf16str = utf8str_to_utf16str(llformat("%s(%d):\t%s", LLUICtrlFactory::getInstance()->getCurFileName().c_str(), mCurReadNode->getLineNumber(), message.c_str()).c_str());
- utf16str += '\n';
- OutputDebugString(utf16str.c_str());
-#else
- Parser::parserError(message);
-#endif
-}