SUMO - Simulation of Urban MObility
|
00001 /****************************************************************************/ 00007 // missing_desc 00008 /****************************************************************************/ 00009 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/ 00010 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors 00011 /****************************************************************************/ 00012 // 00013 // This file is part of SUMO. 00014 // SUMO is free software: you can redistribute it and/or modify 00015 // it under the terms of the GNU General Public License as published by 00016 // the Free Software Foundation, either version 3 of the License, or 00017 // (at your option) any later version. 00018 // 00019 /****************************************************************************/ 00020 00021 00022 // =========================================================================== 00023 // included modules 00024 // =========================================================================== 00025 #ifdef _MSC_VER 00026 #include <windows_config.h> 00027 #else 00028 #include <config.h> 00029 #endif 00030 00031 #include <fx.h> 00032 #include <fxkeys.h> 00033 #include <utils/common/TplConvert.h> 00034 #include <utils/common/ToString.h> 00035 #include "MFXAddEditTypedTable.h" 00036 #include <iostream> 00037 00038 #ifdef CHECK_MEMORY_LEAKS 00039 #include <foreign/nvwa/debug_new.h> 00040 #endif // CHECK_MEMORY_LEAKS 00041 00042 00043 // Map 00044 FXDEFMAP(MFXAddEditTypedTable) MFXAddEditTypedTableMap[] = { 00045 FXMAPFUNC(SEL_CLICKED, 0, MFXAddEditTypedTable::onClicked), 00046 FXMAPFUNC(SEL_DOUBLECLICKED, 0, MFXAddEditTypedTable::onDoubleClicked), 00047 FXMAPFUNC(SEL_LEFTBUTTONRELEASE, 0, MFXAddEditTypedTable::onLeftBtnRelease), 00048 FXMAPFUNC(SEL_LEFTBUTTONPRESS, 0, MFXAddEditTypedTable::onLeftBtnPress), 00049 }; 00050 // Object implementation 00051 FXIMPLEMENT(MFXAddEditTypedTable, FXTable, MFXAddEditTypedTableMap, ARRAYNUMBER(MFXAddEditTypedTableMap)) 00052 00053 00054 MFXAddEditTypedTable::MFXAddEditTypedTable(FXComposite* p, FXObject* tgt, 00055 FXSelector sel, FXuint opts, 00056 FXint x, FXint y, FXint w, FXint h, 00057 FXint pl, FXint pr, FXint pt, FXint pb) 00058 : FXTable(p, tgt, sel, opts, x, y, w, h, pl, pr, pt, pb) {} 00059 00060 00061 MFXAddEditTypedTable::~MFXAddEditTypedTable() {} 00062 00063 /* 00064 void 00065 MFXAddEditTypedTable::editItem(FXTableItem* item,FXint how) 00066 { 00067 if(item==0) { 00068 editEnd(); 00069 return; 00070 } 00071 if(myWriteProtectedCols.find(myEditedCol)!=myWriteProtectedCols.end()) { 00072 editEnd(); 00073 return; 00074 } 00075 FXTableItem* it= item; 00076 myPreviousText = item->getText(); 00077 FXint x = getColumnX(myEditedCol) + getRowHeader()->getWidth() + xpos; 00078 FXint y = getRowY(myEditedRow) + getColumnHeader()->getHeight() + ypos; 00079 FXIcon* icon = item->getIcon(); 00080 if(icon) x += icon->getWidth() + 4; 00081 FXint vw = getViewportWidth(); 00082 if(vertical->shown()) vw -= vertical->getWidth(); 00083 if(vw>getColumnWidth(myEditedCol)) { 00084 vw = getColumnWidth(myEditedCol) + x; 00085 } 00086 switch(getCellType(myEditedCol)) { 00087 case CT_UNDEFINED: 00088 case CT_STRING: 00089 myEditor->setText(it->getText()); 00090 myEditor->move(x, y); 00091 myEditor->resize(vw - x + 1, getRowHeight(myEditedRow) + 1); 00092 myEditor->show(); 00093 myEditor->raise(); 00094 myEditor->enable(); 00095 myEditor->setFocus(); 00096 myEditor->grab(); 00097 if(how == 'I') { 00098 myEditor->killSelection(); 00099 myEditor->setCursorPos(0); 00100 } else if(how == 'A') { 00101 myEditor->killSelection(); 00102 myEditor->setCursorPos(myEditor->getText().length()); 00103 } else myEditor->selectAll(); 00104 break; 00105 case CT_REAL: 00106 { 00107 try { 00108 myNumberEditor->setValue( 00109 TplConvert<char>::_2SUMOReal(it->getText().text())); 00110 } catch (NumberFormatException &) { 00111 } catch (EmptyData &) { 00112 } 00113 NumberCellParams p = getNumberCellParams(myEditedCol); 00114 if(p.format!="undefined") { 00115 myNumberEditor->setFormatString((char*) p.format.c_str()); 00116 myNumberEditor->setIncrements(p.steps1, p.steps2, p.steps3); 00117 myNumberEditor->setRange(p.min, p.max); 00118 } 00119 myNumberEditor->move(x, y); 00120 myNumberEditor->resize(vw - x + 1, getRowHeight(myEditedRow) + 1); 00121 myNumberEditor->show(); 00122 myNumberEditor->raise(); 00123 myNumberEditor->setFocus(); 00124 myNumberEditor->selectAll(); 00125 } 00126 //myNumberEditor->setRange(0,1000); 00127 break; 00128 case CT_INT: 00129 { 00130 try { 00131 myNumberEditor->setValue( 00132 TplConvert<char>::_2int(it->getText().text())); 00133 } catch (NumberFormatException &) { 00134 } catch (EmptyData &) { 00135 } 00136 NumberCellParams p = getNumberCellParams(myEditedCol); 00137 if(p.format!="undefined") { 00138 myNumberEditor->setFormatString((char*) p.format.c_str()); 00139 myNumberEditor->setIncrements(p.steps1, p.steps2, p.steps3); 00140 myNumberEditor->setRange(p.min, p.max); 00141 } 00142 myNumberEditor->move(x, y); 00143 myNumberEditor->resize(vw - x + 1, getRowHeight(myEditedRow) + 1); 00144 myNumberEditor->show(); 00145 myNumberEditor->raise(); 00146 myNumberEditor->setFocus(); 00147 myNumberEditor->selectAll(); 00148 } 00149 break; 00150 case CT_BOOL: 00151 try { 00152 myBoolEditor->setCheck( 00153 TplConvert<char>::_2bool(it->getText().text()) 00154 ? true : false); 00155 } catch (NumberFormatException &) { 00156 } catch (EmptyData &) { 00157 } 00158 myBoolEditor->move(x, y); 00159 myBoolEditor->resize(vw - x + 1, getRowHeight(myEditedRow) + 1); 00160 myBoolEditor->show(); 00161 myBoolEditor->raise(); 00162 myBoolEditor->setFocus(); 00163 break; 00164 case CT_ENUM: 00165 { 00166 myEnumEditor->hide(); 00167 myEnumEditor->clearItems(); 00168 if(myEnums.size()>myEditedCol) { 00169 for(size_t i=0; i<myEnums[myEditedCol].size(); i++) { 00170 myEnumEditor->appendItem(myEnums[myEditedCol][i].c_str()); 00171 } 00172 } 00173 if(myEnumEditor->findItem(it->getText())>=0) { 00174 myEnumEditor->setCurrentItem( 00175 myEnumEditor->findItem(it->getText())); 00176 } else { 00177 myEnumEditor->setCurrentItem(0); 00178 } 00179 myEnumEditor->setNumVisible( 00180 myEnums[myEditedCol].size()<10 00181 ? myEnums[myEditedCol].size() 00182 : 10); 00183 myEnumEditor->layout(); 00184 y = getRowY(myEditedRow) + getColumnHeader()->getHeight() + ypos 00185 - getRowHeight(myEditedRow); 00186 myEnumEditor->move(x, y); 00187 myEnumEditor->resize(vw - x + 1, getRowHeight(myEditedRow) + 1); 00188 myEnumEditor->show(); 00189 myEnumEditor->raise(); 00190 myEnumEditor->setFocus(); 00191 } 00192 break; 00193 default: 00194 throw 1; 00195 } 00196 myEditedItem = it; 00197 } 00198 */ 00199 00200 00201 FXWindow* 00202 MFXAddEditTypedTable::getControlForItem(FXint r, FXint c) { 00203 register FXTableItem* item = cells[r * ncols + c]; 00204 if (item == NULL) { 00205 return 0; 00206 cells[r * ncols + c] = item = createItem("", NULL, NULL); 00207 if (isItemSelected(r, c)) { 00208 item->setSelected(FALSE); 00209 } 00210 } 00211 delete editor; 00212 editor = NULL; 00213 switch (getCellType(c)) { 00214 case CT_UNDEFINED: 00215 case CT_STRING: { 00216 register FXTextField* field; 00217 register FXuint justify = 0; 00218 field = new FXTextField(this, 1, NULL, 0, TEXTFIELD_ENTER_ONLY, 0, 0, 0, 0, getMarginLeft(), getMarginRight(), getMarginTop(), getMarginBottom()); 00219 // !!! if(state&LEFT) justify|=JUSTIFY_LEFT; 00220 // !!! if(state&RIGHT) justify|=JUSTIFY_RIGHT; 00221 // !!! if(state&TOP) justify|=JUSTIFY_TOP; 00222 // !!! if(state&BOTTOM) justify|=JUSTIFY_BOTTOM; 00223 field->create(); 00224 field->setJustify(justify); 00225 field->setFont(getFont()); 00226 field->setBackColor(getBackColor()); 00227 field->setTextColor(getTextColor()); 00228 field->setSelBackColor(getSelBackColor()); 00229 field->setSelTextColor(getSelTextColor()); 00230 field->setText(item->getText()); 00231 field->selectAll(); 00232 return field; 00233 } 00234 case CT_REAL: 00235 // return myNumberEditor; 00236 case CT_INT: { 00237 register FXRealSpinDial* field; 00238 //register FXuint justify=0; 00239 field = new FXRealSpinDial(this, 1, NULL, 0, TEXTFIELD_ENTER_ONLY, 0, 0, 0, 0, getMarginLeft(), getMarginRight(), getMarginTop(), getMarginBottom()); 00240 // !!! if(state&LEFT) justify|=JUSTIFY_LEFT; 00241 // !!! if(state&RIGHT) justify|=JUSTIFY_RIGHT; 00242 // !!! if(state&TOP) justify|=JUSTIFY_TOP; 00243 // !!! if(state&BOTTOM) justify|=JUSTIFY_BOTTOM; 00244 field->create(); 00245 // field->setJustify(justify); 00246 field->setFont(getFont()); 00247 field->setBackColor(getBackColor()); 00248 field->setTextColor(getTextColor()); 00249 field->setSelBackColor(getSelBackColor()); 00250 field->setSelTextColor(getSelTextColor()); 00251 NumberCellParams p = getNumberCellParams(c); 00252 if (p.format != "undefined") { 00253 field->setFormatString((char*) p.format.c_str()); 00254 field->setIncrements(p.steps1, p.steps2, p.steps3); 00255 field->setRange(p.min, p.max); 00256 } 00257 try { 00258 if (getCellType(c) == CT_REAL) { 00259 field->setValue(TplConvert<char>::_2SUMOReal(item->getText().text())); 00260 } else { 00261 field->setValue(TplConvert<char>::_2int(item->getText().text())); 00262 } 00263 } catch (NumberFormatException&) { 00264 field->setValue(0); 00265 } 00266 field->selectAll(); 00267 return field; 00268 } 00269 case CT_BOOL: 00270 // return myBoolEditor; 00271 case CT_ENUM: 00272 // return myEnumEditor; 00273 default: 00274 throw 1; 00275 } 00276 } 00277 00278 00279 // Cancel editing cell 00280 void 00281 MFXAddEditTypedTable::cancelInput() { 00282 if (editor) { 00283 delete editor; 00284 input.fm.row = -1; 00285 input.to.row = -1; 00286 input.fm.col = -1; 00287 input.to.col = -1; 00288 editor = NULL; 00289 } 00290 } 00291 00292 // Done with editing cell 00293 void 00294 MFXAddEditTypedTable::acceptInput(FXbool notify) { 00295 bool set = false; 00296 FXTableRange tablerange = input; 00297 if (editor) { 00298 // 00299 // 00300 FXRealSpinDial* dial = dynamic_cast<FXRealSpinDial*>(editor); 00301 if (dial != 0) { 00302 if (!dial->getDial().grabbed()) { 00303 set = true; 00304 } else { 00305 setItemFromControl_NoRelease(input.fm.row, input.fm.col, editor); 00306 } 00307 } 00308 if (dynamic_cast<FXTextField*>(editor) != 0) { 00309 set = true; 00310 } 00311 } 00312 if (set) { 00313 setItemFromControl(input.fm.row, input.fm.col, editor); 00314 cancelInput(); 00315 if (notify && target) { 00316 target->tryHandle(this, FXSEL(SEL_REPLACED, message), (void*)&tablerange); 00317 } 00318 } 00319 } 00320 00321 00322 00323 00324 void 00325 MFXAddEditTypedTable::setItemFromControl(FXint r, FXint c, FXWindow* control) { 00326 register FXTableItem* item = cells[r * ncols + c]; 00327 if (item == NULL) { 00328 cells[r * ncols + c] = item = createItem("", NULL, NULL); 00329 if (isItemSelected(r, c)) { 00330 item->setSelected(FALSE); 00331 } 00332 } 00333 switch (getCellType(c)) { 00334 case CT_UNDEFINED: 00335 case CT_STRING: 00336 item->setFromControl(control); 00337 break; 00338 case CT_REAL: 00339 item->setText(toString(static_cast<FXRealSpinDial*>(control)->getValue()).c_str()); 00340 break; 00341 case CT_INT: 00342 item->setText(toString((int) static_cast<FXRealSpinDial*>(control)->getValue()).c_str()); 00343 break; 00344 case CT_BOOL: 00345 // return myBoolEditor; 00346 case CT_ENUM: 00347 // return myEnumEditor; 00348 default: 00349 throw 1; 00350 } 00351 // current.row = -1; 00352 // current.col = -1; 00353 EditedTableItem edited; 00354 edited.item = item; 00355 edited.row = r; 00356 edited.col = c; 00357 edited.updateOnly = false; 00358 killSelection(true); 00359 bool accepted = true; 00360 if (target) { 00361 if (!target->handle(this, FXSEL(SEL_CHANGED, ID_TEXT_CHANGED), (void*) &edited)) { 00362 accepted = false; 00363 // !!! item->setText(myPreviousText); 00364 } 00365 } 00366 if (accepted) { 00367 if (edited.row == getNumRows() - 1) { 00368 insertRows(getNumRows(), 1, true); 00369 for (int i = 0; i < getNumColumns(); i++) { 00370 setItemText(getNumRows() - 1, i, ""); 00371 setItemJustify(getNumRows() - 1, i, JUSTIFY_CENTER_X); 00372 } 00373 } 00374 } 00375 mode = MOUSE_NONE; 00376 } 00377 00378 00379 void 00380 MFXAddEditTypedTable::setItemFromControl_NoRelease(FXint r, FXint c, FXWindow* control) { 00381 register FXTableItem* item = cells[r * ncols + c]; 00382 if (item == NULL) { 00383 return; 00384 } 00385 switch (getCellType(c)) { 00386 case CT_UNDEFINED: 00387 case CT_STRING: 00388 item->setFromControl(control); 00389 break; 00390 case CT_REAL: 00391 item->setText(toString(static_cast<FXRealSpinDial*>(control)->getValue()).c_str()); 00392 break; 00393 case CT_INT: 00394 item->setText(toString((int) static_cast<FXRealSpinDial*>(control)->getValue()).c_str()); 00395 break; 00396 case CT_BOOL: 00397 // return myBoolEditor; 00398 case CT_ENUM: 00399 // return myEnumEditor; 00400 default: 00401 throw 1; 00402 } 00403 EditedTableItem edited; 00404 edited.item = item; 00405 edited.row = r; 00406 edited.col = c; 00407 edited.updateOnly = true; 00408 bool accepted = true; 00409 if (target) { 00410 if (!target->handle(this, FXSEL(SEL_CHANGED, ID_TEXT_CHANGED), (void*) &edited)) { 00411 accepted = false; 00412 // !!! item->setText(myPreviousText); 00413 } 00414 } 00415 } 00416 00417 00418 // Released button 00419 long MFXAddEditTypedTable::onLeftBtnRelease(FXObject*, FXSelector, void* ptr) { 00420 FXEvent* event = (FXEvent*)ptr; 00421 if (isEnabled()) { 00422 ungrab(); 00423 flags &= ~FLAG_PRESSED; 00424 flags |= FLAG_UPDATE; 00425 mode = MOUSE_NONE; 00426 stopAutoScroll(); 00427 setDragCursor(getApp()->getDefaultCursor(DEF_ARROW_CURSOR)); 00428 if (target && target->tryHandle(this, FXSEL(SEL_LEFTBUTTONRELEASE, message), ptr)) { 00429 return 1; 00430 } 00431 00432 // Scroll to make item visibke 00433 makePositionVisible(current.row, current.col); 00434 00435 // Update anchor 00436 //setAnchorItem(current.row,current.col); // FIXME look into the selection stuff 00437 00438 // Generate clicked callbacks 00439 if (event->click_count == 1) { 00440 handle(this, FXSEL(SEL_CLICKED, 0), (void*)¤t); 00441 } else if (event->click_count == 2) { 00442 handle(this, FXSEL(SEL_DOUBLECLICKED, 0), (void*)¤t); 00443 } else if (event->click_count == 3) { 00444 handle(this, FXSEL(SEL_TRIPLECLICKED, 0), (void*)¤t); 00445 } 00446 00447 // Command callback only when clicked on item 00448 if (0 <= current.row && 0 <= current.col && isItemEnabled(current.row, current.col)) { 00449 handle(this, FXSEL(SEL_COMMAND, 0), (void*)¤t); 00450 } 00451 return 1; 00452 } 00453 return 0; 00454 } 00455 00456 00457 // Pressed button 00458 long 00459 MFXAddEditTypedTable::onLeftBtnPress(FXObject*, FXSelector, void* ptr) { 00460 FXEvent* event = (FXEvent*)ptr; 00461 FXTablePos tablepos; 00462 flags &= ~FLAG_TIP; 00463 handle(this, FXSEL(SEL_FOCUS_SELF, 0), ptr); 00464 if (isEnabled()) { 00465 grab(); 00466 if (target && target->tryHandle(this, FXSEL(SEL_LEFTBUTTONPRESS, message), ptr)) { 00467 return 1; 00468 } 00469 00470 // Cell being clicked on 00471 tablepos.row = rowAtY(event->win_y); 00472 tablepos.col = colAtX(event->win_x); 00473 00474 // Outside table 00475 if (tablepos.row < 0 || tablepos.row >= nrows || tablepos.col < 0 || tablepos.col >= ncols) { 00476 setCurrentItem(-1, -1, TRUE); 00477 return 0; 00478 } 00479 00480 // Change current item 00481 bool wasEdited = editor != 0; 00482 setCurrentItem(tablepos.row, tablepos.col, TRUE); 00483 if (!wasEdited) { 00484 00485 // Select or deselect 00486 if (event->state & SHIFTMASK) { 00487 if (0 <= anchor.row && 0 <= anchor.col) { 00488 if (isItemEnabled(anchor.row, anchor.col)) { 00489 extendSelection(current.row, current.col, TRUE); 00490 } 00491 } else { 00492 setAnchorItem(current.row, current.col); 00493 if (isItemEnabled(current.row, current.col)) { 00494 extendSelection(current.row, current.col, TRUE); 00495 } 00496 } 00497 mode = MOUSE_SELECT; 00498 } else { 00499 if (isItemEnabled(current.row, current.col)) { 00500 killSelection(TRUE); 00501 setAnchorItem(current.row, current.col); 00502 extendSelection(current.row, current.col, TRUE); 00503 } else { 00504 setAnchorItem(current.row, current.col); 00505 } 00506 mode = MOUSE_SELECT; 00507 } 00508 } 00509 flags &= ~FLAG_UPDATE; 00510 flags |= FLAG_PRESSED; 00511 return 1; 00512 } 00513 return 0; 00514 } 00515 00516 00517 00518 // Clicked in list 00519 long 00520 MFXAddEditTypedTable::onClicked(FXObject*, FXSelector , void* ptr) { 00521 if (editor) { 00522 delete editor; 00523 input.fm.row = -1; 00524 input.to.row = -1; 00525 input.fm.col = -1; 00526 input.to.col = -1; 00527 editor = NULL; 00528 current.row = -1; 00529 current.col = -1; 00530 } 00531 if (target && target->tryHandle(this, FXSEL(SEL_CLICKED, message), ptr)) { 00532 return 1; 00533 } 00534 handle(this, FXSEL(SEL_COMMAND, ID_START_INPUT), NULL); 00535 return 1; 00536 } 00537 00538 00539 // Double clicked in list; ptr may or may not point to an item 00540 long MFXAddEditTypedTable::onDoubleClicked(FXObject*, FXSelector, void* ptr) { 00541 if (editor) { 00542 delete editor; 00543 input.fm.row = -1; 00544 input.to.row = -1; 00545 input.fm.col = -1; 00546 input.to.col = -1; 00547 editor = NULL; 00548 } else { 00549 if (target && target->tryHandle(this, FXSEL(SEL_CLICKED, message), ptr)) { 00550 return 1; 00551 } 00552 handle(this, FXSEL(SEL_COMMAND, ID_START_INPUT), NULL); 00553 } 00554 return 1; 00555 } 00556 00557 00558 CellType 00559 MFXAddEditTypedTable::getCellType(size_t pos) const { 00560 if (myCellTypes.size() <= pos) { 00561 return CT_UNDEFINED; 00562 } 00563 return myCellTypes[pos]; 00564 } 00565 00566 00567 void 00568 MFXAddEditTypedTable::setCellType(size_t pos, CellType t) { 00569 while (myCellTypes.size() < pos + 1) { 00570 myCellTypes.push_back(CT_UNDEFINED); 00571 } 00572 myCellTypes[pos] = t; 00573 } 00574 00575 void 00576 MFXAddEditTypedTable::setNumberCellParams(size_t pos, double min, double max, 00577 double steps1, 00578 double steps2, 00579 double steps3, 00580 const std::string& format) { 00581 while (myNumberCellParams.size() <= pos) { 00582 NumberCellParams np; 00583 np.format = "undefined"; 00584 myNumberCellParams.push_back(np); 00585 } 00586 NumberCellParams np; 00587 np.pos = (int)(pos); 00588 np.min = min; 00589 np.max = max; 00590 np.steps1 = steps1; 00591 np.steps2 = steps2; 00592 np.steps3 = steps3; 00593 np.format = format; 00594 myNumberCellParams[pos] = np; 00595 } 00596 00597 00598 MFXAddEditTypedTable::NumberCellParams 00599 MFXAddEditTypedTable::getNumberCellParams(size_t pos) const { 00600 if (myNumberCellParams.size() <= pos) { 00601 NumberCellParams np; 00602 np.format = "undefined"; 00603 return np; 00604 } 00605 return myNumberCellParams[pos]; 00606 } 00607 00608 00609 00610 void 00611 MFXAddEditTypedTable::setEnums(size_t pos, 00612 const std::vector<std::string> ¶ms) { 00613 while (myEnums.size() <= pos) { 00614 myEnums.push_back(std::vector<std::string>()); 00615 } 00616 myEnums[pos] = params; 00617 } 00618 00619 00620 void 00621 MFXAddEditTypedTable::addEnum(size_t pos, 00622 const std::string& e) { 00623 while (myEnums.size() <= pos) { 00624 myEnums.push_back(std::vector<std::string>()); 00625 } 00626 myEnums[pos].push_back(e); 00627 } 00628 00629 00630 const std::vector<std::string> & 00631 MFXAddEditTypedTable::getEnums(size_t pos) const { 00632 return myEnums[pos]; 00633 } 00634 00635 00636 00637 /****************************************************************************/ 00638