Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

ConfigurationEditor.cc

Go to the documentation of this file.
00001 #include "ConfigurationEditor.h"
00002 #include "Behaviors/Controls/NullControl.h"
00003 #include "Shared/plistCollections.h"
00004 #include "Shared/Config.h"
00005 #include "Shared/string_util.h"
00006 #include "Wireless/Wireless.h"
00007 #include <exception>
00008 
00009 using namespace std; 
00010 
00011 void ConfigurationEditor::init() {
00012   if(root==NULL)
00013     setRootCollection(config);
00014   pushSlot(NULL); // just to mark as having sub-nodes, will replace during refresh
00015 }
00016 
00017 void ConfigurationEditor::refresh() {
00018   plist::Collection * curcol = (path.size()==0) ? root : dynamic_cast<plist::Collection*>(root->resolveEntry(path));
00019   if(curcol==NULL) {
00020     clearSlots();
00021     pushSlot(new NullControl("[NULL Collection]"));
00022     ControlBase::refresh();
00023     return;
00024   }
00025   for(unsigned int i=0; i<options.size(); ++i) {
00026     if(StringInputControl * input = dynamic_cast<StringInputControl*>(options[i])) {
00027       if(input->getLastInput().size()>0) {
00028         plist::PrimitiveBase * prim=NULL;
00029         if(dynamic_cast<plist::DictionaryBase*>(curcol)) {
00030           std::string key=input->getName();
00031           key=key.substr(0,key.find('='));
00032           prim = dynamic_cast<plist::PrimitiveBase*>(curcol->resolveEntry(key));
00033           if(prim==NULL) {
00034             std::cerr << "ERROR: key " << key << " was set but does not correspond to a primitive value" << std::endl;
00035             continue;
00036           }
00037         } else if(plist::ArrayBase* arr = dynamic_cast<plist::ArrayBase*>(curcol)) {
00038           prim = dynamic_cast<plist::PrimitiveBase*>(&arr->getEntry(i-3));
00039           if(prim==NULL) {
00040             std::cerr << "ERROR: array entry " << i-3 << " is a collection, cannot set value" << std::endl;
00041             continue;
00042           }
00043         } else {
00044           std::cerr << "ERROR: unknown collection type" << std::endl;
00045           break;
00046         }
00047          
00048         try {
00049           prim->set(input->getLastInput());
00050         } catch(const std::exception& e) {
00051           std::cerr << "ERROR: unable to set item " << i << " to value " << input->getLastInput() << '\n'
00052           << "        An exception occurred: " << e.what() << std::endl;
00053         } catch(...) {
00054           std::cerr << "ERROR: unable to set item '" << i << "' to value '" << input->getLastInput() << "', an exception occurred." << std::endl;
00055         }
00056       }
00057     }
00058   }
00059   
00060   for(std::vector<ControlBase*>::iterator it=options.begin(); it!=options.end(); ++it)
00061     if(*it!=NULL && *it!=&load && *it!=&save)
00062       delete *it;
00063   options.clear();
00064   pushSlot(&load);
00065   pushSlot(&save);
00066   pushSlot(NULL);
00067   if(curcol->size()==0) {
00068     pushSlot(new NullControl("[Empty Collection]"));
00069   } else if(plist::DictionaryBase * d = dynamic_cast<plist::DictionaryBase*>(curcol)) {
00070     for(plist::DictionaryBase::const_iterator it=d->begin(); it!=d->end(); ++it) {
00071       if(plist::NamedEnumerationBase * neb = dynamic_cast<plist::NamedEnumerationBase*>(it->second)) {
00072         pushSlot(new NamedEnumerationEditor(it->first+"="+neb->get(),d->getComment(it->first),*neb));
00073       } else if(plist::PrimitiveBase * po = dynamic_cast<plist::PrimitiveBase*>(it->second)) {
00074         pushSlot(new StringInputControl(it->first+"="+po->get(),d->getComment(it->first)));
00075       } else if(dynamic_cast<plist::Collection*>(it->second)) {
00076         ConfigurationEditor * sube = new ConfigurationEditor(it->first,d->getComment(it->first),root);
00077         sube->setPath(path.size()==0 ? it->first : path+plist::Collection::subCollectionSep()+it->first);
00078         pushSlot(sube);
00079       } else {
00080         std::cerr << "WARNING: unknown type for " << it->first << ": " << it->second->toString() << std::endl;
00081       }
00082     }
00083   } else if(plist::ArrayBase * a = dynamic_cast<plist::ArrayBase*>(curcol)) {
00084     for(unsigned int i=0; i<a->size(); ++i) {
00085       if(plist::NamedEnumerationBase * neb = dynamic_cast<plist::NamedEnumerationBase*>(&a->getEntry(i))) {
00086         pushSlot(new NamedEnumerationEditor(neb->get(),a->getComment(i),*neb));
00087       } else if(plist::PrimitiveBase * po = dynamic_cast<plist::PrimitiveBase*>(&a->getEntry(i))) {
00088         pushSlot(new StringInputControl(po->get(),a->getComment(i)));
00089       } else if(dynamic_cast<plist::Collection*>(&a->getEntry(i))) {
00090         stringstream en;
00091         en << "[Entry " << i << "]";
00092         ConfigurationEditor * sube = new ConfigurationEditor(en.str(),a->getComment(i),root);
00093         stringstream ss;
00094         if(path.size()==0)
00095           ss << i;
00096         else
00097           ss << path << plist::Collection::subCollectionSep() << i;
00098         sube->setPath(ss.str());
00099         pushSlot(sube);
00100       } else {
00101         std::cerr << "WARNING: unknown type for entry " << i << ": " << a->getEntry(i).toString() << std::endl;
00102       }
00103     }
00104   }
00105   ControlBase::refresh();
00106 }
00107 
00108 void ConfigurationEditor::clearSlots() {
00109   // don't erase load or save controls -- we'll reuse them
00110   for(std::vector<ControlBase*>::iterator it=options.begin(); it!=options.end(); ++it)
00111     if(*it==&load || *it==&save)
00112       *it=NULL;
00113   ControlBase::clearSlots();
00114 }
00115 
00116 void ConfigurationEditor::setRootCollection(plist::Collection* rootCollection) {
00117   if(root==rootCollection)
00118     return;
00119   root=rootCollection;
00120   load.setRootCollection(root);
00121   save.setRootCollection(root);
00122   for(unsigned int i=0; i<options.size(); i++)
00123     if(ConfigurationEditor * confe = dynamic_cast<ConfigurationEditor*>(options[i]))
00124       confe->setRootCollection(root);
00125 }
00126 
00127 void ConfigurationEditor::setPath(const std::string& p) {
00128   path=p;
00129 }
00130 
00131 plist::Dictionary& ConfigurationEditor::getObjectTemplates() {
00132   static plist::Dictionary dict;
00133   if(dict.size()==0) {
00134     //first call, set up
00135     dict.addEntry("float",new plist::Primitive<float>);
00136     dict.addEntry("int",new plist::Primitive<int>);
00137     dict.addEntry("int (unsigned)",new plist::Primitive<unsigned int>);
00138     dict.addEntry("string",new plist::Primitive<std::string>);
00139     dict.addEntry("sub-array",new plist::Array);
00140     dict.addEntry("sub-dictionary",new plist::Dictionary);
00141   }
00142   return dict;
00143 }
00144 
00145 ControlBase* ConfigurationEditor::LoadSettings::selectedFile(const std::string& f) {
00146   if(rootcol==NULL) {
00147     std::cerr << "ERROR: Unable to load, no plist::Collection has been provided" << std::endl;
00148     return NULL;
00149   }
00150   rootcol->loadFile(f.c_str());
00151   return NULL;
00152 }
00153 ControlBase* ConfigurationEditor::SaveSettings::selectedFile(const std::string& f) {
00154   if(rootcol==NULL) {
00155     std::cerr << "ERROR: Unable to save, no plist::Collection has been provided" << std::endl;
00156     return NULL;
00157   }
00158   rootcol->saveFile(f.c_str());
00159   return NULL;
00160 }
00161 
00162 void ConfigurationEditor::AddCollectionEntry::refresh() {
00163   options.clear();
00164   for(plist::Dictionary::const_iterator it=ConfigurationEditor::getObjectTemplates().begin(); it!=ConfigurationEditor::getObjectTemplates().end(); ++it) {
00165     if(tgt->canContain(*it->second)) {
00166 #ifdef PLATFORM_APERIOS
00167       // aperios uses an old compiler
00168       plist::ObjectBase * cpy = static_cast<plist::ObjectBase*>((void*)it->second->clone());
00169 #else
00170       plist::ObjectBase * cpy = static_cast<plist::ObjectBase*>(it->second->clone());
00171 #endif
00172       pushSlot(new ConfigurationEditor::NewCollectionEntry(it->first,*tgt,*cpy));
00173     }
00174   }
00175 }
00176 
00177 void ConfigurationEditor::NewCollectionEntry::refresh() {
00178   std::string key;
00179   if(options.size()>0 && options[0]!=NULL)
00180     key=dynamic_cast<const StringInputControl&>(*options[0]).getLastInput();
00181   options.clear();
00182   StringInputControl * keyEdit=NULL;
00183   if(dynamic_cast<plist::DictionaryBase*>(tgt)) {
00184     keyEdit = new StringInputControl("Key: "+key,"Enter key for the dictionary entry");
00185   } else if(dynamic_cast<plist::ArrayBase*>(tgt)) {
00186     if(key=="")
00187       key="end";
00188     keyEdit = new StringInputControl("Position: "+key,"Enter an index position or keyword 'end', optionally followed by '-n' to offset from the end");
00189   }
00190   keyEdit->takeInput(key);
00191   pushSlot(keyEdit);
00192   if(plist::PrimitiveBase * po = dynamic_cast<plist::PrimitiveBase*>(obj)) {
00193     pushSlot(new StringInputControl(po->get(),"Enter the intial value for the item"));
00194   } else if(plist::Collection * c = dynamic_cast<plist::Collection*>(obj)) {
00195     ConfigurationEditor * sube = new ConfigurationEditor("sub-entries...","Add entries to the new collection",c);
00196     pushSlot(sube);
00197   } else if(obj!=NULL) {
00198     std::cerr << "WARNING: unknown type for NewCollectionEntry editor" << ": " << obj->toString() << std::endl;
00199   }
00200   pushSlot(NULL);
00201   pushSlot(new NullControl("Commit Entry"));
00202 }
00203 
00204 ControlBase * ConfigurationEditor::NewCollectionEntry::doSelect() {
00205   if(hilights.size()!=1 || hilights.front()!=options.size()-1)
00206     return ControlBase::doSelect();
00207   
00208   if(plist::DictionaryBase* d = dynamic_cast<plist::DictionaryBase*>(tgt)) {
00209     std::string key = dynamic_cast<const StringInputControl&>(*options[0]).getLastInput();
00210     reinterpret_cast<plist::DictionaryBase::EntryConstraint<plist::ObjectBase>*>(d)->addEntry(key,obj);
00211   } else if(plist::ArrayBase* a = dynamic_cast<plist::ArrayBase*>(tgt)) {
00212     std::string key = dynamic_cast<const StringInputControl&>(*options[0]).getLastInput();
00213     int idx;
00214     if(key=="" || string_util::makeLower(key).substr(0,3)=="end") {
00215       idx=a->size();
00216       if(key.size()>3)
00217         idx+=atoi(key.substr(3).c_str());
00218     } else {
00219       idx=atoi(key.c_str()) % (options.size()+1);
00220       if(idx<0)
00221         idx+=options.size()+1;
00222     }
00223     reinterpret_cast<plist::ArrayBase::EntryConstraint<plist::ObjectBase>*>(a)->addEntry(idx,obj);
00224   }
00225   return NULL;
00226 }
00227 
00228 void ConfigurationEditor::NamedEnumerationEditor::refresh() {
00229   options.clear();
00230   std::map<int,std::string> names;
00231   tgt->getPreferredNames(names);
00232   for(std::map<int,std::string>::const_iterator it=names.begin(); it!=names.end(); ++it)
00233     pushSlot(new NullControl(it->second));
00234   ControlBase::refresh();
00235   if(gui_comm!=NULL && wireless->isConnected(gui_comm->sock)) {
00236     if(userPrompt.size()>0)
00237       gui_comm->printf("status\n%td\n%s\n",std::count(userPrompt.begin(),userPrompt.end(),'\n'),userPrompt.c_str());
00238   }
00239 }
00240 
00241 ControlBase * ConfigurationEditor::NamedEnumerationEditor::doSelect() {
00242   if(hilights.size()!=1)
00243     return this;
00244   clearLastInput();
00245   tgt->set(options[hilights.front()]->getName());
00246   return NULL;
00247 }
00248 
00249 /*! @file
00250  * @brief 
00251  * @author Ethan Tira-Thompson (ejt) (Creator)
00252  */

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