00001 #include "ControlBase.h"
00002 #include "Motion/MMAccessor.h"
00003 #include "Motion/LedMC.h"
00004 #include "Shared/string_util.h"
00005 #include "Sound/SoundManager.h"
00006 #include "Wireless/Wireless.h"
00007 #include <iomanip>
00008 #include <sstream>
00009
00010 ControlBase * ControlBase::activate(MotionManager::MC_ID display, Socket * gui) {
00011 display_id=display;
00012 gui_comm=gui;
00013 hilightFirst();
00014 refresh();
00015 return this;
00016 }
00017
00018 void ControlBase::pause() {
00019 if(doRewrite) {
00020 doRewrite=false;
00021 }
00022 }
00023
00024 void ControlBase::refresh() {
00025
00026 if(display_id!=MotionManager::invalid_MC_ID) {
00027 if(hilights.size()>0) {
00028 MMAccessor<LedMC> display(display_id);
00029 unsigned int cur=hilights.front();
00030 if(options.size()<=10)
00031 display.mc()->displayNumber(cur,LedEngine::onedigit);
00032 else
00033 display.mc()->displayNumber(cur,LedEngine::twodigit);
00034 }
00035 }
00036
00037
00038 if(gui_comm==NULL || !wireless->isConnected(gui_comm->sock)) {
00039
00040 const char * const nosel=" ";
00041 const char * slctd="**";
00042 if(config->main.use_VT100) {
00043 slctd="\33[1m**\33[0m";
00044 if(doRewrite)
00045 clearMenu();
00046 sout->printf("\33[1m%s\33[0m:\n",getName().c_str());
00047 } else
00048 sout->printf("%s:\n",getName().c_str());
00049 unsigned int digits=0;
00050 for(unsigned int i=1; i<options.size(); i*=10)
00051 digits++;
00052 for(unsigned int i=0; i<options.size(); i++) {
00053 if(options[i]==NULL)
00054 for(unsigned int j=0; j<strlen(nosel)+digits+2; j++)
00055 sout->printf(" ");
00056 else
00057 sout->printf("%s%*d%s ",(find(hilights.begin(),hilights.end(),i)!=hilights.end()?slctd:nosel),digits,i,(options[i]->slotsSize()>0?">":"."));
00058
00059 sout->printf("%s\n",getSlotName(i).c_str());
00060 }
00061 if(options.size()==0)
00062 sout->printf(" Empty menu\n");
00063 doRewrite=true;
00064 } else {
00065
00066
00067
00068
00069 std::stringstream ss;
00070 ss << "refresh\n"
00071 << getName() << '\n'
00072 << options.size() << '\n';
00073 for(unsigned int i=0; i<options.size(); i++) {
00074 if(options[i]==NULL)
00075 ss << "0\n0\n----------\n0\n\n";
00076 else {
00077 std::string desc = options[i]->getDescription();
00078 ss << options[i]->options.size() << '\n'
00079 << (binary_search(hilights.begin(),hilights.end(),i)?1:0) << '\n'
00080 << options[i]->getName() << '\n'
00081 << std::count(desc.begin(),desc.end(),'\n') << '\n'
00082 << desc << '\n';
00083 }
00084 }
00085
00086
00087 gui_comm->write((const byte*)ss.str().c_str(),ss.str().size());
00088
00089
00090
00091 }
00092 }
00093
00094 void ControlBase::deactivate() {
00095 hilights.clear();
00096 if(display_id!=MotionManager::invalid_MC_ID) {
00097 MMAccessor<LedMC> display(display_id);
00098 display.mc()->clear();
00099 }
00100 if(doRewrite) {
00101 if(config->main.use_VT100)
00102 clearMenu();
00103 doRewrite=false;
00104 }
00105 display_id=MotionManager::invalid_MC_ID;
00106 }
00107
00108 ControlBase* ControlBase::doSelect() {
00109
00110
00111 if(hilights.size()==0) {
00112 sndman->playFile(config->controller.select_snd);
00113 return this;
00114 }
00115 for(unsigned int i=0;i<hilights.size();i++) {
00116 unsigned int cur=hilights[i];
00117 if(cur>=options.size() || options[cur]==NULL) {
00118 if(display_id!=MotionManager::invalid_MC_ID) {
00119 MMAccessor<LedMC> display(display_id);
00120 display.mc()->cflash(FaceLEDMask,.5,100);
00121 }
00122 if(cur>=options.size())
00123 sout->printf("Invalid choice\n");
00124 else
00125 sout->printf("NULL option\n");
00126 continue;
00127 }
00128 if(display_id!=MotionManager::invalid_MC_ID) {
00129 MMAccessor<LedMC> display(display_id);
00130 display.mc()->flash(FaceLEDMask,100);
00131 display.mc()->clear();
00132 }
00133 if(doRewrite) {
00134 if(config->main.use_VT100)
00135 clearMenu();
00136 doRewrite=false;
00137 }
00138 sndman->playFile(config->controller.select_snd);
00139 if(hilights.size()>1) {
00140 options[cur]->activate(display_id,gui_comm);
00141 options[cur]->deactivate();
00142 }
00143 }
00144 if(hilights.size()==1)
00145 return options[hilights.front()];
00146 return this;
00147 }
00148
00149 ControlBase* ControlBase::doNextItem() {
00150
00151 if(options.size()==0)
00152 return this;
00153 unsigned int cur=0;
00154 for(unsigned int i=0; i<hilights.size(); i++)
00155 if(hilights[i]>=cur)
00156 cur=(hilights[i]+1)%options.size();
00157 while(options[cur]==NULL)
00158 cur=(cur+1)%options.size();
00159 hilights.clear();
00160 hilights.push_back(cur);
00161 sndman->playFile(config->controller.next_snd);
00162 refresh();
00163
00164 return this;
00165 }
00166
00167 ControlBase* ControlBase::doPrevItem() {
00168
00169 if(options.size()==0)
00170 return this;
00171 unsigned int cur=options.size()-1;
00172 for(unsigned int i=hilights.size(); i>0; i--)
00173 if(hilights[i-1]<=cur)
00174 cur=(hilights[i-1]+options.size()-1)%options.size();
00175 while(options[cur]==NULL)
00176 cur=(cur+options.size()-1)%options.size();
00177 hilights.clear();
00178 hilights.push_back(cur);
00179 sndman->playFile(config->controller.prev_snd);
00180 refresh();
00181
00182 return this;
00183 }
00184
00185 ControlBase * ControlBase::doCancel() {
00186 sndman->playFile(config->controller.cancel_snd);
00187 return NULL;
00188 }
00189
00190
00191 ControlBase* ControlBase::doReadStdIn(const std::string& prompt) {
00192
00193 if(display_id!=MotionManager::invalid_MC_ID) {
00194 MMAccessor<LedMC> display(display_id);
00195 display.mc()->cset(FaceLEDMask,.5);
00196 }
00197 sndman->playFile(config->controller.read_snd);
00198
00199
00200 if(gui_comm==NULL || !wireless->isConnected(gui_comm->sock)) {
00201
00202 if(prompt.size()>0)
00203 sout->printf("%s\n",prompt.c_str());
00204 sout->printf("#> ");
00205 if(!wireless->isConnected(sout->sock)) {
00206 std::string choice;
00207 std::cin >> choice;
00208 std::cout << std::endl;
00209 return takeInput(choice);
00210 }
00211 return this;
00212 } else {
00213
00214 if(prompt.size()>0) {
00215 unsigned int lines=std::count(prompt.begin(),prompt.end(),'\n');
00216 gui_comm->printf("status\n%u\n%s\n",lines,prompt.c_str());
00217 }
00218 return this;
00219 }
00220 }
00221
00222 ControlBase* ControlBase::takeInput(const std::string& str) {
00223 std::vector<std::string> args;
00224 std::vector<unsigned int> offsets;
00225 if(!string_util::parseArgs(str,args,offsets)) {
00226 serr->printf("ControlBase::takeInput(\"%s\") was not understood.\n",str.c_str());
00227 refresh();
00228 return this;
00229 } else {
00230
00231 if(args.size()==0) {
00232 refresh();
00233 return this;
00234 }
00235
00236 unsigned int choice=-1U;
00237 bool ambiguous=false;
00238 for(unsigned int i=0; i<options.size(); i++) {
00239 if(options[i]!=NULL && options[i]->name.compare(0,args[0].size(),args[0])==0) {
00240 if(choice==-1U)
00241 choice=i;
00242 else
00243 ambiguous=true;
00244 }
00245 }
00246
00247 if(!ambiguous && choice==-1U) {
00248 std::string argname=string_util::makeLower(args[0]);
00249 for(unsigned int i=0; i<options.size(); i++) {
00250 if(options[i]!=NULL) {
00251 std::string optname=string_util::makeLower(options[i]->name);
00252 if(optname.compare(0,argname.size(),argname)==0) {
00253 if(choice==-1U)
00254 choice=i;
00255 else
00256 ambiguous=true;
00257 }
00258 }
00259 }
00260 }
00261
00262 if(ambiguous || choice==-1U) {
00263 char* endp=NULL;
00264 choice=strtol(args[0].c_str(),&endp,10);
00265 if(endp==NULL || endp==args[0].c_str()) {
00266 if(config->main.use_VT100) {
00267 sout->printf("\r\33[1A");
00268 clearMenu();
00269 doRewrite=false;
00270 }
00271 return invalidInput(str,ambiguous);
00272 } else if(choice<options.size() && options[choice]!=NULL) {
00273 ambiguous=false;
00274 } else {
00275 if(config->main.use_VT100) {
00276 sout->printf("\r\33[1A");
00277 clearMenu();
00278 doRewrite=false;
00279 }
00280 return invalidInput(str,ambiguous);
00281 }
00282 }
00283
00284 if(args.size()>1)
00285 return options[choice]->takeInput(str.substr(offsets[1]));
00286 else {
00287 hilights.clear();
00288 hilights.push_back(choice);
00289 return doSelect();
00290 }
00291 }
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330 return this;
00331 }
00332
00333 bool ControlBase::validInput(const std::string& str) {
00334 unsigned int choice=atoi(str.c_str());
00335 return (choice<options.size() && options[choice]!=NULL);
00336 }
00337
00338 std::string ControlBase::getSlotName(unsigned int i) const {
00339 if(options[i]!=NULL)
00340 return options[i]->getName();
00341 else
00342 return "----------";
00343 }
00344
00345
00346 void ControlBase::setSlot(unsigned int i,ControlBase* o) {
00347 while(options.size()<=i)
00348 options.push_back(NULL);
00349 options[i]=o;
00350 }
00351
00352 void ControlBase::pushSlot(ControlBase* o) {
00353 options.push_back(o);
00354 }
00355
00356 void ControlBase::clearSlots() {
00357 for(unsigned int i=0; i<options.size(); i++)
00358 delete options[i];
00359 options.clear();
00360 hilights.clear();
00361 }
00362
00363 void ControlBase::setHilights(const std::vector<unsigned int>& hi) {
00364 float avg=hilightsAvg();
00365 hilights.clear();
00366 for(unsigned int i=0; i<hi.size(); i++)
00367 if(hi[i]<options.size())
00368 hilights.push_back(hi[i]);
00369 float newavg=hilightsAvg();
00370 if(avg!=-1 || newavg!=-1) {
00371 if(avg<=newavg)
00372 sndman->playFile(config->controller.next_snd);
00373 else
00374 sndman->playFile(config->controller.prev_snd);
00375 }
00376 refresh();
00377 }
00378
00379 void ControlBase::hilightFirst() {
00380 hilights.clear();
00381 for(unsigned int i=0; i<options.size(); i++)
00382 if(options[i]!=NULL) {
00383 hilights.push_back(i);
00384 return;
00385 }
00386 }
00387
00388
00389 void ControlBase::clearMenu() {
00390 if(config->main.use_VT100) {
00391 sout->printf("\r\33[%luA",(unsigned long)(options.size()+1));
00392 sout->printf("\33[J");
00393 }
00394 }
00395
00396 ControlBase* ControlBase::invalidInput(const std::string& msg, bool ambiguous) {
00397 if(ambiguous)
00398 serr->printf("ControlBase(\"%s\")::takeInput(\"%s\") was ambiguous\n",name.c_str(),msg.c_str());
00399 else
00400 serr->printf("ControlBase(\"%s\")::takeInput(\"%s\") was not a valid index or option name.\n",name.c_str(),msg.c_str());
00401 refresh();
00402 return this;
00403 }
00404
00405 float ControlBase::hilightsAvg() const {
00406 if(hilights.size()==0)
00407 return -1;
00408 unsigned int total=0;
00409 for(unsigned int i=0; i<hilights.size(); i++)
00410 total+=hilights[i];
00411 return (float)total/(float)hilights.size();
00412 }
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425