vars.h
Go to the documentation of this file.
00001 /* This file is part of the Pangolin Project.
00002  * http://github.com/stevenlovegrove/Pangolin
00003  *
00004  * Copyright (c) 2011 Steven Lovegrove
00005  *
00006  * Permission is hereby granted, free of charge, to any person
00007  * obtaining a copy of this software and associated documentation
00008  * files (the "Software"), to deal in the Software without
00009  * restriction, including without limitation the rights to use,
00010  * copy, modify, merge, publish, distribute, sublicense, and/or sell
00011  * copies of the Software, and to permit persons to whom the
00012  * Software is furnished to do so, subject to the following
00013  * conditions:
00014  *
00015  * The above copyright notice and this permission notice shall be
00016  * included in all copies or substantial portions of the Software.
00017  *
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00019  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
00020  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00021  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
00022  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
00023  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00024  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00025  * OTHER DEALINGS IN THE SOFTWARE.
00026  */
00027 
00028 #ifndef PANGOLIN_VARS_H
00029 #define PANGOLIN_VARS_H
00030 
00031 #include <boost/foreach.hpp>
00032 #include <boost/algorithm/string.hpp>
00033 #include <boost/ptr_container/ptr_unordered_map.hpp>
00034 #include <sstream>
00035 #include <map>
00036 #include <vector>
00037 #include <iostream>
00038 #include <fstream>
00039 
00040 #include "vars_internal.h"
00041 
00042 namespace pangolin
00043 {
00044 
00046 // Interface
00048 
00049 template<typename T>
00050 struct Var
00051 {
00052     Var(const std::string& name, T default_value = T());
00053     Var(const std::string& name, T default_value, bool toggle);
00054     Var(const std::string& name,
00055         T default_value,
00056         double min,
00057         double max,
00058         bool logscale=false);
00059     Var(_Var& var);
00060 
00061     ~Var()
00062     {
00063         delete a;
00064     }
00065 
00066     operator const T& ();
00067     const T* operator->();
00068     void operator=(const T& val);
00069     void operator=(const Var<T>& val);
00070 
00071     void Init(const std::string& name,
00072               T default_value,
00073               double min = 0,
00074               double max = 0,
00075               int flags = 1,
00076               bool logscale = false);
00077     void SetDefault(const T& val);
00078     void Reset();
00079 
00080     _Var* var;
00081     Accessor<T>* a;
00082 };
00083 
00084 bool Pushed(Var<bool>& button);
00085 
00086 void ParseVarsFile(const std::string& filename);
00087 
00088 typedef void (*NewVarCallbackFn)(void* data, const std::string& name, _Var& var, const char* reg_type_name, bool brand_new);
00089 void RegisterNewVarCallback(NewVarCallbackFn callback, void* data, const std::string& filter = "");
00090 
00091 typedef void (*GuiVarChangedCallbackFn)(void* data, const std::string& name, _Var& var);
00092 void RegisterGuiVarChangedCallback(GuiVarChangedCallbackFn callback, void* data, const std::string& filter = "");
00093 
00094 template<typename T>
00095 T FromFile( const std::string& filename, const T& init = T());
00096 
00097 template<typename T>
00098 void FillFromFile( const std::string& filename, std::vector<T>& v, const T& init = T());
00099 
00100 template<typename T>
00101 struct SetVarFunctor
00102 {
00103     SetVarFunctor(const std::string& name, T val) : varName(name), setVal(val) {}
00104     void operator()()
00105     {
00106         Var<T>(varName).a->Set(setVal);
00107     }
00108     std::string varName;
00109     T setVal;
00110 };
00111 
00112 struct ToggleVarFunctor
00113 {
00114     ToggleVarFunctor(const std::string& name) : varName(name) {}
00115     void operator()()
00116     {
00117         Var<bool> val(varName);
00118         val = !val;
00119     }
00120     std::string varName;
00121 };
00122 
00124 // Implementation
00126 
00127 template<typename T>
00128 inline Var<T>::Var(const std::string& name, T default_value)
00129 {
00130     Init(name,default_value);
00131 }
00132 
00133 template<typename T>
00134 inline Var<T>::Var(const std::string& name, T default_value, bool toggle)
00135 {
00136     Init(name,default_value, 0, 1, toggle);
00137 }
00138 
00139 template<typename T>
00140 inline Var<T>::Var(const std::string& name,
00141                    T default_value,
00142                    double min,
00143                    double max,
00144                    bool logscale)
00145 {
00146     if (logscale)
00147     {
00148         if (min<=0 || max<=0)
00149         {
00150             throw std::runtime_error("LogScale: range of numbers must be positive!");
00151         }
00152         Init(name,default_value, log(min), log(max), 1, logscale);
00153     }
00154     else
00155         Init(name,default_value, min, max);
00156 
00157 }
00158 
00159 template<typename T>
00160 inline Var<T>::Var(_Var& var)
00161     : var(&var)
00162 {
00163     a = Accessor<T>::Create(var.type_name,var.val);
00164 }
00165 
00166 template<typename T>
00167 inline Var<T>::operator const T& ()
00168 {
00169     try
00170     {
00171         return a->Get();
00172     }
00173     catch(BadInputException)
00174     {
00175         Reset();
00176         return a->Get();
00177     }
00178 }
00179 
00180 template<typename T>
00181 inline const T* Var<T>::operator->()
00182 {
00183     try
00184     {
00185         return &(a->Get());
00186     }
00187     catch(BadInputException)
00188     {
00189         Reset();
00190         return &(a->Get());
00191     }
00192 }
00193 
00194 template<typename T>
00195 inline void Var<T>::operator=(const T& val)
00196 {
00197     a->Set(val);
00198 }
00199 
00200 template<typename T>
00201 inline void Var<T>::operator=(const Var<T>& v)
00202 {
00203     a->Set(v.a->Get());
00204 }
00205 
00206 
00207 struct NewVarCallback
00208 {
00209     NewVarCallback(const std::string& filter, NewVarCallbackFn fn, void* data)
00210         :filter(filter),fn(fn),data(data) {}
00211     std::string filter;
00212     NewVarCallbackFn fn;
00213     void* data;
00214 };
00215 
00216 struct GuiVarChangedCallback
00217 {
00218     GuiVarChangedCallback(const std::string& filter, GuiVarChangedCallbackFn fn, void* data)
00219         :filter(filter),fn(fn),data(data) {}
00220     std::string filter;
00221     GuiVarChangedCallbackFn fn;
00222     void* data;
00223 };
00224 
00225 extern boost::ptr_unordered_map<std::string,_Var> vars;
00226 extern std::vector<NewVarCallback> new_var_callbacks;
00227 extern std::vector<GuiVarChangedCallback> gui_var_changed_callbacks;
00228 
00229 template<typename T>
00230 inline void Var<T>::Init(const std::string& name,
00231                          T default_value,
00232                          double min,
00233                          double max,
00234                          int  flags,
00235                          bool logscale)
00236 {
00237     boost::ptr_unordered_map<std::string,_Var>::iterator vi = vars.find(name);
00238 
00239     std::vector<std::string> parts;
00240     boost::split(parts,name,boost::is_any_of("."));
00241 
00242 
00243     if( vi != vars.end() )
00244     {
00245         // found
00246         var = vi->second;
00247         a = Accessor<T>::Create(var->type_name,var->val);
00248         if( var->generic && var->type_name != typeid(T).name() )
00249         {
00250             // re-specialise this variable
00251             //      std::cout << "Specialising " << name << std::endl;
00252             default_value = a->Get();
00253 
00254         }
00255         else
00256         {
00257 //      // Meta info for variable
00258 //      var->meta_full_name = name;
00259 //      var->meta_friendly = parts.size() > 0 ? parts[parts.size()-1] : "";
00260 //      var->meta_range[0] = min;
00261 //      var->meta_range[1] = max;
00262 //      var->meta_flags = flags;
00263 //      var->logscale = logscale;
00264 //      var->meta_gui_changed = false;
00265 
00266             // notify those watching new variables
00267             BOOST_FOREACH(NewVarCallback& nvc, new_var_callbacks)
00268             if( boost::starts_with(name,nvc.filter) )
00269                 nvc.fn(nvc.data,name,*var, typeid(T).name(), false);
00270             return;
00271         }
00272         delete a;
00273     }
00274 
00275     // Create var of base type T
00276     {
00277         var = &vars[name];
00278 
00279         const double range = max - min;
00280         const int default_ticks = 5000;
00281         const double default_increment = range / default_ticks;
00282         Accessor<T>* da = 0;
00283 
00284         if( boost::is_same<T,bool>::value )
00285         {
00286             var->create(new bool, new bool, typeid(bool).name() );
00287             a = new _Accessor<T,bool>( *(bool*)var->val );
00288             da = new _Accessor<T,bool>( *(bool*)var->val_default );
00289         }
00290         else if( boost::is_integral<T>::value )
00291         {
00292             var->create(new int, new int, typeid(int).name() );
00293             var->meta_increment = std::max(1.0,default_increment);
00294             a = new _Accessor<T,int>( *(int*)var->val );
00295             da = new _Accessor<T,int>( *(int*)var->val_default );
00296         }
00297         else if( boost::is_scalar<T>::value )
00298         {
00299             var->create(new double, new double, typeid(double).name() );
00300             var->meta_increment = default_increment;
00301             a = new _Accessor<T,double>( *(double*)var->val );
00302             da = new _Accessor<T,double>( *(double*)var->val_default );
00303         }
00304         else
00305         {
00306             var->create(
00307                 new std::string(Convert<std::string,T>::Do(default_value)),
00308                 new std::string,
00309                 typeid(std::string).name()
00310             );
00311             a = new _Accessor<T,std::string>( *(std::string*)var->val );
00312             da = new _Accessor<T,std::string>( *(std::string*)var->val_default );
00313         }
00314 
00315         a->Set(default_value);
00316         da->Set(default_value);
00317         delete da;
00318 
00319         // Meta info for variable
00320         var->meta_full_name = name;
00321         var->meta_friendly = parts.size() > 0 ? parts[parts.size()-1] : "";
00322         var->meta_range[0] = min;
00323         var->meta_range[1] = max;
00324         var->meta_flags = flags;
00325         var->generic = false;
00326         var->logscale = logscale;
00327         var->meta_gui_changed = false;
00328 
00329         // notify those watching new variables
00330         BOOST_FOREACH(NewVarCallback& nvc, new_var_callbacks)
00331         if( boost::starts_with(name,nvc.filter) )
00332             nvc.fn(nvc.data,name,*var, typeid(T).name(), true);
00333     }
00334 }
00335 
00336 inline void ProcessHistoricCallbacks(NewVarCallbackFn callback, void* data, const std::string& filter)
00337 {
00338     for( boost::ptr_unordered_map<std::string,_Var>::iterator i = vars.begin();
00339             i != vars.end(); ++i )
00340     {
00341         const std::string& name = i->first;
00342 
00343         if( boost::starts_with(name,filter) )
00344         {
00345             callback(data,name,*(i->second), typeid(std::string).name(), false);
00346         }
00347     }
00348 
00349 }
00350 
00351 template<typename T>
00352 inline void Var<T>::SetDefault(const T& val)
00353 {
00354     Accessor<T>* da= Accessor<T>::Create(var->type_name, var->val_default );
00355     da->Set(val);
00356     delete da;
00357 }
00358 
00359 template<typename T>
00360 inline void Var<T>::Reset()
00361 {
00362     Accessor<T>* da= Accessor<T>::Create(var->type_name, var->val_default );
00363     a->Set(da->Get());
00364     delete da;
00365 }
00366 
00367 inline bool Pushed(Var<bool>& button)
00368 {
00369     bool val = button;
00370     button = false;
00371     return val;
00372 }
00373 
00374 inline bool Pushed(bool& button)
00375 {
00376     bool val = button;
00377     button = false;
00378     return val;
00379 }
00380 
00381 template<typename T>
00382 inline T FromFile( const std::string& filename, const T& init)
00383 {
00384     T out = init;
00385     std::ifstream f(filename.c_str());
00386     if( f.is_open() )
00387     {
00388         f >> out;
00389         f.close();
00390     }
00391     return out;
00392 }
00393 
00394 template<typename T>
00395 inline void FillFromFile( const std::string& filename, std::vector<T>& v, const T& init)
00396 {
00397     std::ifstream f(filename.c_str());
00398     if( f.is_open() )
00399     {
00400         while(!f.eof() && !f.fail())
00401         {
00402             T data = init;
00403             f >> data;
00404             if( !f.fail() )
00405             {
00406                 v.push_back(data);
00407             }
00408         }
00409         f.close();
00410     }
00411 }
00412 
00413 }
00414 
00415 //struct Example { Example() {} Example(int x, int y) :x(x),y(y) {} int x, y; };
00416 //ostream& operator<<(ostream& s, const Example& t) { s << t.x << "," << t.y; return s; }
00417 //istream& operator>>(istream& s, Example& t) {
00418 //  char delim; s >> t.x; s >> delim;
00419 //  if( delim != ',') s.setstate(ios::failbit);
00420 //  s >> t.y; return s;
00421 //}
00422 
00423 #endif //PANGOLIN_VARS_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines


pangolin_wrapper
Author(s): Todor Stoyanov
autogenerated on Wed Feb 13 2013 14:03:25