Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

plistSpecialty.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #ifndef INCLUDED_plistSpecialty_h_
00003 #define INCLUDED_plistSpecialty_h_
00004 
00005 #include "plist.h"
00006 #include "Shared/RobotInfo.h"
00007 #include "Shared/string_util.h"
00008 #include <limits>
00009 
00010 namespace plist {
00011 #ifdef FMAT_DEFAULT_DOUBLE
00012   typedef double PLISTREAL;
00013 #else
00014   typedef float PLISTREAL;
00015 #endif
00016 
00017   //! Handles mapping <string> elements to the appropriate numeric offset using Capabilities database
00018   /*! Values can be prefixed with the name of a model and '/' -- this is recommended for
00019    *  numeric values so they can be mapped portably to corresponding outputs on other models.
00020    *  This is not necessary when specifying output names, as the name is semantic and allows
00021    *  mapping through Capabilities.
00022    *
00023    *  By default, this class will accept any output offset, but through setRange(), can be configured
00024    *  to accept unactuated reference frames as well (e.g. CameraFrame).  Invalid offsets can either
00025    *  trigger an exception or simply reset to UNUSED depending on #throwOnInvalid.
00026    *  
00027    *  This class stores the numeric output offset so it can be indexed into arrays. */
00028   class OutputSelector : public Primitive<unsigned int> {
00029   public:
00030     enum { UNUSED=-1U };
00031     class bad_value : public std::exception {
00032     public:
00033       //! constructor for invalid/unknown output names, or known ones which are out-of-range if @a range is true
00034       explicit bad_value(const std::string& val, bool range=false) throw() : std::exception(), strValue(val), intValue(UNUSED), rangeError(range), message() { initMessage(); }
00035       //! constructor for invalid numeric output offsets, or known ones which are out-of-range if @a range is true
00036       explicit bad_value(unsigned int val, bool range=false) throw() : std::exception(), strValue(), intValue(val), rangeError(range), message() { initMessage(); }
00037       //! constructor for valid offsets which are out-of-range for this selector
00038       bad_value(const std::string& strVal, unsigned int intVal) throw() : std::exception(), strValue(strVal), intValue(intVal), rangeError(true), message() { initMessage(); }
00039       //! destructor
00040       virtual ~bad_value() throw() {}
00041       //! returns an error message describing the error
00042       virtual const char* what() const throw() { return message.c_str(); }
00043       void initMessage(); //!< initializes #message based on member fields
00044       std::string strValue; //!< the string value which caused the exception (may be empty if a numeric value was used, or an empty value was passed, see intValue to differentiate)
00045       unsigned int intValue; //!< the numeric value which caused the exception, -1U if strValue was invalid or empty
00046       bool rangeError; //!< true if the output was recognized as a known output, but out-of-range for this selector
00047       std::string message; //!< the string which be returned in what()
00048     };
00049     
00050     OutputSelector() : Primitive<unsigned int>(UNUSED), useNumeric(false), defModel(), saveModel(capabilities.getRobotName()), rangeBegin(0), rangeEnd(capabilities.getNumOutputs()), throwInvalid(false), throwUnused(false) {} //!< constructor
00051     OutputSelector(unsigned int v, bool isNum=false) : Primitive<unsigned int>(v), useNumeric(isNum), defModel(), saveModel(capabilities.getRobotName()), rangeBegin(0), rangeEnd(capabilities.getNumOutputs()), throwInvalid(false), throwUnused(false) {} //!< casting constructor
00052     OutputSelector& operator=(const std::string& v) { set(v); return *this; }
00053     OutputSelector& operator=(const unsigned int& v);
00054     OutputSelector& operator=(const OutputSelector& v) { operator=(v.val); return *this; }
00055     using Primitive<unsigned int>::operator=;
00056     
00057     void loadXML(xmlNode* node);
00058     void saveXML(xmlNode* node) const;
00059     void set(const std::string& str);
00060     using Primitive<unsigned int>::set;
00061     std::string get() const;
00062     
00063     void setNumeric(bool isNum) { useNumeric=isNum; } //!< sets #useNumeric
00064     bool getNumeric() const { return useNumeric; } //!< returns #useNumeric
00065     
00066     void setDefaultModel(const std::string& name) { defModel = name; } //!< sets #defModel
00067     const std::string& getDefaultModel() const { return defModel; } //!< returns #defModel
00068     
00069     void setSaveModel(const std::string& name) { saveModel = name; } //!< sets #saveModel
00070     const std::string& getSaveModel() const { return saveModel; } //!< returns #saveModel
00071     
00072     //! Sets range of acceptable output offsets between @a begin (inclusive) and @a end (exclusive).
00073     /*! You could use this to restrict the type of outputs which can be assigned (e.g. LEDOffset to LEDOffset+NumLEDs),
00074      *  or to expand the range to include unactuated reference frames (0 to NumReferenceFrames) */
00075     void setRange(unsigned int begin, unsigned int end);
00076     unsigned int getRangeBegin() const { return rangeBegin; } //!< returns #rangeBegin
00077     unsigned int getRangeEnd() const { return rangeEnd; } //!< returns #rangeEnd
00078     
00079     void throwOnInvalid(bool b) { throwInvalid=b; } //!< sets #throwInvalid
00080     bool throwOnInvalid() const { return throwInvalid; } //!< returns #throwInvalid
00081     
00082     //! clone definition for OutputSelector
00083     PLIST_CLONE_DEF(OutputSelector,new OutputSelector(val));
00084   protected:
00085     //! If true, requests that saves store the numeric value instead of corresponding output name
00086     bool useNumeric;
00087     //! Stores the model to assume when loading a numeric output offset without a model specifier *from a string/file*, blank means current global #capabilities
00088     std::string defModel;
00089     //! If non-empty, indicates the model specifier to use when saving as a numeric (#useNumeric)
00090     /*! This is set whenever a value with a specifier is loaded from a file. */
00091     std::string saveModel;
00092     //! the first acceptable output offset, lower offsets will be set as #UNUSED
00093     unsigned int rangeBegin;
00094     //! The one-past-last acceptable output offset, higher offsets will be set as #UNUSED.
00095     unsigned int rangeEnd;
00096     //! If true, out-of-range or unknown values will throw an OutputSelector::bad_value exception instead of being marked UNUSED
00097     bool throwInvalid;
00098     //! If true, will throw an OutputSelector::bad_value exception for attempts to explicitly mark the output UNUSED (e.g. empty string, -1U numeric...)
00099     bool throwUnused;
00100   };
00101 
00102   //! Handles angle measurements by adding a 'unit' attribute to numeric values, or a character suffix in a string value. */
00103   /*! Values are always stored in radians, but may be converted from/to degrees when loading/saving.
00104    *
00105    *  Valid values for a 'unit' attribute are: rad, radian, radians, °, deg, degree, degrees, π, pi, %, percent.
00106    *
00107    *  Valid values for a suffix are: °, π, π/, %.  The 'π/' should be followed by another number to form a fraction, e.g. '3π/2' or 'π/3'.
00108    *
00109    *  To conform completely to Apple's plist specification, the 'unit' attribute should be avoided,
00110    *  and unit suffixes should only be used in 'string' elements.  This code can handle both, but other
00111    *  editors might not.  Use of the setPedantic() function can give a warning when such values are
00112    *  loaded, and rely on solely on strings for non-radian values.
00113    */
00114   class Angle : public Primitive<PLISTREAL> {
00115   public:
00116     enum Format {
00117       FORMAT_NONE, //!< value will be in radians, but no unit will be specified
00118       FORMAT_RADIAN, //!< value will be in radians
00119       FORMAT_DEGREE, //!< value will be in degrees
00120       FORMAT_PI, //!< value will be multiple of pi
00121       FORMAT_PERCENT, //!< value will be a percentage of a circle
00122       FORMAT_SAME, //!< use same units that was loaded, or 'auto' if not loaded
00123       FORMAT_AUTO //!< uses degrees if value works out to be a integer, or raw radian otherwise
00124     };
00125     
00126     enum Pedantic {
00127       PEDANTIC_FULL, //!< uses 'string' elements for plist compliance, though less intuitive since these are really numeric values
00128       PEDANTIC_VALID, //!< uses a 'unit' attribute on the value element to specify the units... may be stripped by editor, but validates
00129       PEDANTIC_CUTE //!< uses a 'real' element, regardless of presence of suffix... editor may refuse to open due to non-numeric characters
00130     };
00131     
00132     Angle() : Primitive<PLISTREAL>(0), saveFormat(FORMAT_SAME), loadedFormat(FORMAT_AUTO) {} //!< constructor
00133     Angle(PLISTREAL v) : Primitive<PLISTREAL>(v), saveFormat(FORMAT_SAME), loadedFormat(FORMAT_AUTO) {} //!< casting constructor
00134     Angle& operator=(const std::string& v) { set(v); return *this; }
00135     using Primitive<PLISTREAL>::operator=;
00136     
00137     void loadXML(xmlNode* node);
00138     void saveXML(xmlNode* node) const;
00139     void set(const std::string& str);
00140     using Primitive<PLISTREAL>::set;
00141     void setDegree(PLISTREAL v) { operator=(v/180*static_cast<PLISTREAL>(M_PI)); }
00142     PLISTREAL getDegree() const { return val/static_cast<PLISTREAL>(M_PI)*180; }
00143     std::string get() const;
00144     
00145     void setFormat(Format fmt) { saveFormat=fmt; } //!< sets #saveFormat
00146     Format getFormat() const { return saveFormat; } //!< returns #saveFormat
00147     Format getLoadedFormat() const { return loadedFormat; } // !< returns #loadedFormat
00148     
00149     static void setDefaultFormat(Format fmt) { defaultFormat = fmt; } //!< sets #defaultFormat
00150     static Format getDefaultFormat() { return defaultFormat; } //!< returns #defaultFormat
00151     
00152     static void setPedantic(Pedantic p) { pedantic=p; } //!< sets #pedantic
00153     static Pedantic getPedantic() { return pedantic; } //!< returns #pedantic
00154     
00155     //! clone definition for Angle
00156     PLIST_CLONE_DEF(Angle,new Angle(val));
00157   protected:
00158     void parseRadian(const std::string& str);
00159     
00160     //! Specifies what format we should save in
00161     Format saveFormat;
00162     //! Specifies the format last loaded (to be reused if saveFormat is FORMAT_SAME)
00163     Format loadedFormat;
00164     //! The format to use if loadedFormat is FORMAT_AUTO;
00165     static Format defaultFormat;
00166     //! If true, saved elements will use 'string' instead of 'real' with an element, and warnings will be issued
00167     static Pedantic pedantic;
00168   };
00169   
00170   //! A simple class for storing 3D points, will be serialized as an array and provides operator[], but you can also use the #x, #y, #z fields directly if preferred
00171   class Point : public virtual plist::ArrayOf<plist::Primitive<PLISTREAL> > {
00172   public:
00173     typedef PLISTREAL storage_t; //!< storage type for point (could make this a template, seems unnnecessary)
00174     
00175     //! constructor
00176     Point() : x(0), y(0), z(0) { init(); }
00177     //! constructor with data point
00178     Point(storage_t x_, storage_t y_, storage_t z_) : x(x_), y(y_), z(z_) { init(); }
00179     //! copy constructor
00180     /*! This version is needed in addition to the templated 'copy constructor', gcc doesn't recognize,
00181      *  template instance as copy constructor, winds up creating another default copy constructor
00182      *  which doesn't init properly */
00183     Point(const Point& p) : x(p[0]), y(p[1]), z(p[2]) { init(); }
00184     //! conversion from other point class (e.g. C array, fmat::Column, std::vector, etc.)
00185     template<class T> Point(const T& p) : x(p[0]), y(p[1]), z(p[2]) { init(); }
00186     
00187     //! copies data from @a a via T::operator[] into (x, y, z), returns *this for convenience
00188     template<typename T> Point& importFrom(const T& a) { x=a[0]; y=a[1]; z=a[2]; return *this; }
00189     //! copies data from (x, y, z) into a T instance via T(x,y,z) constructor call
00190     template<typename T> T construct() const { return T(x,y,z); }
00191     //! copies data from (x, y, z) into a T instance via T::operator[]
00192     template<typename T> T exportTo() const { T a; a[0]=x; a[1]=y; a[2]=z; return a; }
00193     //! copies data from (x, y, z) into @a a via T::operator[], returns reference to a for convenience
00194     template<typename T> T& exportTo(T& a) const { a[0]=x; a[1]=y; a[2]=z; return a; }
00195     
00196     //! sets x,y,z values
00197     void set(storage_t x_, storage_t y_, storage_t z_) { x=x_; y=y_; z=z_; }
00198     using plist::ArrayOf<plist::Primitive<PLISTREAL> >::set;
00199     
00200     void saveXML(xmlNode* node) const {
00201       if(node==NULL)
00202         return;
00203       if(x==y && y==z) {
00204         x.saveXML(node);
00205       } else {
00206         plist::ArrayOf<plist::Primitive<storage_t> >::saveXML(node);
00207       }
00208     }
00209     void loadXML(xmlNode* node) {
00210       if(node==NULL)
00211         return;
00212       if(xNodeHasName(node,"real")) {
00213         x.loadXML(node);
00214         z = y = x;
00215       } else {
00216         plist::ArrayOf<plist::Primitive<storage_t> >::loadXML(node);
00217       }
00218     }
00219     
00220     plist::Primitive<storage_t> x; //!< x coordinate
00221     plist::Primitive<storage_t> y; //!< y coordinate
00222     plist::Primitive<storage_t> z; //!< z coordinate
00223     
00224   protected:
00225     //! add entries for data fields
00226     void init() {
00227       addEntry(x);
00228       addEntry(y);
00229       addEntry(z);
00230       setLoadSavePolicy(FIXED,SYNC);
00231       setSaveInlineStyle(true);
00232     }     
00233   };
00234     
00235   
00236   template<class T>
00237   class RGBColor : virtual public DictionaryOf<plist::Primitive<T> >, virtual public ArrayOf<plist::Primitive<T> > {
00238   public:
00239     RGBColor() : DictionaryOf<plist::Primitive<T> >(), ArrayOf<plist::Primitive<T> >(), red(0), green(0), blue(0), alpha(255) { init(); }
00240     RGBColor(T r, T g, T b, T a=getMax()) : DictionaryOf<plist::Primitive<T> >(), ArrayOf<plist::Primitive<T> >(), red(r), green(g), blue(b), alpha(a) { init(); }
00241     
00242     plist::Primitive<T> red;
00243     plist::Primitive<T> green;
00244     plist::Primitive<T> blue;
00245     plist::Primitive<T> alpha;
00246     
00247     virtual void loadXML(xmlNode * node);
00248     virtual void saveXML(xmlNode * node) const;
00249     using DictionaryOf<plist::Primitive<T> >::saveXML;
00250     virtual void set(const RGBColor<T>& x);
00251     virtual void set(const plist::ObjectBase& x);
00252     virtual void set(const std::string& str);
00253     using DictionaryOf<plist::Primitive<T> >::set;
00254     using ArrayOf<plist::Primitive<T> >::set;
00255     using DictionaryOf<plist::Primitive<T> >::operator[];
00256     using ArrayOf<plist::Primitive<T> >::operator[];
00257     // to avoid 'ambiguous' usage of rgb[0] (size_t vs. string constructor)
00258     plist::Primitive<T>& operator[](int i) { return ArrayOf<plist::Primitive<T> >::operator[](i); }
00259     const plist::Primitive<T>& operator[](int i) const { return ArrayOf<plist::Primitive<T> >::operator[](i); }
00260     
00261     virtual std::string toString() const;
00262     
00263     virtual size_t size() const { return ArrayOf<plist::Primitive<T> >::size(); }
00264 
00265     virtual void clear() {
00266       DictionaryOf<plist::Primitive<T> >::clear();
00267       ArrayOf<plist::Primitive<T> >::clear();
00268       init();
00269     }
00270     
00271     ObjectBase* resolveEntry(const std::string& s) const {
00272       ObjectBase* obj = DictionaryOf<plist::Primitive<T> >::resolveEntry(s);
00273       return (obj!=NULL) ? obj : ArrayOf<plist::Primitive<T> >::resolveEntry(s);
00274     }
00275     unsigned int getLongestKeyLen(const regex_t* reg, unsigned int depth) const { return DictionaryOf<plist::Primitive<T> >::getLongestKeyLen(reg,depth); }
00276     virtual bool canContain(const ObjectBase& obj) { return DictionaryOf<plist::Primitive<T> >::canContain(obj); }
00277     
00278     PLIST_CLONE_DEF(RGBColor,new RGBColor<T>(red,green,blue,alpha));
00279 
00280   protected:
00281     virtual void fireEntryRemoved(ObjectBase& val);
00282     
00283     static float makeFloat(const T& v) { return v/(float)getMax(); }
00284     static int makeInt(const T& v) { return static_cast<int>(makeFloat(v)*255 + 0.5); }
00285     static T fromByte(unsigned char x) { return static_cast<T>(x)<<(8*(sizeof(T)-sizeof(unsigned char))); }
00286     static T fromReal(double x) { return static_cast<T>(x*getMax()+.5); }
00287     static T getMax() { return std::numeric_limits<T>::max(); }
00288     static void setNumeric(plist::Primitive<T>&) {}
00289     
00290     void init() {
00291       DictionaryOf<plist::Primitive<T> >::addEntry("Red",red);
00292       DictionaryOf<plist::Primitive<T> >::addEntry("Green",green);
00293       DictionaryOf<plist::Primitive<T> >::addEntry("Blue",blue);
00294       DictionaryOf<plist::Primitive<T> >::addEntry("Alpha",alpha);
00295       ArrayOf<plist::Primitive<T> >::addEntry(red);
00296       ArrayOf<plist::Primitive<T> >::addEntry(green);
00297       ArrayOf<plist::Primitive<T> >::addEntry(blue);
00298       ArrayOf<plist::Primitive<T> >::addEntry(alpha);
00299       setNumeric(red);
00300       setNumeric(green);
00301       setNumeric(blue);
00302       setNumeric(alpha);
00303       Collection::setLoadSavePolicy(Collection::FIXED,Collection::SYNC);
00304       ArrayOf<plist::Primitive<T> >::setSaveInlineStyle(true);
00305     }
00306   };
00307   
00308   template<> inline float RGBColor<float>::getMax() { return 1; }
00309   template<> inline double RGBColor<double>::getMax() { return 1; }
00310   
00311   template<> inline unsigned char RGBColor<unsigned char>::fromByte(unsigned char x) { return x; }
00312   template<> inline char RGBColor<char>::fromByte(unsigned char x) { return static_cast<int>(x)-128; }
00313   template<> inline float RGBColor<float>::fromByte(unsigned char x) { return x/255.f; }
00314   template<> inline double RGBColor<double>::fromByte(unsigned char x) { return x/255.0; }
00315   
00316   template<> inline float RGBColor<float>::fromReal(double x) { return static_cast<float>(x); }
00317   template<> inline double RGBColor<double>::fromReal(double x) { return x; }
00318   
00319   template<> inline void RGBColor<char>::setNumeric(plist::Primitive<char>& n) { n.setNumeric(true); }
00320   template<> inline void RGBColor<unsigned char>::setNumeric(plist::Primitive<unsigned char>& n) { n.setNumeric(true); }
00321   
00322   template<class T> void RGBColor<T>::loadXML(xmlNode * node) {
00323     if(ObjectBase::xNodeHasName(node,"array")) {
00324       ArrayOf<plist::Primitive<T> >::loadXML(node);
00325     } else if(ObjectBase::xNodeHasName(node,"dict")) {
00326       DictionaryOf<plist::Primitive<T> >::loadXML(node);
00327     } else if(ObjectBase::xNodeHasName(node,"string")) {
00328       xmlChar * cont=xmlNodeGetContent(node);
00329       try {
00330         set(std::string((const char*)cont));
00331       } catch(const XMLLoadSave::bad_format& err) {
00332         xmlFree(cont);
00333         throw XMLLoadSave::bad_format(node,err.what()); //add current node to exception and rethrow
00334       } catch(...) {
00335         xmlFree(cont);
00336         throw;
00337       }
00338       xmlFree(cont);
00339     } else {
00340       std::stringstream ss;
00341       ss << "plist::RGBColor can't accept value of type "<< ObjectBase::xNodeGetName(node);
00342       ss << ", (try CSS-style string or array of RGB values in range 0-" << getMax() << ")";
00343       throw XMLLoadSave::bad_format(node,ss.str());
00344     }
00345   }
00346   
00347   template<class T> void RGBColor<T>::saveXML(xmlNode * node) const {
00348     if(ObjectBase::xNodeHasName(node,"array")) {
00349       ArrayOf<plist::Primitive<T> >::saveXML(node);
00350     } else if(ObjectBase::xNodeHasName(node,"dict")) {
00351       DictionaryOf<plist::Primitive<T> >::saveXML(node);
00352     } else {
00353       xmlNodeSetName(node,(const xmlChar*)"string");
00354       xmlNodeSetContent(node,(const xmlChar*)toString().c_str());
00355     }
00356   }
00357   
00358   template<class T> void RGBColor<T>::set(const RGBColor<T>& v) {
00359     red=v.red;
00360     green=v.green;
00361     blue=v.blue;
00362     alpha=v.alpha;
00363   }
00364   template<class T> void RGBColor<T>::set(const plist::ObjectBase& x) {
00365     if(const RGBColor * v = dynamic_cast<const RGBColor*>(&x)) {
00366       set(*v);
00367     } else if(const DictionaryBase * d = dynamic_cast<const DictionaryBase*>(&x)) {
00368       DictionaryOf<plist::Primitive<T> >::set(*d);
00369     } else if(const ArrayBase * a = dynamic_cast<const ArrayBase*>(&x)) {
00370       ArrayOf<plist::Primitive<T> >::set(*a);
00371     }
00372   }
00373   
00374   template<class T> void RGBColor<T>::set(const std::string& str) {
00375     std::string s = string_util::makeLower(string_util::trim(str));
00376     if(s[0]=='#') {
00377       if(s.size()==4) {
00378         for(unsigned int i=0; i<3; ++i) {
00379           unsigned char x=0;
00380           if('0'<=s[i+1] && s[i+1]<='9')
00381             x = s[i+1]-'0';
00382           else if('a'<=s[i+1] && s[i+1]<='f')
00383             x = s[i+1]-'a'+10;
00384           else
00385             throw XMLLoadSave::bad_format(NULL,"plist::RGBColor bad character in hex specification: "+str);
00386           ArrayOf<plist::Primitive<T> >::operator[](i)=fromByte(x*16+x);
00387         }
00388         alpha=getMax();
00389       } else if(s.size()==7) {
00390         for(unsigned int i=0; i<3; ++i) {
00391           char ca=s[i*2+1], cb=s[i*2+2];
00392           unsigned char xa=0, xb=0;
00393           if('0'<=ca && ca<='9')
00394             xa = ca-'0';
00395           else if('a'<=ca && ca<='f')
00396             xa = ca-'a'+10;
00397           else
00398             throw XMLLoadSave::bad_format(NULL,"plist::RGBColor bad character in hex specification: "+str);
00399           if('0'<=cb && cb<='9')
00400             xb = cb-'0';
00401           else if('a'<=cb && cb<='f')
00402             xb = cb-'a'+10;
00403           else
00404             throw XMLLoadSave::bad_format(NULL,"plist::RGBColor bad character in hex specification: "+str);
00405           ArrayOf<plist::Primitive<T> >::operator[](i)=fromByte(xa*16+xb);
00406         }
00407         alpha=getMax();
00408       } else {
00409         throw XMLLoadSave::bad_format(NULL,"plist::RGBColor wrong number of characters (3 or 6) in hex specification: "+str);
00410       }
00411     } else if(s.substr(0,4)=="rgb(") {
00412       std::vector<std::string> tok = string_util::tokenize(s.substr(4),",");
00413       if(tok.size()!=3)
00414         throw XMLLoadSave::bad_format(NULL,"plist::RGBColor expects three arguments for rgb() specification");
00415       for(unsigned int i=0; i<tok.size(); ++i) {
00416         std::string t = string_util::trim(tok[i]);
00417         if(t[t.size()-1]=='%') {
00418           float x;
00419           std::stringstream(t.substr(0,t.size()-1)) >> x;
00420           ArrayOf<plist::Primitive<T> >::operator[](i)=fromReal(x/100.0);
00421         } else {
00422           unsigned int x;
00423           std::stringstream(t) >> x;
00424           ArrayOf<plist::Primitive<T> >::operator[](i)=fromByte(x);
00425         }
00426       }
00427       alpha=getMax();
00428     } else if(s.substr(0,5)=="rgba(") {
00429       std::vector<std::string> tok = string_util::tokenize(s.substr(5),",");
00430       if(tok.size()!=4)
00431         throw XMLLoadSave::bad_format(NULL,"plist::RGBColor expects four arguments for rgba() specification");
00432       for(unsigned int i=0; i<3; ++i) {
00433         std::string t = string_util::trim(tok[i]);
00434         if(t[t.size()-1]=='%') {
00435           double x;
00436           std::stringstream(t.substr(0,t.size()-1)) >> x;
00437           ArrayOf<plist::Primitive<T> >::operator[](i)=fromReal(x/100.0);
00438         } else {
00439           unsigned int x;
00440           std::stringstream(t) >> x;
00441           ArrayOf<plist::Primitive<T> >::operator[](i)=fromByte(x);
00442         }
00443       }
00444       std::string t = string_util::trim(tok[3]);
00445       double x;
00446       std::stringstream(t) >> x;
00447       alpha=fromReal(x);
00448     } else {
00449       if(s=="black") {
00450         red=green=blue=0;
00451       } else if(s=="silver") {
00452         red=green=blue=fromByte(0xC0);
00453       } else if(s=="gray") {
00454         red=green=blue=fromByte(0x80);
00455       } else if(s=="white") {
00456         red=green=blue=fromByte(0xFF);
00457       } else if(s=="maroon") {
00458         red=fromByte(0x80); green=blue=0;
00459       } else if(s=="red") {
00460         red=fromByte(0xFF); green=blue=0;
00461       } else if(s=="purple") {
00462         red=blue=fromByte(0x80); green=0;
00463       } else if(s=="fuchsia") {
00464         red=blue=fromByte(0xFF); green=0;
00465       } else if(s=="green") {
00466         green=fromByte(0x80); red=blue=0;
00467       } else if(s=="lime") {
00468         green=fromByte(0xFF); red=blue=0;
00469       } else if(s=="olive") {
00470         red=green=fromByte(0x80); blue=0;
00471       } else if(s=="yellow") {
00472         red=green=fromByte(0xFF); blue=0;
00473       } else if(s=="navy") {
00474         blue=fromByte(0x80); red=green=0;
00475       } else if(s=="blue") {
00476         blue=fromByte(0xFF); red=green=0;
00477       } else if(s=="teal") {
00478         green=blue=fromByte(0x80); red=0;
00479       } else if(s=="aqua") {
00480         green=blue=fromByte(0xFF); red=0;
00481       } else {
00482         throw XMLLoadSave::bad_format(NULL,"plist::RGBColor unknown specification: "+str);
00483       }
00484       alpha=getMax();
00485     }
00486   }
00487   
00488   template<class T> std::string RGBColor<T>::toString() const {
00489     std::stringstream ss;
00490     ss << (alpha!=getMax() ? "rgba(" : "rgb(");
00491     ss << makeInt(red) << ',' << makeInt(green) << ',' << makeInt(blue);
00492     if(alpha!=getMax())
00493       ss << ',' << makeFloat(alpha);
00494     ss <<')';
00495     return ss.str();
00496   }
00497   
00498   PLIST_CLONE_IMPT(T,RGBColor,new RGBColor<T>(red,green,blue,alpha));
00499 
00500   template<class T> void RGBColor<T>::fireEntryRemoved(ObjectBase& val) {
00501     Collection::fireEntryRemoved(val);
00502     std::set<ObjectBase*>::iterator it=DictionaryOf<plist::Primitive<T> >::myRef.find(&val);
00503     bool deleted=false;
00504     if(it!=DictionaryOf<plist::Primitive<T> >::myRef.end()) {
00505       DictionaryOf<plist::Primitive<T> >::myRef.erase(it);
00506       if(!deleted) {
00507         delete &val;
00508         deleted=true;
00509       }
00510     }
00511     it=ArrayOf<plist::Primitive<T> >::myRef.find(&val);
00512     if(it!=ArrayOf<plist::Primitive<T> >::myRef.end()) {
00513       ArrayOf<plist::Primitive<T> >::myRef.erase(it);
00514       if(!deleted) {
00515         delete &val;
00516         deleted=true;
00517       }
00518     }
00519   }
00520 }
00521 
00522 /*! @file
00523  * @brief 
00524  * @author Ethan Tira-Thompson (ejt) (Creator)
00525  */
00526 
00527 #endif

Tekkotsu v5.1CVS
Generated Mon May 9 04:58:49 2016 by Doxygen 1.6.3