SUMO - Simulation of Urban MObility
MFXAddEditTypedTable.cpp
Go to the documentation of this file.
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*)&current);
00441         } else if (event->click_count == 2) {
00442             handle(this, FXSEL(SEL_DOUBLECLICKED, 0), (void*)&current);
00443         } else if (event->click_count == 3) {
00444             handle(this, FXSEL(SEL_TRIPLECLICKED, 0), (void*)&current);
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*)&current);
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> &params) {
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 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines