From e97ec6788ec4354a168404e45f8850130118510b Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 9 Jul 2012 03:45:00 +0200 Subject: [PATCH] CHANGED: #1471 CInterfaceParser is now part of the Nel GUI library and is under the NLGUI namespace. --- code/nel/include/nel/gui/interface_parser.h | 355 ++ code/nel/src/gui/interface_parser.cpp | 2885 ++++++++++++++++ code/ryzom/client/src/actions.h | 2 - .../src/interface_v3/interface_manager.h | 4 +- .../src/interface_v3/interface_parser.cpp | 2919 ----------------- .../src/interface_v3/interface_parser.h | 356 -- .../client/src/interface_v3/parser_modules.h | 4 +- 7 files changed, 3245 insertions(+), 3280 deletions(-) create mode 100644 code/nel/include/nel/gui/interface_parser.h create mode 100644 code/nel/src/gui/interface_parser.cpp delete mode 100644 code/ryzom/client/src/interface_v3/interface_parser.cpp delete mode 100644 code/ryzom/client/src/interface_v3/interface_parser.h diff --git a/code/nel/include/nel/gui/interface_parser.h b/code/nel/include/nel/gui/interface_parser.h new file mode 100644 index 000000000..2ddc359cd --- /dev/null +++ b/code/nel/include/nel/gui/interface_parser.h @@ -0,0 +1,355 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + + +#ifndef RZ_INTERFACE_PARSER_H +#define RZ_INTERFACE_PARSER_H + +#include "nel/misc/types_nl.h" +#include "nel/3d/u_texture.h" +#include "nel/gui/ctrl_sheet_selection.h" +#include "nel/gui/interface_link.h" +#include "nel/misc/smart_ptr.h" +#include "nel/gui/lua_helper.h" +#include "nel/gui/widget_manager.h" + +namespace NLGUI +{ + class CInterfaceElement; + class CInterfaceGroup; + class CInterfaceOptions; + class CInterfaceLink; + class CCtrlBase; + class CGroupList; + class CGroupContainer; + class CInterfaceAnim; + class CViewPointer; + + // *************************************************************************** + /** + * class managing the interface parsing + * \author Matthieu 'TrapII' Besson + * \author Nevrax France + * \date 2002 + */ + + // this is the base class for CInterfaceManager + class CInterfaceParser : public IParser + { + + public: + + class IParserModule + { + public: + enum ParsingStage + { + None = 0, + Unresolved = 1, + Resolved = 2, + GroupChildren = 4 + }; + + IParserModule(){ + parser = NULL; + parsingStage = None; + } + virtual ~IParserModule(){} + + bool canParseInStage( ParsingStage stage ) + { + if( ( parsingStage & static_cast< uint >( stage ) ) != 0 ) + return true; + else + return false; + } + + virtual bool parse( xmlNodePtr cur, CInterfaceGroup *parentGroup ) = 0; + void setParser( CInterfaceParser *p ){ parser = p; } + + protected: + CInterfaceParser *parser; + uint parsingStage; + }; + + CInterfaceParser(); + virtual ~CInterfaceParser(); + + public: + + /** + * Parsing methods + */ + + /** Load a set of xml files + * \param isFilename true if xmlFileNames array contains the names of the xml file, false, if each + * array is a script itself + */ + bool parseInterface (const std::vector &xmlFileNames, bool reload, bool isFilename = true, bool checkInData = false); + + bool parseXMLDocument (xmlNodePtr root, bool reload); + bool parseTemplateNode (xmlNodePtr node,xmlNodePtr instance,xmlNodePtr templ); + bool parseInstance(xmlNodePtr cur); + bool parseVector (xmlNodePtr cur); + bool parseVariable (xmlNodePtr cur, CInterfaceGroup * parentGroup); + bool parseOptions (xmlNodePtr cur, CInterfaceGroup * parentGroup); + bool parseGroup (xmlNodePtr cur, CInterfaceGroup * parentGroup, bool reload); + bool parseGroupChildren(xmlNodePtr cur, CInterfaceGroup * parentGroup, bool reload); + bool parseControl (xmlNodePtr cur, CInterfaceGroup * parentGroup, bool reload); + bool parseLink (xmlNodePtr cur, CInterfaceGroup * parentGroup); + bool parseView (xmlNodePtr cur, CInterfaceGroup * parentGroup, bool reload); + bool parseTreeNode (xmlNodePtr cur, CGroupContainer *parentGroup); + bool parseTree (xmlNodePtr cur, CWidgetManager::SMasterGroup *parentGroup); + bool parseDefine(xmlNodePtr cur); + bool parseProcedure(xmlNodePtr cur, bool reload); + bool parseSheetSelection(xmlNodePtr cur); + bool parseAnim(xmlNodePtr cur, CInterfaceGroup * parentGroup); + bool parseStyle(xmlNodePtr cur); + bool parseLUAScript (xmlNodePtr cur); + bool setupTree (xmlNodePtr cur, CWidgetManager::SMasterGroup *parentGroup); + bool setupTreeNode (xmlNodePtr cur, CGroupContainer *parentGroup); + + void addModule( std::string name, IParserModule *module ); + IParserModule* getModuleFor( std::string name ) const; + void removeAllModules(); + + // Called by each parse in parseXMLDocument + bool solveDefine(xmlNodePtr cur); + bool solveStyle(xmlNodePtr cur); + + // Solve All define in a string. return false if some define not founs (defError contains this define) + bool solveDefine(const std::string &propVal, std::string &newPropVal, std::string &defError); + + // Called after template & options parsing + virtual void setupOptions() { } + + /** + * Initializer + */ + + bool initCoordsAndLuaScript (); + + /// Association builders : associate an element of the interface with the string ID of + /// another element used as reference for position values + void addParentPositionAssociation (CInterfaceElement *element, const std::string &parentID); + void addParentSizeAssociation (CInterfaceElement *element, const std::string &parentID); + void addParentSizeMaxAssociation (CInterfaceElement *element, const std::string &parentID); + + /// LUA Class Association builder : associate a lua script to a group (called for each group after every document parsed) + void addLuaClassAssociation(CInterfaceGroup *group, const std::string &luaScript); + + /** + * Accessors + */ + // access to control sheet selection + CCtrlSheetSelection &getCtrlSheetSelection() { return _CtrlSheetSelection; } + + /// \name Parameter variable + // @{ + const std::string &getDefine(const std::string &id) const; + bool isDefineExist(const std::string &id) const; + void setDefine(const std::string &id, const std::string &value); + // @} + + /// \name Dynamic links mgt + // @{ + /** Associate the given dynamic link with an ID + * \return true if succesful + */ + bool addLink(CInterfaceLink *link, const std::string &id); + /** remove the given link from its ID + * \return true if succesful + */ + bool removeLink(const std::string &id); + // @} + + /** create a template from an instance consisting of a single group + * \param templateName name of the template in the xml + * \param templateParams array containing each template parameter and its name + * \param number of template parameters in the array + */ + CInterfaceGroup *createGroupInstance(const std::string &templateName, const std::string &parentID, const std::pair *templateParams, uint numParams, bool updateLinks = true); + CInterfaceGroup *createGroupInstance(const std::string &templateName, const std::string &parentID, std::vector > &templateParams, bool updateLinks = true) + { + if (templateParams.size() > 0) + return createGroupInstance(templateName, parentID, &templateParams[0], (uint)templateParams.size(), updateLinks); + else + return createGroupInstance(templateName, parentID, NULL, 0, updateLinks); + } + + /** create a template from an instance consisting of a single control or group + * \param templateName name of the template in the xml + * \param templateParams array containing each template parameter and its name + * \param number of template parameters in the array + */ + CInterfaceElement *createUIElement(const std::string &templateName, const std::string &parentID, const std::pair *templateParams, uint numParams, bool updateLinks /* = true */); + CInterfaceElement *createUIElement(const std::string &templateName, const std::string &parentID, std::vector > &templateParams, bool updateLinks = true) + { + if (templateParams.size() > 0) + return createUIElement(templateName, parentID, &templateParams[0], (uint)templateParams.size(), updateLinks); + else + return createUIElement(templateName, parentID, NULL, 0, updateLinks); + } + + static void freeXMLNodeAndSibblings(xmlNodePtr node); + + // search a "tree" node in the hierarchy that match node. may return root! NULL if not found + static xmlNodePtr searchTreeNodeInHierarchy(xmlNodePtr root, const char *node); + + /// \name Clearing mgt + // @{ + void removeAllLinks(); + void removeAllProcedures(); + void removeAllDefines(); + void removeAllTemplates(); + void removeAllAnims(); + void removeAll(); + // @} + + // get info on procedure. return 0 if procedure not found + uint getProcedureNumActions( const std::string &procName ) const; + + // return false if procedure not found, or if bad action index. return false if has some param variable (@0...) + bool getProcedureAction( const std::string &procName, uint actionIndex, std::string &ah, std::string ¶ms ) const; + + void setCacheUIParsing( bool b ){ cacheUIParsing = b; } + + protected: + + /** + * Temporary data for init + */ + + /// vector storing parsed templates during init. At the end of init, only used template are kept + std::vector _Templates; + + + // map linking an element to its parent position used during init only + std::map _ParentPositionsMap; + std::map _ParentSizesMap; + std::map _ParentSizesMaxMap; + + // map linking a group to its lua script. used during init only + std::map _LuaClassAssociation; + + /** + * Data of initialized interface + */ + + /// Define Variable list + typedef std::map TVarMap; + typedef TVarMap::iterator ItVarMap; + typedef TVarMap::const_iterator CstItVarMap; + TVarMap _DefineMap; + + bool validDefineChar(char c) const; + + /// Procedure def + class CParamBlock + { + public: + // -1 if not a param id, but a string + sint32 NumParam; + std::string String; + + CParamBlock() + { + NumParam= -1; + } + }; + class CAction + { + public: + // a condition to launch this action handler (is an expression) + std::vector CondBlocks; + + // the action handler (may be proc!!) + std::string Action; + // A list of string/or param number => to build the final params at execution + std::vector ParamBlocks; + + // build a paramBlock from a string + void buildParamBlock (const std::string ¶ms); + // from ParamBlock, and a paramList (skip the 0th), build params. + void buildParams (const std::vector ¶mList, std::string ¶ms) const; + + void buildCondBlock (const std::string ¶ms); + + void buildCond (const std::vector ¶mList, std::string &cond) const; + + static void buildBlocks (const std::string &in, std::vector &out); + static void eval (const std::vector &inArgs, const std::vector &inBlocks, std::string &out); + + }; + class CProcedure + { + public: + // List of the actions + std::vector Actions; + }; + class CStyleProperty + { + public: + std::string Name; + std::string Value; + }; + class CStyle + { + public: + std::vector Properties; + }; + + + /// Procedure list + typedef std::map TProcedureMap; + typedef TProcedureMap::iterator ItProcedureMap; + typedef TProcedureMap::const_iterator CstItProcedureMap; + TProcedureMap _ProcedureMap; + + // mgt of sheet selections (inventory, buy, sell..) + CCtrlSheetSelection _CtrlSheetSelection; + + // Map of dynamic links + typedef std::map > TLinkMap; + TLinkMap _LinkMap; + + // Map of anims + typedef std::map TAnimMap; + TAnimMap _AnimMap; + + // Map of styles. + typedef std::map TStyleMap; + TStyleMap _StyleMap; + + protected: + std::map< std::string, IParserModule* > moduleMap; + // LUA + // ---------------------------------------------------------------------------------- + // LUA Interface State. NB: The LUA environnement is not shared between Login/OutGame/InGame + NLMISC::CSmartPtr _LuaState; + virtual void initLUA(); + void uninitLUA(); + // List of script loaded (for reloadLua command) + std::set _LuaFileScripts; + // Load A .lua. false if parse error. string 'error' contains the eventual error desc (but warning still displayed) + bool loadLUA(const std::string &luaFile, std::string &error); + bool cacheUIParsing; + }; + +} + +#endif // RZ_INTERFACE_PARSER_H diff --git a/code/nel/src/gui/interface_parser.cpp b/code/nel/src/gui/interface_parser.cpp new file mode 100644 index 000000000..22705fd64 --- /dev/null +++ b/code/nel/src/gui/interface_parser.cpp @@ -0,0 +1,2885 @@ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program 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 Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include +#include "nel/misc/rgba.h" +#include "nel/gui/interface_parser.h" +#include "nel/misc/i_xml.h" +#include "nel/misc/file.h" +#include "nel/misc/algo.h" +#include "nel/misc/mem_stream.h" +#include "nel/misc/factory.h" +#include "nel/misc/big_file.h" +#include "nel/misc/xml_auto_ptr.h" +#include "nel/gui/interface_options.h" +#include "nel/gui/interface_anim.h" +#include "nel/gui/interface_expr.h" +#include "nel/gui/view_pointer.h" +#include "nel/gui/group_modal.h" +#include "nel/gui/group_list.h" +#include "nel/gui/group_container.h" +#include "nel/gui/interface_link.h" +#include "nel/gui/lua_helper.h" +#include "nel/gui/lua_ihm.h" +#include "nel/gui/lua_manager.h" + +#ifdef LUA_NEVRAX_VERSION + #include "lua_ide_dll_nevrax/include/lua_ide_dll/ide_interface.h" // external debugger +#endif +const uint32 UI_CACHE_SERIAL_CHECK = (uint32) 'IUG_'; + +using namespace NLMISC; +using namespace std; + +namespace NLGUI +{ + + void saveXMLTree(COFile &f, xmlNodePtr node) + { + // save node name + std::string name = (const char *) node->name; + f.serial(name); + // save properties + uint32 numProp = 0; + xmlAttrPtr currProp = node->properties; + while (currProp) + { + ++ numProp; + currProp = currProp->next; + } + f.serial(numProp); + currProp = node->properties; + while (currProp) + { + std::string name = (const char *) currProp->name; + f.serial(name); + CXMLAutoPtr ptr(xmlGetProp(node, currProp->name)); + std::string value = (const char *) ptr; + f.serial(value); + currProp = currProp->next; + } + uint32 numChildren = 0; + xmlNodePtr currChild = node->children; + while (currChild) + { + ++ numChildren; + currChild = currChild->next; + } + f.serial(numChildren); + currChild = node->children; + while (currChild) + { + saveXMLTree(f, currChild); + currChild = currChild->next; + } + } + + xmlNodePtr buildTree(CIFile &f) + { + // load node name + std::string name; + f.serial(name); + xmlNodePtr node = xmlNewNode(NULL, (const xmlChar *) name.c_str()); + // slod properties + uint32 numProp; + f.serial(numProp); + for(uint k = 0; k < numProp; ++k) + { + std::string name, value; + f.serial(name, value); + xmlSetProp(node, (const xmlChar *) name.c_str(), (const xmlChar *) value.c_str()); + } + uint32 numChildren; + f.serial(numChildren); + for(uint k = 0; k < numChildren; ++k) + { + xmlAddChild(node, buildTree(f)); + } + return node; + } + + + + // ---------------------------------------------------------------------------- + // CRootGroup + // ---------------------------------------------------------------------------- + + class CRootGroup : public CInterfaceGroup + { + public: + CRootGroup(const TCtorParam ¶m) + : CInterfaceGroup(param) + { } + + /// Destructor + virtual ~CRootGroup() { } + + virtual CInterfaceElement* getElement (const std::string &id) + { + if (_Id == id) + return this; + + if (id.substr(0, _Id.size()) != _Id) + return NULL; + + vector::const_iterator itv; + for (itv = _Views.begin(); itv != _Views.end(); itv++) + { + CViewBase *pVB = *itv; + if (pVB->getId() == id) + return pVB; + } + + vector::const_iterator itc; + for (itc = _Controls.begin(); itc != _Controls.end(); itc++) + { + CCtrlBase* ctrl = *itc; + if (ctrl->getId() == id) + return ctrl; + } + + // Accelerate + string sTmp = id; + sTmp = sTmp.substr(_Id.size()+1,sTmp.size()); + string::size_type pos = sTmp.find(':'); + if (pos != string::npos) + sTmp = sTmp.substr(0,pos); + + map::iterator it = _Accel.find(sTmp); + if (it != _Accel.end()) + { + CInterfaceGroup *pIG = it->second; + return pIG->getElement(id); + } + return NULL; + } + + virtual void addGroup (CInterfaceGroup *child, sint eltOrder = -1) + { + string sTmp = child->getId(); + sTmp = sTmp.substr(_Id.size()+1,sTmp.size()); + _Accel.insert(pair(sTmp, child)); + CInterfaceGroup::addGroup(child,eltOrder); + } + + virtual bool delGroup (CInterfaceGroup *child, bool dontDelete = false) + { + string sTmp = child->getId(); + sTmp = sTmp.substr(_Id.size()+1,sTmp.size()); + map::iterator it = _Accel.find(sTmp); + if (it != _Accel.end()) + { + _Accel.erase(it); + } + return CInterfaceGroup::delGroup(child,dontDelete); + } + + private: + map _Accel; + }; + + // ---------------------------------------------------------------------------- + // CInterfaceParser + // ---------------------------------------------------------------------------- + + // ---------------------------------------------------------------------------- + CInterfaceParser::CInterfaceParser() + { + // LUA + _LuaState= NULL; + cacheUIParsing = false; + } + + CInterfaceParser::~CInterfaceParser() + { + _LuaState = NULL; + removeAllModules(); + } + /** Convert a string into a memstream + */ + static void interfaceScriptAsMemStream(const std::string &script, CMemStream &destStream) + { + NLMISC::contReset(destStream); + if (destStream.isReading()) // we must be sure that we are reading the stream + { + destStream.invert(); + } + destStream.seek(0, NLMISC::IStream::begin); + if (script.empty()) return; + destStream.serialBuffer(const_cast((const uint8 *) &script[0]), (uint)script.size()); + destStream.invert(); + destStream.seek(0, NLMISC::IStream::begin); + } + + // ---------------------------------------------------------------------------- + bool CInterfaceParser::parseInterface (const std::vector & strings, bool reload, bool isFilename, bool checkInData) + { + bool ok; + + bool needCheck = false; + + #if !FINAL_VERSION + needCheck = false; + #endif + + // TestYoyo. UnHide For Parsing Profile + /* + NLMISC::CHTimer::startBench(); + { + + H_AUTO(parseInterface); + */ + + //ignore the content of tags containing only white space + xmlKeepBlanksDefault(0); + //parse all interface files and build a single xml document + xmlNodePtr globalEnclosing; + nlassert (strings.size()); + CIXml read; + string nextFileName; + static const char *SCRIPT_AS_STRING = "