00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
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
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
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
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
00251
00252 default_value = a->Get();
00253
00254 }
00255 else
00256 {
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
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
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
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
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
00416
00417
00418
00419
00420
00421
00422
00423 #endif //PANGOLIN_VARS_H