Homepage Demos Overview Downloads Tutorials Reference
Credits
Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members | Related Pages | Search

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

Tekkotsu v1.4
Generated Sat Jul 19 00:06:29 2003 by Doxygen 1.3.2