lluictrlfactory.cpp

Go to the documentation of this file.
00001 
00032 #include "linden_common.h"
00033 
00034 #include "lluictrlfactory.h"
00035 
00036 #include <fstream>
00037 #include <boost/tokenizer.hpp>
00038 
00039 // other library includes
00040 #include "llcontrol.h"
00041 #include "lldir.h"
00042 #include "v4color.h"
00043 
00044 // this library includes
00045 #include "llbutton.h"
00046 #include "llcheckboxctrl.h"
00047 //#include "llcolorswatch.h"
00048 #include "llcombobox.h"
00049 #include "llcontrol.h"
00050 #include "lldir.h"
00051 #include "llevent.h"
00052 #include "llfloater.h"
00053 #include "lliconctrl.h"
00054 #include "lllineeditor.h"
00055 #include "llmenugl.h"
00056 #include "llradiogroup.h"
00057 #include "llscrollcontainer.h"
00058 #include "llscrollingpanellist.h"
00059 #include "llscrolllistctrl.h"
00060 #include "llslider.h"
00061 #include "llsliderctrl.h"
00062 #include "llmultislider.h"
00063 #include "llmultisliderctrl.h"
00064 #include "llspinctrl.h"
00065 #include "lltabcontainer.h"
00066 #include "lltabcontainervertical.h"
00067 #include "lltextbox.h"
00068 #include "lltexteditor.h"
00069 #include "llui.h"
00070 #include "llviewborder.h"
00071 
00072 const char XML_HEADER[] = "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>\n";
00073 
00074 const S32 HPAD = 4;
00075 const S32 VPAD = 4;
00076 const S32 FLOATER_H_MARGIN = 15;
00077 const S32 MIN_WIDGET_HEIGHT = 10;
00078 
00079 std::vector<LLString> LLUICtrlFactory::mXUIPaths;
00080 
00081 // UI Ctrl class for padding
00082 class LLUICtrlLocate : public LLUICtrl
00083 {
00084 public:
00085         LLUICtrlLocate() : LLUICtrl("locate", LLRect(0,0,0,0), FALSE, NULL, NULL) { setTabStop(FALSE); }
00086         virtual void draw() { }
00087 
00088         static LLView *fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
00089         {
00090                 LLString name("pad");
00091                 node->getAttributeString("name", name);
00092 
00093                 LLUICtrlLocate *new_ctrl = new LLUICtrlLocate();
00094                 new_ctrl->setName(name);
00095                 new_ctrl->initFromXML(node, parent);
00096                 return new_ctrl;
00097         }
00098 };
00099 
00100 static LLRegisterWidget<LLUICtrlLocate> r1("locate");
00101 static LLRegisterWidget<LLUICtrlLocate> r2("pad");
00102 
00103 //-----------------------------------------------------------------------------
00104 // LLUICtrlFactory()
00105 //-----------------------------------------------------------------------------
00106 LLUICtrlFactory::LLUICtrlFactory()
00107         : mDummyPanel(NULL)
00108 {
00109         setupPaths();
00110 }
00111 
00112 LLUICtrlFactory::~LLUICtrlFactory()
00113 {
00114         delete mDummyPanel;
00115         mDummyPanel = NULL;
00116 }
00117 
00118 void LLUICtrlFactory::setupPaths()
00119 {
00120         LLString filename = gDirUtilp->getExpandedFilename(LL_PATH_SKINS, "paths.xml");
00121 
00122         LLXMLNodePtr root;
00123         BOOL success  = LLXMLNode::parseFile(filename, root, NULL);
00124         mXUIPaths.clear();
00125         
00126         if (success)
00127         {
00128                 LLXMLNodePtr path;
00129                 LLString app_dir = gDirUtilp->getAppRODataDir();
00130         
00131                 for (path = root->getFirstChild(); path.notNull(); path = path->getNextSibling())
00132                 {
00133                         LLUIString path_val_ui(path->getValue());
00134                         LLString language = "en-us";
00135                         if (LLUI::sConfigGroup)
00136                         {
00137                                 language = LLUI::sConfigGroup->getString("Language");
00138                                 if(language == "default")
00139                                 {
00140                                         language = LLUI::sConfigGroup->getString("SystemLanguage");
00141                                 }
00142                         }
00143                         path_val_ui.setArg("[Language]", language);
00144                         LLString fullpath = app_dir + path_val_ui.getString();
00145 
00146                         if (std::find(mXUIPaths.begin(), mXUIPaths.end(), fullpath) == mXUIPaths.end())
00147                         {
00148                                 mXUIPaths.push_back(app_dir + path_val_ui.getString());
00149                         }
00150                 }
00151         }
00152         else // parsing failed
00153         {
00154                 LLString slash = gDirUtilp->getDirDelimiter();
00155                 LLString dir = gDirUtilp->getAppRODataDir() + slash + "skins" + slash + "xui" + slash + "en-us" + slash;
00156                 llwarns << "XUI::config file unable to open." << llendl;
00157                 mXUIPaths.push_back(dir);
00158         }
00159 }
00160 
00161 
00162 
00163 //-----------------------------------------------------------------------------
00164 // getLayeredXMLNode()
00165 //-----------------------------------------------------------------------------
00166 bool LLUICtrlFactory::getLayeredXMLNode(const LLString &filename, LLXMLNodePtr& root)
00167 {
00168         if (!LLXMLNode::parseFile(mXUIPaths.front() + filename, root, NULL))
00169         {       
00170                 if (!LLXMLNode::parseFile(filename, root, NULL))
00171                 {
00172                         llwarns << "Problem reading UI description file: " << mXUIPaths.front() + filename << llendl;
00173                         return FALSE;
00174                 }
00175         }
00176 
00177         LLXMLNodePtr updateRoot;
00178 
00179         std::vector<LLString>::const_iterator itor;
00180 
00181         for (itor = mXUIPaths.begin(), ++itor; itor != mXUIPaths.end(); ++itor)
00182         {
00183                 LLString nodeName;
00184                 LLString updateName;
00185 
00186                 LLXMLNode::parseFile((*itor) + filename, updateRoot, NULL);
00187         
00188                 updateRoot->getAttributeString("name", updateName);
00189                 root->getAttributeString("name", nodeName);
00190 
00191                 if (updateName == nodeName)
00192                 {
00193                         LLXMLNode::updateNode(root, updateRoot);
00194                 }
00195         }
00196 
00197         return TRUE;
00198 }
00199 
00200 
00201 //-----------------------------------------------------------------------------
00202 // buildFloater()
00203 //-----------------------------------------------------------------------------
00204 void LLUICtrlFactory::buildFloater(LLFloater* floaterp, const LLString &filename, 
00205                                                                         const LLCallbackMap::map_t* factory_map, BOOL open) /* Flawfinder: ignore */
00206 {
00207         LLXMLNodePtr root;
00208 
00209         if (!LLUICtrlFactory::getLayeredXMLNode(filename, root))
00210         {
00211                 return;
00212         }
00213         
00214         // root must be called floater
00215         if( !(root->hasName("floater") || root->hasName("multi_floater") ) )
00216         {
00217                 llwarns << "Root node should be named floater in: " << filename << llendl;
00218                 return;
00219         }
00220 
00221         if (factory_map)
00222         {
00223                 mFactoryStack.push_front(factory_map);
00224         }
00225 
00226         floaterp->initFloaterXML(root, NULL, this, open);       /* Flawfinder: ignore */
00227 
00228         if (LLUI::sShowXUINames)
00229         {
00230                 floaterp->setToolTip(filename);
00231         }
00232 
00233         if (factory_map)
00234         {
00235                 mFactoryStack.pop_front();
00236         }
00237 
00238         LLHandle<LLFloater> handle = floaterp->getHandle();
00239         mBuiltFloaters[handle] = filename;
00240 }
00241 
00242 //-----------------------------------------------------------------------------
00243 // saveToXML()
00244 //-----------------------------------------------------------------------------
00245 S32 LLUICtrlFactory::saveToXML(LLView* viewp, const LLString& filename)
00246 {
00247         llofstream out(filename.c_str());
00248         if (!out.good())
00249         {
00250                 llwarns << "Unable to open " << filename << " for output." << llendl;
00251                 return 1;
00252         }
00253 
00254         out << XML_HEADER;
00255 
00256         LLXMLNodePtr xml_node = viewp->getXML();
00257 
00258         xml_node->writeToOstream(out);
00259 
00260         out.close();
00261         return 0;
00262 }
00263 
00264 //-----------------------------------------------------------------------------
00265 // buildPanel()
00266 //-----------------------------------------------------------------------------
00267 BOOL LLUICtrlFactory::buildPanel(LLPanel* panelp, const LLString &filename,
00268                                                                         const LLCallbackMap::map_t* factory_map)
00269 {
00270         BOOL didPost = FALSE;
00271         LLXMLNodePtr root;
00272 
00273         if (!LLUICtrlFactory::getLayeredXMLNode(filename, root))
00274         {
00275                 return didPost;
00276         }
00277 
00278         // root must be called panel
00279         if( !root->hasName("panel" ) )
00280         {
00281                 llwarns << "Root node should be named panel in : " << filename << llendl;
00282                 return didPost;
00283         }
00284 
00285         if (factory_map)
00286         {
00287                 mFactoryStack.push_front(factory_map);
00288         }
00289 
00290         didPost = panelp->initPanelXML(root, NULL, this);
00291         
00292         if (LLUI::sShowXUINames)
00293         {
00294                 panelp->setToolTip(filename);
00295         }
00296 
00297         LLHandle<LLPanel> handle = panelp->getHandle();
00298         mBuiltPanels[handle] = filename;
00299 
00300         if (factory_map)
00301         {
00302                 mFactoryStack.pop_front();
00303         }
00304 
00305         return didPost;
00306 }
00307 
00308 //-----------------------------------------------------------------------------
00309 // buildMenu()
00310 //-----------------------------------------------------------------------------
00311 LLMenuGL *LLUICtrlFactory::buildMenu(const LLString &filename, LLView* parentp)
00312 {
00313         // TomY TODO: Break this function into buildMenu and buildMenuBar
00314         LLXMLNodePtr root;
00315         LLMenuGL*    menu;
00316 
00317         if (!LLUICtrlFactory::getLayeredXMLNode(filename, root))
00318         {
00319                 return NULL;
00320         }
00321 
00322         // root must be called panel
00323         if( !root->hasName( "menu_bar" ) && !root->hasName( "menu" ))
00324         {
00325                 llwarns << "Root node should be named menu bar or menu in : " << filename << llendl;
00326                 return NULL;
00327         }
00328 
00329         if (root->hasName("menu"))
00330         {
00331                 menu = (LLMenuGL*)LLMenuGL::fromXML(root, parentp, this);
00332         }
00333         else
00334         {
00335                 menu = (LLMenuGL*)LLMenuBarGL::fromXML(root, parentp, this);
00336         }
00337         
00338         if (LLUI::sShowXUINames)
00339         {
00340                 menu->setToolTip(filename);
00341         }
00342 
00343     return menu;
00344 }
00345 
00346 //-----------------------------------------------------------------------------
00347 // buildMenu()
00348 //-----------------------------------------------------------------------------
00349 LLPieMenu *LLUICtrlFactory::buildPieMenu(const LLString &filename, LLView* parentp)
00350 {
00351         LLXMLNodePtr root;
00352 
00353         if (!LLUICtrlFactory::getLayeredXMLNode(filename, root))
00354         {
00355                 return NULL;
00356         }
00357 
00358         // root must be called panel
00359         if( !root->hasName( LL_PIE_MENU_TAG ))
00360         {
00361                 llwarns << "Root node should be named " << LL_PIE_MENU_TAG << " in : " << filename << llendl;
00362                 return NULL;
00363         }
00364 
00365         LLString name("menu");
00366         root->getAttributeString("name", name);
00367 
00368         LLPieMenu *menu = new LLPieMenu(name);
00369         parentp->addChild(menu);
00370         menu->initXML(root, parentp, this);
00371 
00372         if (LLUI::sShowXUINames)
00373         {
00374                 menu->setToolTip(filename);
00375         }
00376 
00377         return menu;
00378 }
00379 
00380 //-----------------------------------------------------------------------------
00381 // rebuild()
00382 //-----------------------------------------------------------------------------
00383 void LLUICtrlFactory::rebuild()
00384 {
00385         built_panel_t::iterator built_panel_it;
00386         for (built_panel_it = mBuiltPanels.begin();
00387                 built_panel_it != mBuiltPanels.end();
00388                 ++built_panel_it)
00389         {
00390                 LLString filename = built_panel_it->second;
00391                 LLPanel* panelp = built_panel_it->first.get();
00392                 if (!panelp)
00393                 {
00394                         continue;
00395                 }
00396                 llinfos << "Rebuilding UI panel " << panelp->getName() 
00397                         << " from " << filename
00398                         << llendl;
00399                 BOOL visible = panelp->getVisible();
00400                 panelp->setVisible(FALSE);
00401                 panelp->setFocus(FALSE);
00402                 panelp->deleteAllChildren();
00403 
00404                 buildPanel(panelp, filename.c_str(), &panelp->getFactoryMap());
00405                 panelp->setVisible(visible);
00406         }
00407 
00408         built_floater_t::iterator built_floater_it;
00409         for (built_floater_it = mBuiltFloaters.begin();
00410                 built_floater_it != mBuiltFloaters.end();
00411                 ++built_floater_it)
00412         {
00413                 LLFloater* floaterp = built_floater_it->first.get();
00414                 if (!floaterp)
00415                 {
00416                         continue;
00417                 }
00418                 LLString filename = built_floater_it->second;
00419                 llinfos << "Rebuilding UI floater " << floaterp->getName()
00420                         << " from " << filename
00421                         << llendl;
00422                 BOOL visible = floaterp->getVisible();
00423                 floaterp->setVisible(FALSE);
00424                 floaterp->setFocus(FALSE);
00425                 floaterp->deleteAllChildren();
00426 
00427                 gFloaterView->removeChild(floaterp);
00428                 buildFloater(floaterp, filename, &floaterp->getFactoryMap());
00429                 floaterp->setVisible(visible);
00430         }
00431 }
00432 
00433 //-----------------------------------------------------------------------------
00434 //-----------------------------------------------------------------------------
00435 
00436 LLView *LLUICtrlFactory::createCtrlWidget(LLPanel *parent, LLXMLNodePtr node)
00437 {
00438         LLString ctrl_type = node->getName()->mString;
00439         LLString::toLower(ctrl_type);
00440         
00441         LLWidgetClassRegistry::factory_func_t func = LLWidgetClassRegistry::getInstance()->getCreatorFunc(ctrl_type);
00442 
00443         if (func == NULL)
00444         {
00445                 llwarns << "Unknown control type " << ctrl_type << llendl;
00446                 return NULL;
00447         }
00448 
00449         if (parent == NULL)
00450         {
00451                 if (mDummyPanel == NULL)
00452                 {
00453                         mDummyPanel = new LLPanel;
00454                 }
00455                 parent = mDummyPanel;
00456         }
00457         LLView *ctrl = func(node, parent, this);
00458 
00459         return ctrl;
00460 }
00461 
00462 LLView* LLUICtrlFactory::createWidget(LLPanel *parent, LLXMLNodePtr node)
00463 {
00464         LLView* view = createCtrlWidget(parent, node);
00465 
00466         S32 tab_group = parent->getLastTabGroup();
00467         node->getAttributeS32("tab_group", tab_group);
00468 
00469         if (view)
00470         {
00471                 parent->addChild(view, tab_group);
00472         }
00473 
00474         return view;
00475 }
00476 
00477 //-----------------------------------------------------------------------------
00478 // createFactoryPanel()
00479 //-----------------------------------------------------------------------------
00480 LLPanel* LLUICtrlFactory::createFactoryPanel(LLString name)
00481 {
00482         std::deque<const LLCallbackMap::map_t*>::iterator itor;
00483         for (itor = mFactoryStack.begin(); itor != mFactoryStack.end(); ++itor)
00484         {
00485                 const LLCallbackMap::map_t* factory_map = *itor;
00486 
00487                 // Look up this panel's name in the map.
00488                 LLCallbackMap::map_const_iter_t iter = factory_map->find( name );
00489                 if (iter != factory_map->end())
00490                 {
00491                         // Use the factory to create the panel, instead of using a default LLPanel.
00492                         LLPanel *ret = (LLPanel*) iter->second.mCallback( iter->second.mData );
00493                         return ret;
00494                 }
00495         }
00496         return NULL;
00497 }
00498 
00499 //-----------------------------------------------------------------------------
00500 
00501 //static
00502 BOOL LLUICtrlFactory::getAttributeColor(LLXMLNodePtr node, const LLString& name, LLColor4& color)
00503 {
00504         LLString colorstring;
00505         BOOL res = node->getAttributeString(name, colorstring);
00506         if (res && LLUI::sColorsGroup)
00507         {
00508                 if (LLUI::sColorsGroup->controlExists(colorstring))
00509                 {
00510                         color.setVec(LLUI::sColorsGroup->getColor(colorstring));
00511                 }
00512                 else
00513                 {
00514                         res = FALSE;
00515                 }
00516         }
00517         if (!res)
00518         {
00519                 res = LLColor4::parseColor(colorstring.c_str(), &color);
00520         }       
00521         if (!res)
00522         {
00523                 res = node->getAttributeColor(name, color);
00524         }
00525         return res;
00526 }
00527 

Generated on Fri May 16 08:33:00 2008 for SecondLife by  doxygen 1.5.5