Goby Underwater Autonomy Project
Series: 1.1, revision: 163, released on 2013-02-06 14:23:27 -0500
|
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