Homepage Demos Overview Downloads Tutorials Reference
Credits

ControlBase.cc

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

Tekkotsu v2.2
Generated Tue Oct 19 14:19:13 2004 by Doxygen 1.3.9.1