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);
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
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
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
00230
00231
00232
00233
00234
00235
00236
00237
00238