LCOV - code coverage report
Current view: top level - src/utils/foxtools - MFXDecalsTable.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 0 398 0.0 %
Date: 2024-04-27 15:34:54 Functions: 0 57 0.0 %

          Line data    Source code
       1             : /****************************************************************************/
       2             : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3             : // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
       4             : // This program and the accompanying materials are made available under the
       5             : // terms of the Eclipse Public License 2.0 which is available at
       6             : // https://www.eclipse.org/legal/epl-2.0/
       7             : // This Source Code may also be made available under the following Secondary
       8             : // Licenses when the conditions for such availability set forth in the Eclipse
       9             : // Public License 2.0 are satisfied: GNU General Public License, version 2
      10             : // or later which is available at
      11             : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
      12             : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
      13             : /****************************************************************************/
      14             : /// @file    MFXDecalsTable.cpp
      15             : /// @author  Pablo Alvarez Lopez
      16             : /// @date    Feb 2023
      17             : ///
      18             : // Table used for show and edit decal values
      19             : /****************************************************************************/
      20             : #include <config.h>
      21             : 
      22             : #include "MFXDecalsTable.h"
      23             : 
      24             : #include <netedit/GNEViewNet.h>
      25             : #include <netedit/GNEViewParent.h>
      26             : #include <netedit/GNEApplicationWindow.h>
      27             : #include <utils/gui/div/GUIDesigns.h>
      28             : #include <utils/gui/images/GUIIconSubSys.h>
      29             : #include <utils/gui/windows/GUIAppEnum.h>
      30             : #include <utils/gui/windows/GUIDialog_ViewSettings.h>
      31             : 
      32             : 
      33             : #define EXTRAMARGIN 4
      34             : 
      35             : #define MAXROWS 100
      36             : 
      37             : // ===========================================================================
      38             : // FOX callback mapping
      39             : // ===========================================================================
      40             : 
      41             : FXDEFMAP(MFXDecalsTable) MFXDecalsTableMap[] = {
      42             :     FXMAPFUNC(MID_MBTTIP_FOCUS,     0,                  MFXDecalsTable::onFocusRow),
      43             :     FXMAPFUNC(SEL_FOCUSIN,  MID_DECALSTABLE_TEXTFIELD,  MFXDecalsTable::onFocusRow),
      44             :     FXMAPFUNC(SEL_KEYPRESS, MID_DECALSTABLE_TEXTFIELD,  MFXDecalsTable::onCmdKeyPress),
      45             :     FXMAPFUNC(SEL_COMMAND,  MID_DECALSTABLE_TEXTFIELD,  MFXDecalsTable::onCmdEditRowString),
      46             :     FXMAPFUNC(SEL_COMMAND,  MID_DECALSTABLE_SPINNER,    MFXDecalsTable::onCmdEditRowSpinner),
      47             :     FXMAPFUNC(SEL_COMMAND,  MID_DECALSTABLE_CHECKBOX,   MFXDecalsTable::onCmdEditRowCheckBox),
      48             :     FXMAPFUNC(SEL_COMMAND,  MID_DECALSTABLE_OPEN,       MFXDecalsTable::onCmdOpenDecal),
      49             :     FXMAPFUNC(SEL_COMMAND,  MID_DECALSTABLE_ADD,        MFXDecalsTable::onCmdAddRow),
      50             :     FXMAPFUNC(SEL_UPDATE,   MID_DECALSTABLE_ADD,        MFXDecalsTable::onUpdAddRow),
      51             :     FXMAPFUNC(SEL_COMMAND,  MID_DECALSTABLE_REMOVE,     MFXDecalsTable::onCmdRemoveRow),
      52             : };
      53             : 
      54             : // Object implementation
      55           0 : FXIMPLEMENT(MFXDecalsTable, FXVerticalFrame, MFXDecalsTableMap, ARRAYNUMBER(MFXDecalsTableMap))
      56             : 
      57             : // ===========================================================================
      58             : // method definitions
      59             : // ===========================================================================
      60             : 
      61             : // ---------------------------------------------------------------------------
      62             : // MFXDecalsTable - public methods
      63             : // ---------------------------------------------------------------------------
      64             : 
      65           0 : MFXDecalsTable::MFXDecalsTable(GUIDialog_ViewSettings* dialogViewSettingsParent, FXComposite* parent) :
      66             :     FXVerticalFrame(parent, GUIDesignAuxiliarFrameFixHeight),
      67           0 :     myIndexFont(new FXFont(getApp(), "Segoe UI", 9)),
      68           0 :     myIndexSelectedFont(new FXFont(getApp(), "Segoe UI", 9, FXFont::Bold)),
      69           0 :     myDialogViewSettings(dialogViewSettingsParent) {
      70             :     // create vertical frame for rows
      71           0 :     myColumnsFrame = new FXHorizontalFrame(this, GUIDesignAuxiliarFrame);
      72             :     // create add button
      73           0 :     myAddButton = GUIDesigns::buildFXButton(this, "", TL("Add decal"), TL("Add decal."),
      74             :                                             GUIIconSubSys::getIcon(GUIIcon::ADD), this, MID_DECALSTABLE_ADD, GUIDesignButtonIcon);
      75           0 : }
      76             : 
      77             : 
      78           0 : MFXDecalsTable::~MFXDecalsTable() {
      79             :     // delete fonts
      80           0 :     delete myIndexFont;
      81           0 :     delete myIndexSelectedFont;
      82           0 : }
      83             : 
      84             : 
      85             : void
      86           0 : MFXDecalsTable::clearTable() {
      87             :     // clear rows (always before columns, because delete row delete also all cells)
      88           0 :     for (const auto& row : myRows) {
      89           0 :         delete row;
      90             :     }
      91             :     // clear columns
      92           0 :     for (const auto& column : myColumns) {
      93           0 :         delete column;
      94             :     }
      95             :     // drop rows and columns
      96             :     myRows.clear();
      97             :     myColumns.clear();
      98           0 : }
      99             : 
     100             : 
     101             : void
     102           0 : MFXDecalsTable::fillTable() {
     103             :     // first clear table
     104           0 :     clearTable();
     105             :     // get decals
     106           0 :     const auto decals = myDialogViewSettings->getSUMOAbstractView()->getDecals();
     107             :     // create columns
     108           0 :     std::string columnsType = "ibfsssspscd";
     109           0 :     for (int i = 0; i < (FXint)columnsType.size(); i++) {
     110           0 :         myColumns.push_back(new Column(this, i, columnsType.at(i)));
     111             :     }
     112             :     // get num decals
     113           0 :     const int numDecals = decals.size() < MAXROWS ? (int)decals.size() : MAXROWS;
     114             :     // create rows
     115           0 :     for (int i = 0; i < numDecals; i++) {
     116             :         // get decal
     117           0 :         const auto& decal = decals.at(i);
     118             :         // create row
     119           0 :         auto row = new Row(this);
     120             :         // fill cells
     121           0 :         row->getCells().at(2)->getTextField()->setText(decal.filename.c_str());
     122           0 :         row->getCells().at(3)->getTextField()->setText(toString(decal.centerX).c_str());
     123           0 :         row->getCells().at(4)->getTextField()->setText(toString(decal.centerY).c_str());
     124           0 :         row->getCells().at(5)->getTextField()->setText(toString(decal.width).c_str());
     125           0 :         row->getCells().at(6)->getTextField()->setText(toString(decal.height).c_str());
     126           0 :         row->getCells().at(7)->getSpinner()->setValue(decal.rot);
     127           0 :         row->getCells().at(8)->getTextField()->setText(toString(decal.layer).c_str());
     128           0 :         if (decal.screenRelative) {
     129           0 :             row->getCells().at(9)->getCheckButton()->setCheck(true);
     130           0 :             row->getCells().at(9)->getCheckButton()->setText("true");
     131             :         } else {
     132           0 :             row->getCells().at(9)->getCheckButton()->setCheck(false);
     133           0 :             row->getCells().at(9)->getCheckButton()->setText("false");
     134             :         }
     135           0 :         myRows.push_back(row);
     136             :     }
     137             :     // set headers
     138           0 :     myColumns.at(2)->setColumnLabel("filename", "");
     139           0 :     myColumns.at(3)->setColumnLabel("centerX", "");
     140           0 :     myColumns.at(4)->setColumnLabel("centerY", "");
     141           0 :     myColumns.at(5)->setColumnLabel("width", "");
     142           0 :     myColumns.at(6)->setColumnLabel("height", "");
     143           0 :     myColumns.at(7)->setColumnLabel("rotation", "");
     144           0 :     myColumns.at(8)->setColumnLabel("layer", "");
     145           0 :     myColumns.at(9)->setColumnLabel("sRel", "screen relative");
     146             :     // adjust height (header + rows + add button)
     147           0 :     setHeight((numDecals + 2) * GUIDesignHeight);
     148             :     // call create to create all row's elements
     149           0 :     create();
     150           0 : }
     151             : 
     152             : 
     153             : void
     154           0 : MFXDecalsTable::setItemText(FXint row, FXint column, const std::string& text) {
     155           0 :     if ((row >= 0) && (row < (FXint)myRows.size()) &&
     156           0 :             (column >= 0) && (column < (FXint)myColumns.size())) {
     157           0 :         myRows.at(row)->setText(column, text);
     158             :     } else {
     159           0 :         throw ProcessError(TL("Invalid row or column"));
     160             :     }
     161           0 : }
     162             : 
     163             : 
     164             : std::string
     165           0 : MFXDecalsTable::getItemText(const int row, const int column) const {
     166           0 :     if ((row >= 0) && (row < (FXint)myRows.size()) &&
     167           0 :             (column >= 0) && (column < (FXint)myColumns.size())) {
     168           0 :         return myRows.at(row)->getText(column);
     169             :     }
     170           0 :     throw ProcessError(TL("Invalid row or column"));
     171             : }
     172             : 
     173             : 
     174             : int
     175           0 : MFXDecalsTable::getNumRows() const {
     176           0 :     return (int)myRows.size();
     177             : }
     178             : 
     179             : 
     180             : int
     181           0 : MFXDecalsTable::getCurrentSelectedRow() const {
     182           0 :     return myCurrentSelectedRow;
     183             : }
     184             : 
     185             : 
     186             : void
     187           0 : MFXDecalsTable::selectRow(const int row) {
     188           0 :     if ((row >= 0) && (row < (FXint)myRows.size())) {
     189             :         // update current selected row
     190           0 :         myCurrentSelectedRow = row;
     191             :         // update index label
     192           0 :         updateIndexLabel();
     193             :     } else {
     194           0 :         throw ProcessError(TL("Invalid row"));
     195             :     }
     196           0 : }
     197             : 
     198             : 
     199             : void
     200           0 : MFXDecalsTable::setColumnLabel(const int column, const std::string& text, const std::string& tooltip) {
     201           0 :     if ((column >= 0) && (column < (int)myColumns.size())) {
     202           0 :         myColumns.at(column)->setColumnLabel(text, tooltip);
     203             :     } else {
     204           0 :         throw ProcessError(TL("Invalid column"));
     205             :     }
     206           0 : }
     207             : 
     208             : 
     209             : long
     210           0 : MFXDecalsTable::onFocusRow(FXObject* sender, FXSelector, void*) {
     211             :     int selectedRow = -1;
     212             :     // search selected text field
     213           0 :     for (int rowIndex = 0; rowIndex < (int)myRows.size(); rowIndex++) {
     214             :         // iterate over every cell
     215           0 :         for (const auto& cell : myRows.at(rowIndex)->getCells()) {
     216           0 :             if ((cell->getTextField() == sender) || (cell->getButton() == sender)) {
     217             :                 selectedRow = rowIndex;
     218             :             }
     219             :         }
     220             :     }
     221             :     // update index label
     222           0 :     updateIndexLabel();
     223             :     // set new row
     224           0 :     if (myCurrentSelectedRow != selectedRow) {
     225           0 :         myCurrentSelectedRow = selectedRow;
     226           0 :         updateIndexLabel();
     227             :     }
     228           0 :     return 0;
     229             : }
     230             : 
     231             : 
     232             : long
     233           0 : MFXDecalsTable::onCmdKeyPress(FXObject* sender, FXSelector sel, void* ptr) {
     234             :     // get FXEvent
     235             :     FXEvent* eventInfo = (FXEvent*)ptr;
     236             :     // check code
     237           0 :     if (eventInfo->code == 65362) {
     238             :         // move up
     239           0 :         if (myCurrentSelectedRow > 0) {
     240           0 :             myCurrentSelectedRow -= 1;
     241             :         } else {
     242             :             // we're in the first, then select last
     243           0 :             myCurrentSelectedRow = ((int)myRows.size() - 1);
     244             :         }
     245             :         // update index label
     246           0 :         updateIndexLabel();
     247             :         // move focus
     248           0 :         moveFocus();
     249           0 :         return 1;
     250           0 :     } else if (eventInfo->code == 65364) {
     251             :         // move down
     252           0 :         if (myCurrentSelectedRow < ((int)myRows.size() - 1)) {
     253           0 :             myCurrentSelectedRow += 1;
     254             :         } else {
     255             :             // we're in the last, then select first
     256           0 :             myCurrentSelectedRow = 0;
     257             :         }
     258             :         // update index label
     259           0 :         updateIndexLabel();
     260             :         // move focus
     261           0 :         moveFocus();
     262           0 :         return 1;
     263             :     } else {
     264             :         // continue handling key pres
     265           0 :         return sender->handle(sender, sel, ptr);
     266             :     }
     267             : }
     268             : 
     269             : 
     270             : long
     271           0 : MFXDecalsTable::onCmdEditRowString(FXObject* sender, FXSelector, void*) {
     272             :     // get decals
     273           0 :     auto& decals = myDialogViewSettings->getSUMOAbstractView()->getDecals();
     274             :     // get value
     275           0 :     const std::string value = dynamic_cast<FXTextField*>(sender)->getText().text();
     276             :     // set filename
     277           0 :     for (int rowIndex = 0; rowIndex < (int)myRows.size(); rowIndex++) {
     278             :         // continue depending of string
     279           0 :         if (myRows.at(rowIndex)->getCells().at(2)->getTextField() == sender) {
     280           0 :             decals.at(rowIndex).filename = value;
     281           0 :         } else if (myRows.at(rowIndex)->getCells().at(3)->getTextField() == sender) {
     282           0 :             decals.at(rowIndex).centerX = StringUtils::toDouble(value);
     283           0 :         } else if (myRows.at(rowIndex)->getCells().at(4)->getTextField() == sender) {
     284           0 :             decals.at(rowIndex).centerY = StringUtils::toDouble(value);
     285           0 :         } else if (myRows.at(rowIndex)->getCells().at(5)->getTextField() == sender) {
     286           0 :             decals.at(rowIndex).width = StringUtils::toDouble(value);
     287           0 :         } else if (myRows.at(rowIndex)->getCells().at(6)->getTextField() == sender) {
     288           0 :             decals.at(rowIndex).height = StringUtils::toDouble(value);
     289           0 :         } else if (myRows.at(rowIndex)->getCells().at(8)->getTextField() == sender) {
     290           0 :             decals.at(rowIndex).layer = StringUtils::toDouble(value);
     291             :         }
     292             :     }
     293             :     // update view
     294           0 :     myDialogViewSettings->getSUMOAbstractView()->update();
     295           0 :     return 1;
     296             : }
     297             : 
     298             : 
     299             : long
     300           0 : MFXDecalsTable::onCmdEditRowSpinner(FXObject* sender, FXSelector, void*) {
     301             :     // get decals
     302           0 :     auto& decals = myDialogViewSettings->getSUMOAbstractView()->getDecals();
     303             :     // get value
     304           0 :     const auto value = dynamic_cast<FXRealSpinner*>(sender)->getValue();
     305             :     // set filename
     306           0 :     for (int rowIndex = 0; rowIndex < (int)myRows.size(); rowIndex++) {
     307           0 :         if (myRows.at(rowIndex)->getCells().at(7)->getSpinner() == sender) {
     308           0 :             decals.at(rowIndex).rot = value;
     309             :         }
     310             :     }
     311             :     // update view
     312           0 :     myDialogViewSettings->getSUMOAbstractView()->update();
     313           0 :     return 1;
     314             : }
     315             : 
     316             : 
     317             : long
     318           0 : MFXDecalsTable::onCmdEditRowCheckBox(FXObject* sender, FXSelector, void*) {
     319             :     // get decals
     320           0 :     auto& decals = myDialogViewSettings->getSUMOAbstractView()->getDecals();
     321             :     // get check buton
     322           0 :     auto checkButton = dynamic_cast<FXCheckButton*>(sender);
     323             :     // update text
     324           0 :     checkButton->setText((checkButton->getCheck() == TRUE) ? "true" : "false");
     325             :     // set filename
     326           0 :     for (int rowIndex = 0; rowIndex < (int)myRows.size(); rowIndex++) {
     327           0 :         if (myRows.at(rowIndex)->getCells().at(9)->getCheckButton() == sender) {
     328           0 :             decals.at(rowIndex).screenRelative = (checkButton->getCheck() == TRUE) ? true : false;
     329             :         }
     330             :     }
     331             :     // update view
     332           0 :     myDialogViewSettings->getSUMOAbstractView()->update();
     333           0 :     return 1;
     334             : }
     335             : 
     336             : 
     337             : long
     338           0 : MFXDecalsTable::onCmdOpenDecal(FXObject* sender, FXSelector, void*) {
     339             :     // configure open dialog
     340           0 :     FXFileDialog opendialog(this, TL("Open decal"));
     341             :     // select existing file
     342           0 :     opendialog.setSelectMode(SELECTFILE_EXISTING);
     343             :     // set icon and pattern list
     344           0 :     opendialog.setIcon(GUIIconSubSys::getIcon(GUIIcon::OPEN));
     345           0 :     opendialog.setPatternList(TL("All files (*)"));
     346             :     // set current folder
     347           0 :     if (gCurrentFolder.length() != 0) {
     348           0 :         opendialog.setDirectory(gCurrentFolder);
     349             :     }
     350             :     // open dialog
     351           0 :     opendialog.execute();
     352             :     // check if file exist
     353           0 :     if (!opendialog.getFilename().empty()) {
     354             :         // get decals
     355           0 :         auto& decals = myDialogViewSettings->getSUMOAbstractView()->getDecals();
     356             :         // set filename
     357           0 :         for (int rowIndex = 0; rowIndex < (int)myRows.size(); rowIndex++) {
     358           0 :             if (myRows.at(rowIndex)->getCells().at(1)->getButton() == sender) {
     359             :                 // set text in filename
     360           0 :                 myRows.at(rowIndex)->getCells().at(2)->getTextField()->setText(opendialog.getFilename());
     361             :                 // update filename in decal
     362           0 :                 decals.at(rowIndex).filename = opendialog.getFilename().text();
     363             :                 // update view
     364           0 :                 myDialogViewSettings->getSUMOAbstractView()->update();
     365             :                 return 1;
     366             :             }
     367             :         }
     368             :     }
     369             :     return 1;
     370           0 : }
     371             : 
     372             : 
     373             : long
     374           0 : MFXDecalsTable::onCmdAddRow(FXObject*, FXSelector, void*) {
     375             :     // add a new decal
     376           0 :     myDialogViewSettings->getSUMOAbstractView()->getDecals().push_back(GUISUMOAbstractView::Decal());
     377             :     // refill table
     378           0 :     fillTable();
     379           0 :     return 1;
     380             : }
     381             : 
     382             : 
     383             : long
     384           0 : MFXDecalsTable::onUpdAddRow(FXObject* sender, FXSelector, void* ptr) {
     385           0 :     if (myDialogViewSettings->getSUMOAbstractView()->getDecals().size() < MAXROWS) {
     386           0 :         return sender->handle(this, FXSEL(SEL_COMMAND, ID_ENABLE), ptr);
     387             :     } else {
     388           0 :         return sender->handle(this, FXSEL(SEL_COMMAND, ID_DISABLE), ptr);
     389             :     }
     390             : }
     391             : 
     392             : 
     393             : long
     394           0 : MFXDecalsTable::onCmdRemoveRow(FXObject* sender, FXSelector, void*) {
     395             :     // get decals
     396           0 :     auto& decals = myDialogViewSettings->getSUMOAbstractView()->getDecals();
     397             :     // search row
     398           0 :     for (int rowIndex = 0; rowIndex < (int)myRows.size(); rowIndex++) {
     399           0 :         if (myRows.at(rowIndex)->getCells().back()->getButton() == sender) {
     400             :             // remove row
     401             :             decals.erase(decals.begin() + rowIndex);
     402             :             // update view
     403           0 :             myDialogViewSettings->getSUMOAbstractView()->update();
     404             :             // refill table
     405           0 :             fillTable();
     406           0 :             return 1;
     407             :         }
     408             :     }
     409             :     return 1;
     410             : }
     411             : 
     412             : 
     413             : void
     414           0 : MFXDecalsTable::updateIndexLabel() {
     415             :     // update radio buttons checks
     416           0 :     for (int rowIndex = 0; rowIndex < (int)myRows.size(); rowIndex++) {
     417             :         // iterate over every cell
     418           0 :         for (const auto& cell : myRows.at(rowIndex)->getCells()) {
     419           0 :             if (cell->getIndexLabel()) {
     420           0 :                 if (myCurrentSelectedRow == rowIndex) {
     421           0 :                     cell->showIndexLabelBold();
     422             :                 } else {
     423           0 :                     cell->showIndexLabelNormal();
     424             :                 }
     425             :             }
     426             :         }
     427             :     }
     428           0 : }
     429             : 
     430             : 
     431             : bool
     432           0 : MFXDecalsTable::moveFocus() {
     433             :     // first find focus
     434             :     // update radio buttons checks
     435           0 :     for (int rowIndex = 0; rowIndex < (int)myRows.size(); rowIndex++) {
     436           0 :         for (int cellIndex = 0; cellIndex < (int)myRows.at(rowIndex)->getCells().size(); cellIndex++) {
     437           0 :             if (myRows.at(rowIndex)->getCells().at(cellIndex)->hasFocus()) {
     438             :                 // set focus in current row
     439           0 :                 myRows.at(myCurrentSelectedRow)->getCells().at(cellIndex)->setFocus();
     440           0 :                 return true;
     441             :             }
     442             :         }
     443             :     }
     444             :     return false;
     445             : }
     446             : 
     447             : // ---------------------------------------------------------------------------
     448             : // MFXDecalsTable::Cell - methods
     449             : // ---------------------------------------------------------------------------
     450             : 
     451           0 : MFXDecalsTable::Cell::Cell(MFXDecalsTable* decalsTable, FXTextField* textField, int col, int row) :
     452           0 :     myDecalsTable(decalsTable),
     453           0 :     myTextField(textField),
     454           0 :     myCol(col),
     455           0 :     myRow(row) {
     456           0 : }
     457             : 
     458             : 
     459           0 : MFXDecalsTable::Cell::Cell(MFXDecalsTable* decalsTable, FXLabel* indexLabel, FXLabel* indexLabelBold, int col, int row) :
     460           0 :     myDecalsTable(decalsTable),
     461           0 :     myIndexLabel(indexLabel),
     462           0 :     myIndexLabelBold(indexLabelBold),
     463           0 :     myCol(col),
     464           0 :     myRow(row) {
     465             :     // hide bold and set background
     466           0 :     indexLabelBold->hide();
     467           0 :     indexLabelBold->setBackColor(FXRGBA(210, 233, 255, 255));
     468           0 : }
     469             : 
     470             : 
     471           0 : MFXDecalsTable::Cell::Cell(MFXDecalsTable* decalsTable, FXButton* button, int col, int row) :
     472           0 :     myDecalsTable(decalsTable),
     473           0 :     myButton(button),
     474           0 :     myCol(col),
     475           0 :     myRow(row) {
     476           0 : }
     477             : 
     478             : 
     479           0 : MFXDecalsTable::Cell::Cell(MFXDecalsTable* decalsTable, FXCheckButton* checkButton, int col, int row) :
     480           0 :     myDecalsTable(decalsTable),
     481           0 :     myCheckButton(checkButton),
     482           0 :     myCol(col),
     483           0 :     myRow(row) {
     484           0 : }
     485             : 
     486             : 
     487           0 : MFXDecalsTable::Cell::Cell(MFXDecalsTable* decalsTable, FXRealSpinner* spinner, int col, int row) :
     488           0 :     myDecalsTable(decalsTable),
     489           0 :     mySpinner(spinner),
     490           0 :     myCol(col),
     491           0 :     myRow(row) {
     492           0 : }
     493             : 
     494             : 
     495           0 : MFXDecalsTable::Cell::~Cell() {
     496             :     // delete all elements
     497           0 :     if (myTextField) {
     498           0 :         delete myTextField;
     499             :     }
     500           0 :     if (myIndexLabel) {
     501           0 :         delete myIndexLabel;
     502             :     }
     503           0 :     if (myIndexLabelBold) {
     504           0 :         delete myIndexLabelBold;
     505             :     }
     506           0 :     if (myButton) {
     507           0 :         delete myButton;
     508             :     }
     509           0 :     if (myCheckButton) {
     510           0 :         delete myCheckButton;
     511             :     }
     512           0 : }
     513             : 
     514             : 
     515             : bool
     516           0 : MFXDecalsTable::Cell::hasFocus() const {
     517             :     // check if one of the cell elements has the focus
     518           0 :     if (myTextField && myTextField->hasFocus()) {
     519             :         return true;
     520           0 :     } else if (myButton && myButton->hasFocus()) {
     521             :         return true;
     522           0 :     } else if (myCheckButton && myCheckButton->hasFocus()) {
     523             :         return true;
     524             :     } else {
     525           0 :         return false;
     526             :     }
     527             : }
     528             : 
     529             : 
     530             : void
     531           0 : MFXDecalsTable::Cell::setFocus() {
     532             :     // set focus
     533           0 :     if (myTextField) {
     534           0 :         myTextField->setFocus();
     535           0 :     } else if (myButton) {
     536           0 :         myButton->setFocus();
     537           0 :     } else if (myCheckButton) {
     538           0 :         myCheckButton->setFocus();
     539             :     }
     540           0 : }
     541             : 
     542             : 
     543             : FXTextField*
     544           0 : MFXDecalsTable::Cell::getTextField() const {
     545           0 :     return myTextField;
     546             : }
     547             : 
     548             : 
     549             : FXLabel*
     550           0 : MFXDecalsTable::Cell::getIndexLabel() const {
     551           0 :     return myIndexLabel;
     552             : }
     553             : 
     554             : 
     555             : FXButton*
     556           0 : MFXDecalsTable::Cell::getButton() {
     557           0 :     return myButton;
     558             : }
     559             : 
     560             : 
     561             : FXCheckButton*
     562           0 : MFXDecalsTable::Cell::getCheckButton() {
     563           0 :     return myCheckButton;
     564             : }
     565             : 
     566             : 
     567             : FXRealSpinner*
     568           0 : MFXDecalsTable::Cell::getSpinner() {
     569           0 :     return mySpinner;
     570             : }
     571             : 
     572             : 
     573             : void
     574           0 : MFXDecalsTable::Cell::showIndexLabelNormal() {
     575           0 :     myIndexLabel->show();
     576           0 :     myIndexLabelBold->hide();
     577             :     // recalc both
     578           0 :     myIndexLabel->recalc();
     579           0 :     myIndexLabelBold->recalc();
     580           0 : }
     581             : 
     582             : 
     583             : void
     584           0 : MFXDecalsTable::Cell::showIndexLabelBold() {
     585           0 :     myIndexLabel->hide();
     586           0 :     myIndexLabelBold->show();
     587             :     // recalc both
     588           0 :     myIndexLabel->recalc();
     589           0 :     myIndexLabelBold->recalc();
     590           0 : }
     591             : 
     592             : 
     593             : int
     594           0 : MFXDecalsTable::Cell::getCol() const {
     595           0 :     return myCol;
     596             : }
     597             : 
     598             : 
     599             : int
     600           0 : MFXDecalsTable::Cell::getRow() const {
     601           0 :     return myRow;
     602             : }
     603             : 
     604             : 
     605             : char
     606           0 : MFXDecalsTable::Cell::getType() const {
     607           0 :     return myDecalsTable->myColumns.at(myCol)->getType();
     608             : }
     609             : 
     610             : 
     611           0 : MFXDecalsTable::Cell::Cell() :
     612           0 :     myCol(-1),
     613           0 :     myRow(-1) {
     614           0 : }
     615             : 
     616             : // ---------------------------------------------------------------------------
     617             : // MFXDecalsTable::Column - methods
     618             : // ---------------------------------------------------------------------------
     619             : 
     620           0 : MFXDecalsTable::Column::Column(MFXDecalsTable* table, const int index, const char type) :
     621           0 :     myTable(table),
     622           0 :     myIndex(index),
     623           0 :     myType(type) {
     624             :     // get static tooltip
     625           0 :     auto staticTooltip = table->myDialogViewSettings->getSUMOAbstractView()->getGUIGlChildWindow()->getGUIMainWindowParent()->getStaticTooltipMenu();
     626             :     // create vertical frame
     627           0 :     if (myType == 'f') {
     628           0 :         myVerticalFrame = new FXVerticalFrame(table->myColumnsFrame, GUIDesignAuxiliarFrame);
     629             :     } else {
     630           0 :         myVerticalFrame = new FXVerticalFrame(table->myColumnsFrame, GUIDesignAuxiliarFrameFixWidth);
     631             :     }
     632             :     // create top label
     633           0 :     switch (myType) {
     634           0 :         case ('f'): {
     635             :             // ticked label extended
     636           0 :             myTopLabel = new MFXLabelTooltip(myVerticalFrame, staticTooltip, "", nullptr, GUIDesignLabelThick(JUSTIFY_NORMAL));
     637           0 :             break;
     638             :         }
     639           0 :         case ('p'):
     640             :         case ('s'): {
     641             :             // ticked label fixed
     642           0 :             myTopLabel = new MFXLabelTooltip(myVerticalFrame, staticTooltip, "", nullptr, GUIDesignLabelThickedFixed(0));
     643           0 :             break;
     644             :         }
     645           0 :         case ('c'): {
     646             :             // ticked label for checkbox
     647           0 :             myTopLabel = new MFXLabelTooltip(myVerticalFrame, staticTooltip, "", nullptr, GUIDesignLabelThickedFixed(30));
     648           0 :             break;
     649             :         }
     650           0 :         case ('i'): {
     651             :             // ticked label for index
     652           0 :             myTopLabel = new MFXLabelTooltip(myVerticalFrame, staticTooltip, "", nullptr, GUIDesignLabelFixed(30));
     653           0 :             break;
     654             :         }
     655           0 :         default: {
     656             :             // empty label (for buttons)
     657           0 :             myTopLabel = new MFXLabelTooltip(myVerticalFrame, staticTooltip,  "", nullptr, GUIDesignLabelFixed(0));
     658           0 :             break;
     659             :         }
     660             :     }
     661             :     // create vertical frame for cells
     662           0 :     if (myType == 'f') {
     663           0 :         myVerticalCellFrame = new FXVerticalFrame(myVerticalFrame, GUIDesignAuxiliarFrame);
     664             :     } else {
     665           0 :         myVerticalCellFrame = new FXVerticalFrame(myVerticalFrame, GUIDesignAuxiliarFrameFixWidth);
     666             :     }
     667             :     // create elements
     668           0 :     myVerticalFrame->create();
     669           0 :     myTopLabel->create();
     670           0 :     myVerticalCellFrame->create();
     671             :     // adjust column width
     672           0 :     adjustColumnWidth();
     673           0 : }
     674             : 
     675             : 
     676           0 : MFXDecalsTable::Column::~Column() {
     677             :     // delete vertical frame (this also delete all childrens)
     678           0 :     delete myVerticalFrame;
     679           0 : }
     680             : 
     681             : 
     682             : FXVerticalFrame*
     683           0 : MFXDecalsTable::Column::getVerticalCellFrame() const {
     684           0 :     return myVerticalCellFrame;
     685             : }
     686             : 
     687             : 
     688             : char
     689           0 : MFXDecalsTable::Column::getType() const {
     690           0 :     return myType;
     691             : }
     692             : 
     693             : 
     694             : FXString
     695           0 : MFXDecalsTable::Column::getColumnLabel() const {
     696           0 :     return myTopLabel->getText();
     697             : }
     698             : 
     699             : 
     700             : void
     701           0 : MFXDecalsTable::Column::setColumnLabel(const std::string& text, const std::string& tooltip) {
     702           0 :     myTopLabel->setText(text.c_str());
     703           0 :     myTopLabel->setTipText(tooltip.c_str());
     704             :     // adjust column width
     705           0 :     adjustColumnWidth();
     706           0 : }
     707             : 
     708             : 
     709             : void
     710           0 : MFXDecalsTable::Column::adjustColumnWidth() {
     711             :     // filename always extended
     712           0 :     if (myType != 'f') {
     713             :         // declare columnWidth
     714             :         int columnWidth = GUIDesignHeight;
     715             :         // adjust depending of label
     716           0 :         if ((myType == 's') || (myType == 'p') || (myType == 'c')) {
     717             :             // calculate top label width
     718           0 :             columnWidth = myTopLabel->getFont()->getTextWidth(myTopLabel->getText().text(), myTopLabel->getText().length() + EXTRAMARGIN);
     719             :         }
     720             :         // adjust width in all rows
     721           0 :         for (const auto& row : myTable->myRows) {
     722           0 :             if (row->getCells().at(myIndex)->getTextField()) {
     723           0 :                 row->getCells().at(myIndex)->getTextField()->setWidth(columnWidth);
     724           0 :             } else if (row->getCells().at(myIndex)->getButton()) {
     725           0 :                 row->getCells().at(myIndex)->getButton()->setWidth(columnWidth);
     726           0 :             } else if (row->getCells().at(myIndex)->getSpinner()) {
     727           0 :                 row->getCells().at(myIndex)->getSpinner()->setWidth(columnWidth);
     728             :             }
     729             :         }
     730             :         // adjust labels and vertical frames
     731           0 :         myVerticalFrame->setWidth(columnWidth);
     732           0 :         myTopLabel->setWidth(columnWidth);
     733           0 :         myVerticalCellFrame->setWidth(columnWidth);
     734             :     }
     735           0 : }
     736             : 
     737             : 
     738           0 : MFXDecalsTable::Column::Column() :
     739           0 :     myIndex(0),
     740           0 :     myType('-') {}
     741             : 
     742             : // ---------------------------------------------------------------------------
     743             : // MFXDecalsTable::Row - methods
     744             : // ---------------------------------------------------------------------------
     745             : 
     746           0 : MFXDecalsTable::Row::Row(MFXDecalsTable* table) :
     747           0 :     myTable(table) {
     748             :     // build textFields
     749           0 :     for (int columnIndex = 0; columnIndex < (FXint)table->myColumns.size(); columnIndex++) {
     750             :         // get number of cells
     751           0 :         const int numCells = (int)myCells.size();
     752             :         // continue depending of type
     753           0 :         switch (table->myColumns.at(columnIndex)->getType()) {
     754           0 :             case ('f'): {
     755             :                 // create textField for filenames
     756           0 :                 auto textField = new FXTextField(table->myColumns.at(columnIndex)->getVerticalCellFrame(),
     757           0 :                                                  GUIDesignTextFieldNCol, table, MID_DECALSTABLE_TEXTFIELD, GUIDesignTextField);
     758           0 :                 myCells.push_back(new Cell(table, textField, columnIndex, numCells));
     759           0 :                 break;
     760             :             }
     761           0 :             case ('s'): {
     762             :                 // create textField for textfiedl real values
     763           0 :                 auto textField = new FXTextField(table->myColumns.at(columnIndex)->getVerticalCellFrame(),
     764           0 :                                                  GUIDesignTextFieldNCol, table, MID_DECALSTABLE_TEXTFIELD, GUIDesignTextFieldFixedRestricted(0, TEXTFIELD_REAL));
     765           0 :                 myCells.push_back(new Cell(table, textField, columnIndex, numCells));
     766           0 :                 break;
     767             :             }
     768           0 :             case ('p'): {
     769             :                 // create spinner for real values
     770           0 :                 auto spinner = new FXRealSpinner(table->myColumns.at(columnIndex)->getVerticalCellFrame(), GUIDesignTextFieldNCol,
     771           0 :                                                  table, MID_DECALSTABLE_SPINNER, GUIDesignSpinDialDecalsTable);
     772           0 :                 myCells.push_back(new Cell(table, spinner, columnIndex, numCells));
     773           0 :                 break;
     774             :             }
     775           0 :             case ('i'): {
     776             :                 // create labels for index
     777           0 :                 auto indexLabel = new FXLabel(table->myColumns.at(columnIndex)->getVerticalCellFrame(),
     778           0 :                                               toString(myTable->myRows.size()).c_str(), nullptr, GUIDesignLabelThickedFixed(30));
     779           0 :                 auto indexLabelBold = new FXLabel(table->myColumns.at(columnIndex)->getVerticalCellFrame(),
     780           0 :                                                   toString(myTable->myRows.size()).c_str(), nullptr, GUIDesignLabelThickedFixed(30));
     781             :                 // set fonts
     782           0 :                 indexLabel->setFont(myTable->myIndexFont);
     783           0 :                 indexLabelBold->setFont(myTable->myIndexSelectedFont);
     784           0 :                 myCells.push_back(new Cell(table, indexLabel, indexLabelBold, columnIndex, numCells));
     785           0 :                 break;
     786             :             }
     787           0 :             case ('c'): {
     788             :                 // create checkbox for
     789           0 :                 auto checkableButton = new FXCheckButton(table->myColumns.at(columnIndex)->getVerticalCellFrame(),
     790           0 :                         "false", table, MID_DECALSTABLE_CHECKBOX, GUIDesignMFXCheckableButton);
     791           0 :                 myCells.push_back(new Cell(table, checkableButton, columnIndex, numCells));
     792           0 :                 break;
     793             :             }
     794           0 :             case ('b'): {
     795             :                 // create button for open decal
     796           0 :                 auto button = GUIDesigns::buildFXButton(table->myColumns.at(columnIndex)->getVerticalCellFrame(),
     797           0 :                                                         "", TL("Open decal"), TL("Open decal."),
     798             :                                                         GUIIconSubSys::getIcon(GUIIcon::OPEN), table, MID_DECALSTABLE_OPEN, GUIDesignButtonIcon);
     799           0 :                 myCells.push_back(new Cell(table, button, columnIndex, numCells));
     800           0 :                 break;
     801             :             }
     802           0 :             case ('d'): {
     803             :                 // create button for delete decal
     804           0 :                 auto button = GUIDesigns::buildFXButton(table->myColumns.at(columnIndex)->getVerticalCellFrame(),
     805           0 :                                                         "", TL("Remove decal"), TL("Remove decal."),
     806             :                                                         GUIIconSubSys::getIcon(GUIIcon::REMOVE), table, MID_DECALSTABLE_REMOVE, GUIDesignButtonIcon);
     807           0 :                 myCells.push_back(new Cell(table, button, columnIndex, numCells));
     808           0 :                 break;
     809             :             }
     810           0 :             default:
     811           0 :                 throw ProcessError("Invalid Cell type");
     812             :         }
     813             :     }
     814           0 : }
     815             : 
     816             : 
     817           0 : MFXDecalsTable::Row::~Row() {
     818             :     // delete all cells
     819           0 :     for (const auto& cell : myCells) {
     820           0 :         delete cell;
     821             :     }
     822           0 : }
     823             : 
     824             : 
     825             : std::string
     826           0 : MFXDecalsTable::Row::getText(int index) const {
     827           0 :     if (myCells.at(index)->getTextField()) {
     828           0 :         return myCells.at(index)->getTextField()->getText().text();
     829             :     } else {
     830           0 :         throw ProcessError("Cell doesn't have a textField");
     831             :     }
     832             : }
     833             : 
     834             : 
     835             : void
     836           0 : MFXDecalsTable::Row::setText(int index, const std::string& text) const {
     837             :     // set text
     838           0 :     myCells.at(index)->getTextField()->setText(text.c_str());
     839           0 : }
     840             : 
     841             : 
     842             : const std::vector<MFXDecalsTable::Cell*>&
     843           0 : MFXDecalsTable::Row::getCells() const {
     844           0 :     return myCells;
     845             : }
     846             : 
     847             : 
     848           0 : MFXDecalsTable::Row::Row() {}
     849             : 
     850             : /****************************************************************************/

Generated by: LCOV version 1.14