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

Tekkotsu v4.0
Generated Thu Nov 22 00:54:52 2007 by Doxygen 1.5.4