llcontrol.cpp

Go to the documentation of this file.
00001 
00032 #include "linden_common.h"
00033 
00034 #include <iostream>
00035 #include <fstream>
00036 #include <algorithm>
00037 
00038 #include "llcontrol.h"
00039 
00040 #include "llstl.h"
00041 
00042 #include "linked_lists.h"
00043 #include "llstring.h"
00044 #include "v3math.h"
00045 #include "v3dmath.h"
00046 #include "v4coloru.h"
00047 #include "v4color.h"
00048 #include "v3color.h"
00049 #include "llrect.h"
00050 #include "llxmltree.h"
00051 #include "llsdserialize.h"
00052 
00053 #if LL_RELEASE_FOR_DOWNLOAD
00054 #define CONTROL_ERRS llwarns
00055 #else
00056 #define CONTROL_ERRS llerrs
00057 #endif
00058 
00059 //this defines the current version of the settings file
00060 U32     LLControlBase::sMaxControlNameLength = 0;
00061 
00062 //These lists are used to store the ID's of registered event listeners.
00063 std::list<S32>                          LLControlBase::mFreeIDs;
00064 std::list<S32>                          LLControlBase::mUsedIDs;
00065 
00066 S32                                                     LLControlBase::mTopID;
00067 
00068 std::set<LLControlBase*>        LLControlBase::mChangedControls;
00069 
00070 const S32 CURRENT_VERSION = 101;
00071 
00072 BOOL control_insert_before( LLControlBase* first, LLControlBase* second );
00073 
00074 BOOL LLControl::llsd_compare(const LLSD& a, const LLSD & b)
00075 {
00076         switch (mType)
00077         {
00078         case TYPE_U32:
00079         case TYPE_S32:
00080                 return a.asInteger() == b.asInteger();
00081         case TYPE_BOOLEAN:
00082                 return a.asBoolean() == b.asBoolean();
00083         case TYPE_F32:
00084                 return a.asReal() == b.asReal();
00085         case TYPE_VEC3:
00086         case TYPE_VEC3D:
00087                 return LLVector3d(a) == LLVector3d(b);
00088         case TYPE_RECT:
00089                 return LLRect(a) == LLRect(b);
00090         case TYPE_COL4:
00091                 return LLColor4(a) == LLColor4(b);
00092         case TYPE_COL3:
00093                 return LLColor3(a) == LLColor3(b);
00094         case TYPE_COL4U:
00095                 return LLColor4U(a) == LLColor4U(b);
00096         case TYPE_STRING:
00097                 return a.asString() == b.asString();
00098         default:
00099                 // no-op
00100                 break;
00101         }
00102 
00103         return FALSE;
00104 }
00105 
00106 LLControlBase::~LLControlBase()
00107 {
00108 }
00109 
00110 // virtual
00111 void LLControlBase::resetToDefault()
00112 {
00113 }
00114 
00115 LLControlGroup::LLControlGroup():       mNameTable()
00116 {
00117         //mFreeStringOffset = 0;
00118 }
00119 
00120 LLControlGroup::~LLControlGroup()
00121 {
00122 }
00123 
00124 LLSD LLControlBase::registerListener(LLSimpleListenerObservable *listener, LLSD userdata)
00125 {
00126         // Symmetric listener relationship
00127         addListener(listener, "", userdata);
00128         listener->addListener(this, "", userdata);
00129         return getValue();
00130 }
00131 
00132 void LLControlGroup::cleanup()
00133 {
00134         mNameTable.clear();
00135 }
00136 
00137 LLControlBase*  LLControlGroup::getControl(const LLString& name)
00138 {
00139         ctrl_name_table_t::iterator iter = mNameTable.find(name);
00140         return iter == mNameTable.end() ? NULL : (LLControlBase*)iter->second;
00141 }
00142 
00143 BOOL LLControlGroup::declareControl(const LLString& name, eControlType type, const LLSD initial_val, const LLString& comment, BOOL persist)
00144 {
00145         if(!mNameTable[name])
00146         {
00147                 // if not, create the control and add it to the name table
00148                 LLControl* control = new LLControl(name, type, initial_val, comment, persist);
00149                 mNameTable[name] = control;
00150                 return TRUE;
00151         }
00152         else
00153         {
00154                 llwarns << "LLControlGroup::declareControl: Control named " << name << " already exists." << llendl;
00155                 mNameTable.erase(name);
00156                 return FALSE;
00157         }
00158 }
00159 
00160 BOOL LLControlGroup::declareU32(const LLString& name, const U32 initial_val, const LLString& comment, BOOL persist)
00161 {
00162         return declareControl(name, TYPE_U32, (LLSD::Integer) initial_val, comment, persist);
00163 }
00164 
00165 BOOL LLControlGroup::declareS32(const LLString& name, const S32 initial_val, const LLString& comment, BOOL persist)
00166 {
00167         return declareControl(name, TYPE_S32, initial_val, comment, persist);
00168 }
00169 
00170 BOOL LLControlGroup::declareF32(const LLString& name, const F32 initial_val, const LLString& comment, BOOL persist)
00171 {
00172         return declareControl(name, TYPE_F32, initial_val, comment, persist);
00173 }
00174 
00175 BOOL LLControlGroup::declareBOOL(const LLString& name, const BOOL initial_val, const LLString& comment, BOOL persist)
00176 {
00177         return declareControl(name, TYPE_BOOLEAN, initial_val, comment, persist);
00178 }
00179 
00180 BOOL LLControlGroup::declareString(const LLString& name, const LLString& initial_val, const LLString& comment, BOOL persist)
00181 {
00182         return declareControl(name, TYPE_STRING, initial_val, comment, persist);
00183 }
00184 
00185 BOOL LLControlGroup::declareVec3(const LLString& name, const LLVector3 &initial_val, const LLString& comment, BOOL persist)
00186 {
00187         return declareControl(name, TYPE_VEC3, initial_val.getValue(), comment, persist);
00188 }
00189 
00190 BOOL LLControlGroup::declareVec3d(const LLString& name, const LLVector3d &initial_val, const LLString& comment, BOOL persist)
00191 {
00192         return declareControl(name, TYPE_VEC3D, initial_val.getValue(), comment, persist);
00193 }
00194 
00195 BOOL LLControlGroup::declareRect(const LLString& name, const LLRect &initial_val, const LLString& comment, BOOL persist)
00196 {
00197         return declareControl(name, TYPE_RECT, initial_val.getValue(), comment, persist);
00198 }
00199 
00200 BOOL LLControlGroup::declareColor4U(const LLString& name, const LLColor4U &initial_val, const LLString& comment, BOOL persist )
00201 {
00202         return declareControl(name, TYPE_COL4U, initial_val.getValue(), comment, persist);
00203 }
00204 
00205 BOOL LLControlGroup::declareColor4(const LLString& name, const LLColor4 &initial_val, const LLString& comment, BOOL persist )
00206 {
00207         return declareControl(name, TYPE_COL4, initial_val.getValue(), comment, persist);
00208 }
00209 
00210 BOOL LLControlGroup::declareColor3(const LLString& name, const LLColor3 &initial_val, const LLString& comment, BOOL persist )
00211 {
00212         return declareControl(name, TYPE_COL3, initial_val.getValue(), comment, persist);
00213 }
00214 
00215 LLSD LLControlGroup::registerListener(const LLString& name, LLSimpleListenerObservable *listener)
00216 {
00217         LLControlBase *control = getControl(name);
00218         if (control)
00219         {
00220                 return control->registerListener(listener);
00221         }
00222         return LLSD();
00223 }
00224 
00225 BOOL LLControlGroup::getBOOL(const LLString& name)
00226 {
00227         LLControlBase* control = getControl(name);
00228         
00229         if (control && control->isType(TYPE_BOOLEAN))
00230                 return control->get().asBoolean();
00231         else
00232         {
00233                 CONTROL_ERRS << "Invalid BOOL control " << name << llendl;
00234                 return FALSE;
00235         }
00236 }
00237 
00238 S32 LLControlGroup::getS32(const LLString& name)
00239 {
00240         LLControlBase* control = getControl(name);
00241         
00242         if (control && control->isType(TYPE_S32))
00243                 return control->get().asInteger();
00244         else
00245         {
00246                 CONTROL_ERRS << "Invalid S32 control " << name << llendl;
00247                 return 0;
00248         }
00249 }
00250 
00251 U32 LLControlGroup::getU32(const LLString& name)
00252 {
00253         LLControlBase* control = getControl(name);
00254         
00255         if (control && control->isType(TYPE_U32))               
00256                 return control->get().asInteger();
00257         else
00258         {
00259                 CONTROL_ERRS << "Invalid U32 control " << name << llendl;
00260                 return 0;
00261         }
00262 }
00263 
00264 F32 LLControlGroup::getF32(const LLString& name)
00265 {
00266         LLControlBase* control = getControl(name);
00267         
00268         if (control && control->isType(TYPE_F32))
00269                 return (F32) control->get().asReal();
00270         else
00271         {
00272                 CONTROL_ERRS << "Invalid F32 control " << name << llendl;
00273                 return 0.0f;
00274         }
00275 }
00276 
00277 LLString LLControlGroup::findString(const LLString& name)
00278 {
00279         LLControlBase* control = getControl(name);
00280         
00281         if (control && control->isType(TYPE_STRING))
00282                 return control->get().asString();
00283         return LLString::null;
00284 }
00285 
00286 LLString LLControlGroup::getString(const LLString& name)
00287 {
00288         LLControlBase* control = getControl(name);
00289         
00290         if (control && control->isType(TYPE_STRING))
00291                 return control->get().asString();
00292         else
00293         {
00294                 CONTROL_ERRS << "Invalid string control " << name << llendl;
00295                 return LLString::null;
00296         }
00297 }
00298 
00299 LLWString LLControlGroup::getWString(const LLString& name)
00300 {
00301         return utf8str_to_wstring(getString(name));
00302 }
00303 
00304 LLString LLControlGroup::getText(const LLString& name)
00305 {
00306         LLString utf8_string = getString(name);
00307         LLString::replaceChar(utf8_string, '^', '\n');
00308         LLString::replaceChar(utf8_string, '%', ' ');
00309         return (utf8_string);
00310 }
00311 
00312 LLVector3 LLControlGroup::getVector3(const LLString& name)
00313 {
00314         LLControlBase* control = getControl(name);
00315         
00316         if (control && control->isType(TYPE_VEC3))
00317                 return control->get();
00318         else
00319         {
00320                 CONTROL_ERRS << "Invalid LLVector3 control " << name << llendl;
00321                 return LLVector3::zero;
00322         }
00323 }
00324 
00325 LLVector3d LLControlGroup::getVector3d(const LLString& name)
00326 {
00327         LLControlBase* control = getControl(name);
00328         
00329         if (control && control->isType(TYPE_VEC3D))
00330                 return control->get();
00331         else
00332         {
00333                 CONTROL_ERRS << "Invalid LLVector3d control " << name << llendl;
00334                 return LLVector3d::zero;
00335         }
00336 }
00337 
00338 LLRect LLControlGroup::getRect(const LLString& name)
00339 {
00340         LLControlBase* control = getControl(name);
00341         
00342         if (control && control->isType(TYPE_RECT))
00343                 return control->get();
00344         else
00345         {
00346                 CONTROL_ERRS << "Invalid rect control " << name << llendl;
00347                 return LLRect::null;
00348         }
00349 }
00350 
00351 
00352 LLColor4 LLControlGroup::getColor(const LLString& name)
00353 {
00354         ctrl_name_table_t::const_iterator i = mNameTable.find(name);
00355 
00356         if (i != mNameTable.end())
00357         {
00358                 LLControlBase* control = i->second;
00359 
00360                 switch(control->mType)
00361                 {
00362                 case TYPE_COL4:
00363                         {
00364                                 return LLColor4(control->get());
00365                         }
00366                 case TYPE_COL4U:
00367                         {
00368                                 return LLColor4(LLColor4U(control->get()));
00369                         }
00370                 default:
00371                         {
00372                                 CONTROL_ERRS << "Control " << name << " not a color" << llendl;
00373                                 return LLColor4::white;
00374                         }
00375                 }
00376         }
00377         else
00378         {
00379                 CONTROL_ERRS << "Invalid getColor control " << name << llendl;
00380                 return LLColor4::white;
00381         }
00382 }
00383 
00384 LLColor4U LLControlGroup::getColor4U(const LLString& name)
00385 {
00386         LLControlBase* control = getControl(name);
00387         
00388         if (control && control->isType(TYPE_COL4U))
00389                 return control->get();
00390         else
00391         {
00392                 CONTROL_ERRS << "Invalid LLColor4 control " << name << llendl;
00393                 return LLColor4U::white;
00394         }
00395 }
00396 
00397 LLColor4 LLControlGroup::getColor4(const LLString& name)
00398 {
00399         LLControlBase* control = getControl(name);
00400         
00401         if (control && control->isType(TYPE_COL4))
00402                 return control->get();
00403         else
00404         {
00405                 CONTROL_ERRS << "Invalid LLColor4 control " << name << llendl;
00406                 return LLColor4::white;
00407         }
00408 }
00409 
00410 LLColor3 LLControlGroup::getColor3(const LLString& name)
00411 {
00412         LLControlBase* control = getControl(name);
00413         
00414         if (control && control->isType(TYPE_COL3))
00415                 return control->get();
00416         else
00417         {
00418                 CONTROL_ERRS << "Invalid LLColor3 control " << name << llendl;
00419                 return LLColor3::white;
00420         }
00421 }
00422 
00423 BOOL LLControlGroup::controlExists(const LLString& name)
00424 {
00425         ctrl_name_table_t::iterator iter = mNameTable.find(name);
00426         return iter != mNameTable.end();
00427 }
00428 
00429 //-------------------------------------------------------------------
00430 // Set functions
00431 //-------------------------------------------------------------------
00432 
00433 void LLControlGroup::setBOOL(const LLString& name, BOOL val)
00434 {
00435         LLControlBase* control = getControl(name);
00436         
00437         if (control && control->isType(TYPE_BOOLEAN))
00438         {
00439                 control->set(val);
00440         }
00441         else
00442         {
00443                 CONTROL_ERRS << "Invalid control " << name << llendl;
00444         }
00445 }
00446 
00447 
00448 void LLControlGroup::setS32(const LLString& name, S32 val)
00449 {
00450         LLControlBase* control = getControl(name);
00451         
00452         if (control && control->isType(TYPE_S32))
00453         {
00454                 control->set(val);
00455         }
00456         else
00457         {
00458                 CONTROL_ERRS << "Invalid control " << name << llendl;
00459         }
00460 }
00461 
00462 
00463 void LLControlGroup::setF32(const LLString& name, F32 val)
00464 {
00465         LLControlBase* control = getControl(name);
00466         
00467         if (control && control->isType(TYPE_F32))
00468         {
00469                 control->set(val);
00470         }
00471         else
00472         {
00473                 CONTROL_ERRS << "Invalid control " << name << llendl;
00474         }
00475 }
00476 
00477 
00478 void LLControlGroup::setU32(const LLString& name, U32 val)
00479 {
00480         LLControlBase* control = getControl(name);
00481         
00482         if (control && control->isType(TYPE_U32))
00483         {
00484                 control->set((LLSD::Integer) val);
00485         }
00486         else
00487         {
00488                 CONTROL_ERRS << "Invalid control " << name << llendl;
00489         }
00490 }
00491 
00492 
00493 void LLControlGroup::setString(const LLString& name, const LLString &val)
00494 {
00495         LLControlBase* control = getControl(name);
00496         
00497         if (control && control->isType(TYPE_STRING))
00498         {
00499                 control->set(val);
00500         }
00501         else
00502         {
00503                 CONTROL_ERRS << "Invalid control " << name << llendl;
00504         }
00505 }
00506 
00507 
00508 void LLControlGroup::setVector3(const LLString& name, const LLVector3 &val)
00509 {
00510         LLControlBase* control = getControl(name);
00511         
00512         if (control && control->isType(TYPE_VEC3))
00513         {
00514                 control->set(val.getValue());
00515         }
00516         else
00517         {
00518                 CONTROL_ERRS << "Invalid control " << name << llendl;
00519         }
00520 }
00521 
00522 void LLControlGroup::setVector3d(const LLString& name, const LLVector3d &val)
00523 {
00524         LLControlBase* control = getControl(name);
00525         
00526         if (control && control->isType(TYPE_VEC3D))
00527         {
00528                 control->set(val.getValue());
00529         }
00530         else
00531         {
00532                 CONTROL_ERRS << "Invalid control " << name << llendl;
00533         }
00534 }
00535 
00536 void LLControlGroup::setRect(const LLString& name, const LLRect &val)
00537 {
00538         LLControlBase* control = getControl(name);
00539 
00540         if (control && control->isType(TYPE_RECT))
00541         {
00542                 control->set(val.getValue());
00543         }
00544         else
00545         {
00546                 CONTROL_ERRS << "Invalid rect control " << name << llendl;
00547         }
00548 }
00549 
00550 void LLControlGroup::setColor4U(const LLString& name, const LLColor4U &val)
00551 {
00552         LLControlBase* control = getControl(name);
00553         
00554         if (control && control->isType(TYPE_COL4U))
00555         {
00556                 control->set(val.getValue());
00557         }
00558         else
00559         {
00560                 CONTROL_ERRS << "Invalid LLColor4 control " << name << llendl;
00561         }
00562 }
00563 
00564 void LLControlGroup::setColor4(const LLString& name, const LLColor4 &val)
00565 {
00566         LLControlBase* control = getControl(name);
00567         
00568         if (control && control->isType(TYPE_COL4))
00569         {
00570                 control->set(val.getValue());
00571         }
00572         else
00573         {
00574                 CONTROL_ERRS << "Invalid LLColor4 control " << name << llendl;
00575         }
00576 }
00577 
00578 void LLControlGroup::setValue(const LLString& name, const LLSD& val)
00579 {
00580         if (name.empty())
00581         {
00582                 return;
00583         }
00584 
00585         LLControlBase* control = getControl(name);
00586         
00587         if (control)
00588         {
00589                 control->set(val);
00590         }
00591         else
00592         {
00593                 CONTROL_ERRS << "Invalid control " << name << llendl;
00594         }
00595 }
00596 
00597 //---------------------------------------------------------------
00598 // Load and save
00599 //---------------------------------------------------------------
00600 
00601 U32 LLControlGroup::loadFromFileLegacy(const LLString& filename, BOOL require_declaration, eControlType declare_as)
00602 {
00603         U32             item = 0;
00604         U32             validitems = 0;
00605         llifstream file;
00606         S32 version;
00607         
00608         file.open(filename.c_str());            /*Flawfinder: ignore*/ 
00609 
00610         if (!file)
00611         {
00612                 llinfos << "LLControlGroup::loadFromFile unable to open." << llendl;
00613                 return 0;
00614         }
00615 
00616         // Check file version
00617         LLString name;
00618         file >> name;
00619         file >> version;
00620         if (name != "version" || version != CURRENT_VERSION)
00621         {
00622                 llinfos << filename << " does not appear to be a version " << CURRENT_VERSION << " controls file" << llendl;
00623                 return 0;
00624         }
00625 
00626         while (!file.eof())
00627         {
00628                 file >> name;
00629                 
00630                 if (name.empty())
00631                 {
00632                         continue;
00633                 }
00634 
00635                 if (name.substr(0,2) == "//")
00636                 {
00637                         // This is a comment.
00638                         char buffer[MAX_STRING];                /*Flawfinder: ignore*/
00639                         file.getline(buffer, MAX_STRING);
00640                         continue;
00641                 }
00642 
00643                 BOOL declared = mNameTable.find(name) != mNameTable.end();
00644 
00645                 if (require_declaration && !declared)
00646                 {
00647                         // Declaration required, but this name not declared.
00648                         // Complain about non-empty names.
00649                         if (!name.empty())
00650                         {
00651                                 //read in to end of line
00652                                 char buffer[MAX_STRING];                /*Flawfinder: ignore*/
00653                                 file.getline(buffer, MAX_STRING);
00654                                 llwarns << "LLControlGroup::loadFromFile() : Trying to set \"" << name << "\", setting doesn't exist." << llendl;
00655                         }
00656                         continue;
00657                 }
00658 
00659                 // Got an item.  Load it up.
00660                 item++;
00661 
00662                 // If not declared, assume it's a string
00663                 if (!declared)
00664                 {
00665                         switch(declare_as)
00666                         {
00667                         case TYPE_COL4:
00668                                 declareColor4(name, LLColor4::white, LLString::null, NO_PERSIST);
00669                                 break;
00670                         case TYPE_COL4U:
00671                                 declareColor4U(name, LLColor4U::white, LLString::null, NO_PERSIST);
00672                                 break;
00673                         case TYPE_STRING:
00674                         default:
00675                                 declareString(name, LLString::null, LLString::null, NO_PERSIST);
00676                                 break;
00677                         }
00678                 }
00679 
00680                 // Control name has been declared in code.
00681                 LLControlBase *control = getControl(name);
00682 
00683                 llassert(control);
00684 
00685                 switch(control->mType)
00686                 {
00687                 case TYPE_F32:
00688                         {
00689                                 F32 initial;
00690 
00691                                 file >> initial;
00692 
00693                                 control->set(initial);
00694                                 validitems++;
00695                         }
00696                         break;
00697                 case TYPE_S32:
00698                         {
00699                                 S32 initial;
00700 
00701                                 file >> initial;
00702 
00703                                 control->set(initial);
00704                                 validitems++;
00705                         }
00706                         break;
00707                 case TYPE_U32:
00708                         {
00709                                 U32 initial;
00710 
00711                                 file >> initial;
00712                                 control->set((LLSD::Integer) initial);
00713                                 validitems++;
00714                         }
00715                         break;
00716                 case TYPE_BOOLEAN:
00717                         {
00718                                 char boolstring[256];           /*Flawfinder: ignore*/
00719                                 BOOL valid = FALSE;
00720                                 BOOL initial = FALSE;
00721 
00722                                 file >> boolstring;
00723                                 if (!strcmp("TRUE", boolstring))
00724                                 {
00725                                         initial = TRUE;
00726                                         valid = TRUE;
00727                                 }
00728                                 else if (!strcmp("FALSE", boolstring))
00729                                 {
00730                                         initial = FALSE;
00731                                         valid = TRUE;
00732                                 }
00733 
00734                                 if (valid)
00735                                 {
00736                                         control->set(initial);
00737                                 }
00738                                 else
00739                                 {
00740                                         llinfos << filename << "Item " << item << ": Invalid BOOL control " << name << ", " << boolstring << llendl; 
00741                                 }
00742 
00743                                 validitems++;
00744                         }
00745                         break;
00746                 case TYPE_STRING:
00747                         {
00748                                 LLString string;
00749                                 
00750                                 file >> string;
00751                                 
00752                                 control->set(string);
00753                                 validitems++;
00754                         }
00755                         break;
00756                 case TYPE_VEC3:
00757                         {
00758                                 F32 x, y, z;
00759 
00760                                 file >> x >> y >> z;
00761 
00762                                 LLVector3 vector(x, y, z);
00763 
00764                                 control->set(vector.getValue());
00765                                 validitems++;
00766                         }
00767                         break;
00768                 case TYPE_VEC3D:
00769                         {
00770                                 F64 x, y, z;
00771 
00772                                 file >> x >> y >> z;
00773 
00774                                 LLVector3d vector(x, y, z);
00775 
00776                                 control->set(vector.getValue());
00777                                 validitems++;
00778                         }
00779                         break;
00780                 case TYPE_RECT:
00781                         {
00782                                 S32 left, bottom, width, height;
00783 
00784                                 file >> left >> bottom >> width >> height;
00785 
00786                                 LLRect rect;
00787                                 rect.setOriginAndSize(left, bottom, width, height);
00788 
00789                                 control->set(rect.getValue());
00790                                 validitems++;
00791                         }
00792                         break;
00793                 case TYPE_COL4U:
00794                         {
00795                                 S32 red, green, blue, alpha;
00796                                 LLColor4U color;
00797                                 file >> red >> green >> blue >> alpha;
00798                                 color.setVec(red, green, blue, alpha);
00799                                 control->set(color.getValue());
00800                                 validitems++;
00801                         }
00802                         break;
00803                 case TYPE_COL4:
00804                         {
00805                                 LLColor4 color;
00806                                 file >> color.mV[VRED] >> color.mV[VGREEN]
00807                                          >> color.mV[VBLUE] >> color.mV[VALPHA];
00808                                 control->set(color.getValue());
00809                                 validitems++;
00810                         }
00811                         break;
00812                 case TYPE_COL3:
00813                         {
00814                                 LLColor3 color;
00815                                 file >> color.mV[VRED] >> color.mV[VGREEN]
00816                                          >> color.mV[VBLUE];
00817                                 control->set(color.getValue());
00818                                 validitems++;
00819                         }
00820                         break;
00821                 }
00822         }
00823 
00824         file.close();
00825 
00826         return validitems;
00827 }
00828 
00829 // Returns number of controls loaded, so 0 if failure
00830 U32 LLControlGroup::loadFromFile(const LLString& filename, BOOL require_declaration, eControlType declare_as)
00831 {
00832         LLString name;
00833 
00834         LLXmlTree xml_controls;
00835 
00836         if (!xml_controls.parseFile(filename))
00837         {
00838                 llwarns << "Unable to open control file " << filename << llendl;
00839                 return 0;
00840         }
00841 
00842         LLXmlTreeNode* rootp = xml_controls.getRoot();
00843         if (!rootp || !rootp->hasAttribute("version"))
00844         {
00845                 llwarns << "No valid settings header found in control file " << filename << llendl;
00846                 return 0;
00847         }
00848 
00849         U32             item = 0;
00850         U32             validitems = 0;
00851         S32 version;
00852         
00853         rootp->getAttributeS32("version", version);
00854 
00855         // Check file version
00856         if (version != CURRENT_VERSION)
00857         {
00858                 llinfos << filename << " does not appear to be a version " << CURRENT_VERSION << " controls file" << llendl;
00859                 return 0;
00860         }
00861 
00862         LLXmlTreeNode* child_nodep = rootp->getFirstChild();
00863         while(child_nodep)
00864         {
00865                 name = child_nodep->getName();          
00866                 
00867                 BOOL declared = controlExists(name);
00868 
00869                 if (require_declaration && !declared)
00870                 {
00871                         // Declaration required, but this name not declared.
00872                         // Complain about non-empty names.
00873                         if (!name.empty())
00874                         {
00875                                 //read in to end of line
00876                                 llwarns << "LLControlGroup::loadFromFile() : Trying to set \"" << name << "\", setting doesn't exist." << llendl;
00877                         }
00878                         child_nodep = rootp->getNextChild();
00879                         continue;
00880                 }
00881 
00882                 // Got an item.  Load it up.
00883                 item++;
00884 
00885                 // If not declared, assume it's a string
00886                 if (!declared)
00887                 {
00888                         switch(declare_as)
00889                         {
00890                         case TYPE_COL4:
00891                                 declareColor4(name, LLColor4::white, "", NO_PERSIST);
00892                                 break;
00893                         case TYPE_COL4U:
00894                                 declareColor4U(name, LLColor4U::white, "", NO_PERSIST);
00895                                 break;
00896                         case TYPE_STRING:
00897                         default:
00898                                 declareString(name, LLString::null, "", NO_PERSIST);
00899                                 break;
00900                         }
00901                 }
00902 
00903                 // Control name has been declared in code.
00904                 LLControlBase *control = getControl(name);
00905 
00906                 llassert(control);
00907 
00908                 switch(control->mType)
00909                 {
00910                 case TYPE_F32:
00911                         {
00912                                 F32 initial = 0.f;
00913 
00914                                 child_nodep->getAttributeF32("value", initial);
00915 
00916                                 control->set(initial);
00917                                 validitems++;
00918                         }
00919                         break;
00920                 case TYPE_S32:
00921                         {
00922                                 S32 initial = 0;
00923 
00924                                 child_nodep->getAttributeS32("value", initial);
00925 
00926                                 control->set(initial);
00927                                 validitems++;
00928                         }
00929                         break;
00930                 case TYPE_U32:
00931                         {
00932                                 U32 initial = 0;
00933                                 child_nodep->getAttributeU32("value", initial);
00934                                 control->set((LLSD::Integer) initial);
00935                                 validitems++;
00936                         }
00937                         break;
00938                 case TYPE_BOOLEAN:
00939                         {
00940                                 BOOL initial = FALSE;
00941 
00942                                 child_nodep->getAttributeBOOL("value", initial);
00943                                 control->set(initial);
00944 
00945                                 validitems++;
00946                         }
00947                         break;
00948                 case TYPE_STRING:
00949                         {
00950                                 LLString string;
00951                                 child_nodep->getAttributeString("value", string);
00952                                 if (string == LLString::null)
00953                                 {
00954                                         string = "";
00955                                 }
00956                                 control->set(string);
00957                                 validitems++;
00958                         }
00959                         break;
00960                 case TYPE_VEC3:
00961                         {
00962                                 LLVector3 vector;
00963 
00964                                 child_nodep->getAttributeVector3("value", vector);
00965                                 control->set(vector.getValue());
00966                                 validitems++;
00967                         }
00968                         break;
00969                 case TYPE_VEC3D:
00970                         {
00971                                 LLVector3d vector;
00972 
00973                                 child_nodep->getAttributeVector3d("value", vector);
00974 
00975                                 control->set(vector.getValue());
00976                                 validitems++;
00977                         }
00978                         break;
00979                 case TYPE_RECT:
00980                         {
00981                                 //RN: hack to support reading rectangles from a string
00982                                 LLString rect_string;
00983 
00984                                 child_nodep->getAttributeString("value", rect_string);
00985                                 std::istringstream istream(rect_string);
00986                                 S32 left, bottom, width, height;
00987 
00988                                 istream >> left >> bottom >> width >> height;
00989 
00990                                 LLRect rect;
00991                                 rect.setOriginAndSize(left, bottom, width, height);
00992 
00993                                 control->set(rect.getValue());
00994                                 validitems++;
00995                         }
00996                         break;
00997                 case TYPE_COL4U:
00998                         {
00999                                 LLColor4U color;
01000 
01001                                 child_nodep->getAttributeColor4U("value", color);
01002                                 control->set(color.getValue());
01003                                 validitems++;
01004                         }
01005                         break;
01006                 case TYPE_COL4:
01007                         {
01008                                 LLColor4 color;
01009                                 
01010                                 child_nodep->getAttributeColor4("value", color);
01011                                 control->set(color.getValue());
01012                                 validitems++;
01013                         }
01014                         break;
01015                 case TYPE_COL3:
01016                         {
01017                                 LLVector3 color;
01018                                 
01019                                 child_nodep->getAttributeVector3("value", color);
01020                 control->set(LLColor3(color.mV).getValue());
01021                                 validitems++;
01022                         }
01023                         break;
01024                 }
01025 
01026                 child_nodep = rootp->getNextChild();
01027         }
01028 
01029         return validitems;
01030 }
01031 
01032 
01033 U32 LLControlGroup::saveToFile(const LLString& filename, BOOL nondefault_only)
01034 {
01035         const char ENDL = '\n';
01036 
01037         llinfos << "Saving settings to file: " << filename << llendl;
01038 
01039         // place the objects in a temporary container that enforces a sort
01040         // order to ease manual editing of the file
01041         LLLinkedList< LLControlBase > controls;
01042         controls.setInsertBefore( &control_insert_before );
01043         LLString name;
01044         for (ctrl_name_table_t::iterator iter = mNameTable.begin();
01045                  iter != mNameTable.end(); iter++)
01046         {
01047                 name = iter->first;
01048                 if (name.empty())
01049                 {
01050                         CONTROL_ERRS << "Control with no name found!!!" << llendl;
01051                         break;
01052                 }
01053 
01054                 LLControlBase* control = (LLControlBase *)iter->second;
01055                 if (!control)
01056                 {
01057                         llwarns << "Tried to save invalid control: " << name << llendl;
01058                 }
01059 
01060                 if( control && control->mPersist )
01061                 {
01062                         if (!(nondefault_only && (control->mIsDefault)))
01063                         {
01064                                 controls.addDataSorted( control );
01065                         }
01066                         else
01067                         {
01068                                 // Debug spam
01069                                 // llinfos << "Skipping " << control->getName() << llendl;
01070                         }
01071                 }
01072         }
01073 
01074         llofstream file;
01075         file.open(filename.c_str());            /*Flawfinder: ignore*/
01076 
01077         if (!file.is_open())
01078         {
01079                 // This is a warning because sometime we want to use settings files which can't be written...
01080                 llwarns << "LLControlGroup::saveToFile unable to open file for writing" << llendl;
01081                 return 0;
01082         }
01083 
01084         // Write file version
01085         file << "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>\n";
01086         file << "<settings version = \"" << CURRENT_VERSION << "\">\n";
01087     for( LLControlBase* control = controls.getFirstData();
01088                  control != NULL;
01089                  control = controls.getNextData() )
01090         {
01091                 file << "\t<!--" << control->comment() << "-->" << ENDL;
01092                 name = control->name();
01093                 switch (control->type())
01094                 {
01095                         case TYPE_U32:
01096                         {
01097                                 file << "\t<" << name << " value=\"" << (U32) control->get().asInteger() << "\"/>\n";
01098                                 break;
01099                         }
01100                         case TYPE_S32:
01101                         {
01102                                 file << "\t<" << name << " value=\"" << (S32) control->get().asInteger() << "\"/>\n";
01103                                 break;
01104                         }
01105                         case TYPE_F32:
01106                         {
01107                                 file << "\t<" << name << " value=\"" << (F32) control->get().asReal() << "\"/>\n";
01108                                 break;
01109                         }
01110                         case TYPE_VEC3:
01111                         {
01112                                 LLVector3 vector(control->get());
01113                                 file << "\t<" << name << " value=\"" << vector.mV[VX] << " " << vector.mV[VY] << " " << vector.mV[VZ] << "\"/>\n";
01114                                 break;
01115                         }
01116                         case TYPE_VEC3D:
01117                         {
01118                                 LLVector3d vector(control->get());
01119                                 file << "\t<" << name << " value=\"" << vector.mdV[VX] << " " << vector.mdV[VY] << " " << vector.mdV[VZ] << "\"/>\n";
01120                                 break;
01121                         }
01122                         case TYPE_RECT:
01123                         {
01124                                 LLRect rect(control->get());
01125                                 file << "\t<" << name << " value=\"" << rect.mLeft << " " << rect.mBottom << " " << rect.getWidth() << " " << rect.getHeight() << "\"/>\n";
01126                                 break;
01127                         }
01128                         case TYPE_COL4:
01129                         {
01130                                 LLColor4 color(control->get());
01131                                 file << "\t<" << name << " value=\"" << color.mV[VRED] << ", " << color.mV[VGREEN] << ", " << color.mV[VBLUE] << ", " << color.mV[VALPHA] << "\"/>\n";
01132                                 break;
01133                         }
01134                         case TYPE_COL3:
01135                         {
01136                                 LLColor3 color(control->get());
01137                                 file << "\t<" << name << " value=\"" << color.mV[VRED] << ", " << color.mV[VGREEN] << ", " << color.mV[VBLUE] << "\"/>\n";
01138                                 break;
01139                         }
01140                         case TYPE_BOOLEAN:
01141                         {
01142                                 file << "\t<" << name << " value=\"" << (control->get().asBoolean() ? "TRUE" : "FALSE") << "\"/>\n";                    
01143                                 break;
01144                         }
01145                         case TYPE_STRING:
01146                         {
01147                                 file << "\t<" << name << " value=\"" << LLSDXMLFormatter::escapeString(control->get().asString()) << "\"/>\n";
01148                                 break;
01149                         }
01150                         default:
01151                         {
01152                                 CONTROL_ERRS << "LLControlGroup::saveToFile - unknown control type!" << llendl;
01153                                 break;
01154                         }
01155                 }
01156 
01157                 // Debug spam
01158                 // llinfos << name << " " << control->getValue().asString() << llendl;
01159         }// next
01160 
01161         file << "</settings>\n";
01162         file.close();
01163 
01164         return controls.getLength();
01165 }
01166 
01167 void LLControlGroup::applyOverrides(const std::map<std::string, std::string>& overrides)
01168 {
01169         for (std::map<std::string, std::string>::const_iterator iter = overrides.begin();
01170                  iter != overrides.end(); ++iter)
01171         {
01172                 const std::string& command = iter->first;
01173                 const std::string& value = iter->second;
01174                 LLControlBase* control = (LLControlBase *)mNameTable[command];
01175                 if (control)
01176                 {
01177                         switch(control->mType)
01178                         {
01179                         case TYPE_U32:
01180                                 control->set((LLSD::Integer)atof(value.c_str()));
01181                                 break;
01182                         case TYPE_S32:
01183                                 control->set((S32)atof(value.c_str()));
01184                                 break;
01185                         case TYPE_F32:
01186                                 control->set((F32)atof(value.c_str()));
01187                                 break;
01188                         case TYPE_BOOLEAN:
01189                                 if (!LLString::compareInsensitive(value.c_str(), "TRUE"))
01190                                 {
01191                                         control->set(TRUE);
01192                                 } 
01193                                 else if (!LLString::compareInsensitive(value.c_str(), "FALSE"))
01194                                 {
01195                                         control->set(FALSE);
01196                                 }
01197                                 else
01198                                 {
01199                                         control->set((BOOL)atof(value.c_str()));
01200                                 }
01201                                 break;
01202                         case TYPE_STRING:
01203                                 control->set(value);
01204                                 break;
01205 //                      // *FIX: implement this given time and need.
01206 //                      case TYPE_UUID:
01207 //                              break;
01208                         // we don't support command line overrides of vec3 or col4
01209                         // yet - requires parsing of multiple values
01210                         case TYPE_VEC3:
01211                         case TYPE_VEC3D:
01212                         case TYPE_COL4:
01213                         case TYPE_COL3:
01214                         default:
01215                                 break;
01216                         }
01217                 }
01218                 else
01219                 {
01220                         llinfos << "There is no control variable " << command << llendl;
01221                 }
01222         }
01223 }
01224 
01225 void LLControlGroup::resetToDefaults()
01226 {
01227         ctrl_name_table_t::iterator control_iter;
01228         for (control_iter = mNameTable.begin();
01229                 control_iter != mNameTable.end();
01230                 ++control_iter)
01231         {
01232                 LLControlBase* control = (*control_iter).second;
01233                 control->resetToDefault();
01234         }
01235 }
01236 
01237 //============================================================================
01238 // FIrst-use
01239 
01240 
01241 void LLControlGroup::addWarning(const LLString& name)
01242 {
01243         LLString warnname = "Warn" + name;
01244         if(!mNameTable[warnname])
01245         {
01246                 LLString comment = LLString("Enables ") + name + LLString(" warning dialog");
01247                 declareBOOL(warnname, TRUE, comment);
01248                 mWarnings.insert(warnname);
01249         }
01250 }
01251 
01252 BOOL LLControlGroup::getWarning(const LLString& name)
01253 {
01254         LLString warnname = "Warn" + name;
01255         return getBOOL(warnname);
01256 }
01257 
01258 void LLControlGroup::setWarning(const LLString& name, BOOL val)
01259 {
01260         LLString warnname = "Warn" + name;
01261         setBOOL(warnname, val);
01262 }
01263 
01264 void LLControlGroup::resetWarnings()
01265 {
01266         for (std::set<LLString>::iterator iter = mWarnings.begin();
01267                  iter != mWarnings.end(); ++iter)
01268         {
01269                 setBOOL(*iter, TRUE);
01270         }
01271 }
01272 
01273 
01274 
01275 //=============================================================================
01276 // Listener ID generator/management
01277 
01278 void    LLControlBase::releaseListenerID(S32    id)
01279 {       
01280         mFreeIDs.push_back(id);
01281 }
01282 
01283 S32     LLControlBase::allocateListenerID()
01284 {       
01285         if(mFreeIDs.size() == 0)
01286         {       //Out of IDs so generate some new ones.
01287                 for(int t=0;t<32;t++)
01288                 {
01289                         mFreeIDs.push_back(mTopID++);
01290                 }
01291         }
01292         S32     rtn = mFreeIDs.front();
01293         mFreeIDs.pop_front();
01294         mUsedIDs.push_back(rtn);
01295         return rtn;
01296 }
01297 
01298 bool LLControlBase::handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
01299 {
01300         if (event->desc() == "value_changed")
01301         {
01302                 setValue(((LLValueChangedEvent*)(LLEvent*)event)->mValue);
01303                 return TRUE;
01304         }
01305         return TRUE;
01306 }
01307 
01308 void LLControlBase::firePropertyChanged()
01309 {
01310         LLValueChangedEvent *evt = new LLValueChangedEvent(this, getValue());
01311         fireEvent(evt, "");
01312 }
01313 
01314 //============================================================================
01315 // Used to add a listener callback that will be called on the frame that the controls value changes
01316 
01317 S32 LLControl::addListener(LLControl::tListenerCallback* cbfn)
01318 {
01319         S32     id = allocateListenerID();
01320         mListeners.push_back(cbfn);
01321         mListenerIDs.push_back( id );
01322         return id;
01323 }
01324 
01325 void LLControl::updateListeners() {
01326         LLControl::tPropertyChangedListIter iter = mChangeEvents.begin();
01327         while(iter!=mChangeEvents.end()){
01328                 LLControl::tPropertyChangedEvent&       evt = *iter;
01329                 (*evt.mCBFN)(evt.mNewValue,evt.mID,*this);
01330                 iter++;
01331         }
01332         mChangeEvents.clear();
01333 }
01334 
01335 //static
01336 void    LLControlBase::updateAllListeners()
01337 {
01338         std::set< LLControlBase* >::iterator iter = mChangedControls.begin();
01339         while(iter != mChangedControls.end()){
01340                 (*iter)->updateListeners();
01341                 iter++;
01342         }
01343         mChangedControls.clear();
01344 }
01345 
01346 LLControl::LLControl(
01347         const LLString& name,
01348         eControlType type,
01349         LLSD initial,
01350         const LLString& comment,
01351         BOOL persist) :
01352         LLControlBase(name, type, comment, persist),
01353         mCurrent(initial),
01354         mDefault(initial)
01355 {
01356 }
01357 
01358 //============================================================================
01359 
01360 #ifdef TEST_HARNESS
01361 void main()
01362 {
01363         F32_CONTROL foo, getfoo;
01364 
01365         S32_CONTROL bar, getbar;
01366         
01367         BOOL_CONTROL baz;
01368 
01369         U32 count = gGlobals.loadFromFile("controls.ini");
01370         llinfos << "Loaded " << count << " controls" << llendl;
01371 
01372         // test insertion
01373         foo = new LLControl<F32>("gFoo", 5.f, 1.f, 20.f);
01374         gGlobals.addEntry("gFoo", foo);
01375 
01376         bar = new LLControl<S32>("gBar", 10, 2, 22);
01377         gGlobals.addEntry("gBar", bar);
01378 
01379         baz = new LLControl<BOOL>("gBaz", FALSE);
01380         gGlobals.addEntry("gBaz", baz);
01381 
01382         // test retrieval
01383         getfoo = (LLControl<F32>*) gGlobals.resolveName("gFoo");
01384         getfoo->dump();
01385 
01386         getbar = (S32_CONTROL) gGlobals.resolveName("gBar");
01387         getbar->dump();
01388 
01389         // change data
01390         getfoo->set(10.f);
01391         getfoo->dump();
01392 
01393         // Failure modes
01394 
01395         // ...min > max
01396         // badfoo = new LLControl<F32>("gFoo2", 100.f, 20.f, 5.f);
01397 
01398         // ...initial > max
01399         // badbar = new LLControl<S32>("gBar2", 10, 20, 100000);
01400 
01401         // ...misspelled name
01402         // getfoo = (F32_CONTROL) gGlobals.resolveName("fooMisspelled");
01403         // getfoo->dump();
01404 
01405         // ...invalid data type
01406         getfoo = (F32_CONTROL) gGlobals.resolveName("gFoo");
01407         getfoo->set(TRUE);
01408         getfoo->dump();
01409 
01410         // ...out of range data
01411         // getfoo->set(100000000.f);
01412         // getfoo->dump();
01413 
01414         // Clean Up
01415         delete foo;
01416         delete bar;
01417         delete baz;
01418 }
01419 #endif
01420 
01421 BOOL control_insert_before( LLControlBase* first, LLControlBase* second )
01422 {
01423         return ( first->getName().compare(second->getName()) < 0 );
01424 }
01425 

Generated on Thu Jul 1 06:08:23 2010 for Second Life Viewer by  doxygen 1.4.7