Note: Goby version 1 (shown here) is now considered obsolete. Please use version 2 for new projects, and consider upgrading old projects.

Goby Underwater Autonomy Project  Series: 1.1, revision: 163, released on 2013-02-06 14:23:27 -0500
moos/iCommander/commander_cdk.cpp
00001 // t. schneider tes@mit.edu 02.24.09
00002 // ocean engineering graduate student - mit / whoi joint program
00003 // massachusetts institute of technology (mit)
00004 // laboratory for autonomous marine sensing systems (lamss)
00005 // 
00006 // this is commander_cdk.cpp
00007 //
00008 // see the readme file within this directory for information
00009 // pertaining to usage and purpose of this script.
00010 //
00011 // This program is free software: you can redistribute it and/or modify
00012 // it under the terms of the GNU General Public License as published by
00013 // the Free Software Foundation, either version 3 of the License, or
00014 // (at your option) any later version.
00015 //
00016 // This software is distributed in the hope that it will be useful,
00017 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019 // GNU General Public License for more details.
00020 //
00021 // You should have received a copy of the GNU General Public License
00022 // along with this software.  If not, see <http://www.gnu.org/licenses/>.
00023 
00024 #include "commander_cdk.h"
00025 #include "goby/util/string.h"
00026 
00027 using namespace std;
00028 
00029 static int matrixPostProcessCB(EObjectType cdkType,
00030                                void *object,
00031                                void *clientData,
00032                                chtype input)
00033 {
00034     CDKMATRIX *matrix = (CDKMATRIX *) object;
00035     int row = getCDKMatrixRow(matrix);
00036     int col = getCDKMatrixCol(matrix);
00037     char * crow_val  =  getCDKMatrixCell (matrix, row, 1);
00038     string row_val = crow_val;
00039     
00040     if(post_cb_)
00041     {        
00042         if(post_cb_(row, col, row_val, input))
00043         {
00044             drawCDKMatrix(matrix, true);
00045             return 1;
00046         }
00047         else
00048             matrixPostProcessCB(vMATRIX,matrix,NULL,KEY_ESC);
00049     }
00050  
00051 
00052     char buff [1][row_val.size()+1];    
00053     strcpy(buff[0], row_val.c_str()); crow_val = buff[0];
00054 
00055     setCDKMatrixCell(matrix, row, col, crow_val);   
00056     drawCDKMatrix(matrix, true);
00057     
00058 
00059     return 0;
00060 }
00061 
00062 static int matrixPreProcessCB(EObjectType cdkType,
00063                               void *object,
00064                               void *clientData,
00065                               chtype input)
00066 {
00067 
00068     CDKMATRIX *matrix = (CDKMATRIX *) object;
00069     int row = getCDKMatrixRow(matrix);
00070     int col = getCDKMatrixCol(matrix);
00071     char * crow_val  =  getCDKMatrixCell (matrix, row, 1);
00072     string row_val = crow_val;
00073     
00074     if(pre_cb_)
00075     {        
00076         if(pre_cb_(row, col, row_val, input))
00077             return 1;
00078 
00079         else
00080             matrixPostProcessCB(vMATRIX,matrix,NULL,KEY_DC);
00081     }
00082 
00083     char buff [1][row_val.size()+1];    
00084     strcpy(buff[0], row_val.c_str()); crow_val = buff[0];
00085 
00086     setCDKMatrixCell(matrix, row, col, crow_val);   
00087 
00088     drawCDKMatrix(matrix, true);    
00089     return 0;
00090 }
00091 
00092 void CommanderCdk::cursor_on()
00093 {
00094     curs_set(1);
00095 }
00096 
00097 void CommanderCdk::cursor_off()
00098 {
00099     curs_set(0);
00100 }
00101 
00102 
00103 void CommanderCdk::initialize()
00104 {   
00105     cursesWin_ = initscr ();
00106 
00107     keypad(cursesWin_, true);
00108     notimeout(cursesWin_, true);
00109     ESCDELAY = 0;
00110     
00111     cursor_off();
00112     
00113     cdkscreen_ = initCDKScreen (cursesWin_);
00114 
00115 
00116     initCDKColor ();
00117     
00118     initialized_ = true;
00119 }
00120 
00121 void CommanderCdk::cleanup()
00122 {
00123     destroyCDKScreen (cdkscreen_);
00124     endCDK ();
00125 }
00126 
00127 
00128 bool CommanderCdk::disp_scroll(std::string title, std::vector<std::string> buttons, int & selection, bool do_split_title)
00129 {
00130     if(!initialized_)
00131     {
00132         selection = 0;
00133         return false;
00134     }
00135     
00136     CDKSCROLL *scroll;
00137     char * ctitle;
00138     vector<char *> cbuttons;
00139 
00140     int max_x, max_y;
00141     getmaxyx(cursesWin_, max_y, max_x);
00142 
00143     int height = min(GENERIC_HEIGHT,max_y);
00144     int width = min(GENERIC_WIDTH,max_x);
00145 
00146     if (do_split_title)
00147         title = word_wrap(title, width, ",");
00148         
00149     // figure out how big the buffer needs to be
00150     size_t max_length = title.length();
00151 
00152     for (vector<string>::size_type i = 0, n = buttons.size(); i < n; ++i)
00153     {
00154         buttons[i] = "> " + buttons[i];
00155         max_length = max(max_length, buttons[i].length());
00156     }
00157     
00158     // store room for title (1 space) and all buttons
00159     char buff [1+buttons.size()][max_length+1];
00160 
00161     // this whole mess is because CDK wants a freaking char ** (not const char **)
00162     strcpy(buff[0], title.c_str()); ctitle = buff[0];
00163     for (vector<string>::size_type i = 0, n = buttons.size(); i < n; ++i)
00164     {
00165         strcpy(buff[i+1], buttons[i].c_str()); cbuttons.push_back(buff[i+1]);
00166     }
00167   
00168     scroll = newCDKScroll (cdkscreen_,
00169                            CENTER,
00170                            CENTER,
00171                            NONE,
00172                            height,
00173                            width,
00174                            ctitle,
00175                            &cbuttons[0],
00176                            cbuttons.size(),
00177                            false,
00178                            A_REVERSE,
00179                            box_,
00180                            shadow_);
00181 
00182     if (scroll == 0)
00183         fail();
00184 
00185     top_widget_object_ = scroll;
00186     top_widget_type_ = vSCROLL;    
00187 
00188     selection = activateCDKScroll (scroll, (chtype *) 0);
00189     destroyCDKScroll (scroll);
00190 
00191     top_widget_object_ = NULL;
00192     
00193     if(scroll->exitType == vESCAPE_HIT)
00194         return false;
00195     else
00196         return true;
00197 }
00198 
00199 
00200 bool CommanderCdk::disp_alphalist(const string title,
00201                                  const string label,
00202                                  const vector<string> & items,
00203                                  int & selected)
00204 {
00205     if(!initialized_)
00206     {
00207         selected = 0;
00208         return false;
00209     }
00210 
00211     cursor_on();
00212     
00213     
00214         
00215     CDKALPHALIST * alphalist;
00216     
00217     char * ctitle;
00218     char * clabel;
00219     vector<char *> citems;
00220 
00221     int max_x, max_y;
00222     getmaxyx(cursesWin_, max_y, max_x);
00223     
00224     // figure out how big the buffer needs to be
00225     size_t max_length = title.length();
00226     max_length = max(max_length, label.length());
00227 
00228     for (vector<string>::size_type i = 0, n = items.size(); i < n; ++i)
00229     {
00230         max_length = max(max_length, items[i].length());
00231     }
00232     
00233     // title, label, items
00234     char buff [1+1+items.size()][max_length+1];
00235 
00236 
00237     
00238     strcpy(buff[0], title.c_str()); ctitle = buff[0];
00239     strcpy(buff[1], label.c_str()); clabel = buff[1];
00240     for (vector<string>::size_type i = 0, n = items.size(); i < n; ++i)
00241     {
00242         strcpy(buff[i+2], items[i].c_str()); citems.push_back(buff[i+2]);
00243     }
00244     
00245     /* Create the alpha list widget. */
00246     alphalist = newCDKAlphalist (cdkscreen_,
00247                                  CENTER,
00248                                  CENTER,
00249                                  min(GENERIC_HEIGHT,max_y), 
00250                                  min(GENERIC_WIDTH,max_x), 
00251                                  ctitle,
00252                                  clabel,
00253                                  &citems[0],
00254                                  citems.size(),
00255                                  '_',
00256                                  A_REVERSE,
00257                                  box_,
00258                                  shadow_);
00259     
00260     if (alphalist == 0)
00261         fail();
00262 
00263     setCDKAlphalistCurrentItem (alphalist, 0);
00264     
00265     char * message = activateCDKAlphalist (alphalist, 0);
00266     string selected_message;
00267     if(message)
00268         selected_message = message;        
00269 
00270     selected = -1;
00271     // check if valid message
00272     for (vector<string>::size_type i = 0, n = items.size(); i < n; ++i)
00273     {
00274         if(boost::iequals(items[i], selected_message))
00275             selected = i;
00276     }
00277 
00278     if(selected == -1 && alphalist->exitType != vESCAPE_HIT)
00279     {
00280         destroyCDKAlphalist (alphalist);
00281         disp_alphalist(title, label, items, selected);
00282     }
00283 
00284     destroyCDKAlphalist (alphalist);
00285 
00286     cursor_off();
00287     
00288     
00289     if(alphalist->exitType == vESCAPE_HIT)
00290         return false;
00291     else
00292         return true;
00293 
00294 }
00295 
00296 
00297 bool CommanderCdk::disp_matrix(const string title,
00298                                int rows,
00299                                int cols,
00300                                int fieldwidth,
00301                                const vector<string> & rowtitles,
00302                                const vector<string> & coltitles,
00303                                vector<string > & values,
00304                                cdk_callback pre_cb,
00305                                cdk_callback post_cb,
00306                                int startx,
00307                                int starty)
00308 {
00309     if(!initialized_)
00310         return false;
00311     
00312     
00313     post_cb_ = post_cb;
00314     pre_cb_ = pre_cb;
00315 
00316     
00317 //    CDKMATRIX * matrix;
00318 
00319     // figure out how big the buffer needs to be
00320     size_t max_length = title.length();
00321 
00322     size_t max_rowtitlelength = 0;
00323     for (vector<string>::size_type i = 0, n = rowtitles.size(); i < n; ++i)
00324     {
00325         max_rowtitlelength = max(max_rowtitlelength, rowtitles[i].length());
00326     }
00327     size_t max_coltitlelength = 0;
00328     for (vector<string>::size_type i = 0, n = coltitles.size(); i < n; ++i)
00329     {
00330         max_coltitlelength = max(max_coltitlelength, coltitles[i].length());
00331     }
00332     
00333     max_length = max(max_rowtitlelength, max_length);
00334     max_length = max(max_coltitlelength, max_length);
00335     
00336 
00337     int title_newlines = 0;
00338     for(string::size_type i = 0, n = title.length(); i < n; ++i)
00339     {
00340         if(title[i] == '\n')
00341             ++title_newlines;
00342     }
00343 
00344     int vcols, vrows = 0;
00345     while(vcols<=0 || vrows<=0)
00346     {
00347         int max_x, max_y;
00348         getmaxyx(cursesWin_, max_y, max_x);
00349 // visible columns / rows
00350         // each row takes width + 2 + title length + 4  + 6 for safety
00351         vcols = (int)min((double)cols, floor(static_cast<double>((max_x - 4 - 6 - max_rowtitlelength) / (fieldwidth+2))));
00352         // each row takes 3 + title length + 3 constant + 4 for safety
00353         vrows = (int)min((double)rows, floor(static_cast<double>((max_y - lower_box_size_ - 3 - 4 - (title_newlines + 1)) / (3))));
00354         if(vcols<=0 || vrows<=0)
00355             disp_scroll("You must enlarge your window!", vector<string>(1, "OK"));
00356     }
00357     
00358                 
00359     
00360     // cols + 1 because for some dumb reason the matrix widget starts
00361     // matrix numbering at 1 not 0
00362     int colwidth[cols+1];
00363     int colvalue[cols+1];
00364     char * ccoltitles[cols+1];
00365     char * crowtitles[rows+1];
00366     char * ctitle;
00367     
00368     char title_buff [1][max_length+1];
00369     char rowtitle_buff [rowtitles.size()][max_length+1];
00370     char coltitle_buff [coltitles.size()][max_length+1];
00371 
00372     strcpy(title_buff[0], title.c_str()); ctitle = title_buff[0];
00373 
00374     size_t num_row_titles = rowtitles.size();
00375     size_t num_col_titles = coltitles.size();
00376     for (vector<string>::size_type i = 0, n = rows; i < n; ++i)
00377     {
00378         if (i < num_row_titles)
00379         {
00380             strcpy(rowtitle_buff[i], rowtitles[i].c_str()); crowtitles[i+1] = rowtitle_buff[i];
00381         }
00382         else
00383             crowtitles[i+1] = 0;
00384     }
00385     for (vector<string>::size_type i = 0, n = cols; i < n; ++i)
00386     {
00387         if (i < num_col_titles)
00388         {
00389             strcpy(coltitle_buff[i], coltitles[i].c_str()); ccoltitles[i+1] = coltitle_buff[i];
00390         }
00391         else
00392             ccoltitles[i+1] = 0;
00393 
00394         colwidth[i+1] = fieldwidth;
00395         colvalue[i+1] = vMIXED;
00396     }    
00397 
00398     
00399     /* Create the matrix object. */
00400     matrix_ = newCDKMatrix (cdkscreen_,
00401                            startx,
00402                            starty,
00403                            rows,
00404                            cols,
00405                            vrows,
00406                            vcols,
00407                            ctitle,
00408                            crowtitles,
00409                            ccoltitles,
00410                            colwidth,
00411                            colvalue,
00412                            1,
00413                            1,
00414                            ' ',
00415                            COL,
00416                            true,
00417                            true,
00418                            false);
00419 
00420     int max_length2 = 0;
00421     for (vector<string>::size_type i = 0, n = values.size(); i < n; ++i)
00422     {
00423         max_length2 = max(max_length2, (int)values[i].length());
00424     }
00425 
00426     size_t num_values = values.size();
00427     for (size_t i = 0, n = cols; i < n; ++i)
00428     {
00429         for (size_t j = 0, m = rows; j < m; ++j)
00430         {
00431 
00432             if ((j+i*rows) < num_values)
00433             {
00434                 char value_buff[1][max_length2];
00435                 char * cvalue;
00436                 strcpy(value_buff[1], values[j+i*rows].c_str()); cvalue = value_buff[1];
00437 
00438                 setCDKMatrixCell (matrix_,
00439                                   j+1,
00440                                   i+1,
00441                                   cvalue);
00442                     
00443             }
00444         }
00445     }
00446 
00447 
00448         
00449         
00450     setCDKMatrixPostProcess (matrix_, matrixPostProcessCB, 0);
00451     setCDKMatrixPreProcess (matrix_, matrixPreProcessCB, 0);
00452     
00453     matrixPostProcessCB(vMATRIX,
00454                         matrix_,
00455                         NULL,
00456                         KEY_DC);
00457 
00458     refresh();
00459     
00460     /* Activate the matrix. */
00461     activateCDKMatrix (matrix_, 0);
00462     
00463 
00464     values.clear();
00465     for (size_t i = 0, n = cols; i < n; ++i)
00466     {
00467         for (size_t j = 0, m = rows; j < m; ++j)
00468         {
00469             char * cval = getCDKMatrixCell (matrix_,
00470                                             j+1,
00471                                             i+1);
00472 
00473             string val = cval;
00474             values.push_back(val);
00475                                
00476         }
00477     }
00478 
00479         
00480     destroyCDKMatrix (matrix_);
00481     
00482     destroyCDKLabel (info_box_);
00483     info_box_set_ = false;
00484 
00485     if(matrix_->exitType == vESCAPE_HIT)
00486     {
00487         matrix_ = NULL;
00488         return false;
00489     }            
00490     else
00491     {
00492         matrix_ = NULL;
00493         return true;
00494     }
00495 }
00496 
00497 
00498 void CommanderCdk::refresh()
00499 {
00500     if(lower_info_box_set_)
00501         drawCDKLabel(lower_info_box_,
00502                      true);
00503 
00504         
00505     refreshCDKScreen(cdkscreen_);
00506 }
00507 
00508 bool CommanderCdk::disp_lower_info(const vector<string> & lines)
00509 {
00510     if(!initialized_)
00511         return false;
00512 
00513     destroyCDKLabel (lower_info_box_);
00514      
00515     size_t max_length = 0;
00516     for (vector<string>::size_type i = 0, n = lines.size(); i < n; ++i)
00517     {
00518         max_length = max(max_length, lines[i].length());
00519     }
00520 
00521     char * clines[lines.size()];
00522     char buff [lines.size()][max_length+1];
00523     for (vector<string>::size_type i = 0, n = lines.size(); i < n; ++i)
00524     {
00525         strcpy(buff[i], lines[i].c_str()); clines[i] = buff[i];
00526     }    
00527 
00528     lower_info_box_ = newCDKLabel (cdkscreen_,
00529                                    CENTER,
00530                                    BOTTOM,
00531                                    clines,
00532                                    lines.size(),
00533                                    box_,
00534                                    shadow_);
00535     drawCDKLabel(lower_info_box_,
00536                  true);
00537     
00538 
00539     restore_widgets();
00540     
00541     return true;
00542 }
00543 
00544 void CommanderCdk::restore_widgets()
00545 {
00546     if(matrix_ != NULL && top_widget_object_ == NULL)
00547     {
00548         drawCDKMatrix(matrix_, true);
00549     }
00550 }
00551 
00552 bool CommanderCdk::disp_info(const vector<string> & lines)
00553 {
00554     if(!initialized_)
00555         return false;
00556 
00557     destroyCDKLabel (info_box_);
00558      
00559     size_t max_length = 0;
00560     for (vector<string>::size_type i = 0, n = lines.size(); i < n; ++i)
00561     {
00562         max_length = max(max_length, lines[i].length());
00563     }
00564 
00565     char * clines[lines.size()];
00566     char buff [lines.size()][max_length+1];
00567     for (vector<string>::size_type i = 0, n = lines.size(); i < n; ++i)
00568     {
00569         strcpy(buff[i], lines[i].c_str()); clines[i] = buff[i];
00570     }    
00571     
00572     info_box_ = newCDKLabel (cdkscreen_,
00573                              CENTER,
00574                              TOP,
00575                              clines,
00576                              lines.size(),
00577                              box_,
00578                              shadow_);
00579     drawCDKLabel(info_box_,
00580                  true);
00581     
00582     
00583     restore_widgets();
00584 
00585     return true;
00586 }
00587 
00588 
00589 
00590 bool CommanderCdk::disp_fselect(const string title, const string label, std::string & name)
00591 {
00592     if(!initialized_)
00593         return false;
00594 
00595     cursor_on();    
00596     
00597     CDKFSELECT * fselect;
00598     
00599     char * filename;
00600     char * ctitle;
00601     char * clabel;
00602 
00603     int max_x, max_y;
00604     getmaxyx(cursesWin_, max_y, max_x);
00605     
00606     // figure out how big the buffer needs to be
00607     size_t max_length = title.length();
00608     max_length = max(max_length, label.length());
00609    
00610     // title, label, items
00611     char buff [2+4][max_length+1];    
00612     strcpy(buff[0], title.c_str()); ctitle = buff[0];
00613     strcpy(buff[1], label.c_str()); clabel = buff[1];
00614 
00615     strcpy(buff[2], "");
00616     strcpy(buff[3], "");
00617     strcpy(buff[4], "");
00618     strcpy(buff[5], "");
00619     
00620 /* Create the alpha list widget. */
00621     fselect = newCDKFselect (cdkscreen_,
00622                              CENTER,
00623                              CENTER,
00624                              min(GENERIC_HEIGHT,max_y), 
00625                              min(GENERIC_WIDTH,max_x), 
00626                              ctitle,
00627                              clabel,
00628                              A_NORMAL,
00629                              ' ',
00630                              A_REVERSE,
00631                              buff[2],
00632                              buff[3],
00633                              buff[4],
00634                              buff[5],
00635                              box_,
00636                              shadow_);
00637     
00638     if (fselect == 0)
00639         fail();
00640     
00641     filename = activateCDKFselect (fselect, 0);
00642     filename = copyChar (filename);
00643 
00644     if(filename)
00645         name = filename;    
00646 
00647     destroyCDKFselect (fselect);
00648 
00649     cursor_off();
00650     
00651     if(fselect->exitType == vESCAPE_HIT)
00652         return false;
00653     else
00654         return true;
00655 }
00656 
00657 void CommanderCdk::set_matrix_val(int row, int col, std::string s)
00658 {
00659     if(matrix_ != NULL)
00660     {
00661         char buff [s.length()+1];
00662         char * cs;
00663         
00664         strcpy(buff, s.c_str()); cs = buff;
00665         
00666         setCDKMatrixCell(matrix_, row, col, cs);
00667     }
00668 }
00669 
00670 void CommanderCdk::get_matrix_val(int row, int col, std::string & s)
00671 {
00672     if(matrix_ != NULL)
00673         s = string(getCDKMatrixCell(matrix_, row, col));
00674 }
00675 
00676 void CommanderCdk::resize()
00677 {
00678     destroyCDKLabel (lower_info_box_);
00679 }
00680 
00681 
00682 void CommanderCdk::fail()
00683 {
00684     cleanup();
00685     
00686     cout << "Oops. Can't seem to create the dialog box. " << endl;
00687     cout << "Is the window too small?";
00688     exit(EXIT_FAILURE);
00689 }
00690 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends