LCOV - code coverage report
Current view: top level - src/utils/gui/windows - GUIMainWindow.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 61.4 % 210 129
Test Date: 2024-11-21 15:56:26 Functions: 54.5 % 33 18

            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    GUIMainWindow.cpp
      15              : /// @author  Daniel Krajzewicz
      16              : /// @author  Jakob Erdmann
      17              : /// @author  Michael Behrisch
      18              : /// @date    Tue, 29.05.2005
      19              : ///
      20              : //
      21              : /****************************************************************************/
      22              : #include <config.h>
      23              : 
      24              : #include <string>
      25              : #include <algorithm>
      26              : #include <utils/foxtools/fxheader.h>
      27              : // fx3d includes windows.h so we need to guard against macro pollution
      28              : #ifdef WIN32
      29              : #define NOMINMAX
      30              : #endif
      31              : #include <fx3d.h>
      32              : #ifdef WIN32
      33              : #undef NOMINMAX
      34              : #endif
      35              : #include <utils/common/MsgHandler.h>
      36              : #include <utils/common/StringUtils.h>
      37              : #include <utils/foxtools/MFXImageHelper.h>
      38              : #include <utils/foxtools/MFXStaticToolTip.h>
      39              : #include <utils/gui/images/GUITexturesHelper.h>
      40              : #include <utils/gui/div/GUIDesigns.h>
      41              : #include <utils/options/OptionsCont.h>
      42              : #include "GUIMainWindow.h"
      43              : #include "GUIGlChildWindow.h"
      44              : 
      45              : 
      46              : // ===========================================================================
      47              : // static member definitions
      48              : // ===========================================================================
      49              : GUIMainWindow* GUIMainWindow::myInstance = nullptr;
      50              : 
      51              : // ===========================================================================
      52              : // member method definitions
      53              : // ===========================================================================
      54         7548 : GUIMainWindow::GUIMainWindow(FXApp* app) :
      55              :     FXMainWindow(app, "sumo-gui main window", nullptr, nullptr, DECOR_ALL, 20, 20, 600, 400),
      56         7548 :     myAmFullScreen(false),
      57         7548 :     myTrackerLock(true),
      58         7548 :     myGLVisual(new FXGLVisual(app, VISUAL_DOUBLEBUFFER)),
      59         7548 :     myAmGaming(false),
      60         7548 :     myListInternal(false),
      61         7548 :     myListParking(true),
      62        15096 :     myListTeleporting(false) {
      63              :     // build static tooltips
      64         7548 :     myStaticTooltipMenu = new MFXStaticToolTip(app);
      65         7548 :     myStaticTooltipView = new MFXStaticToolTip(app);
      66              :     // build bold font
      67              :     FXFontDesc fdesc;
      68         7548 :     app->getNormalFont()->getFontDesc(fdesc);
      69         7548 :     fdesc.weight = FXFont::Bold;
      70         7548 :     GUIDesignHeight = (int)(fdesc.size / 90.0 * 18) + 5;
      71         7548 :     myBoldFont = new FXFont(app, fdesc);
      72              :     // https://en.wikipedia.org/wiki/Noto_fonts should be widely available
      73         7548 :     myFallbackFont = new FXFont(app, "Noto Sans CJK JP");
      74              :     // build docks
      75         7548 :     myTopDock = new FXDockSite(this, LAYOUT_SIDE_TOP | LAYOUT_FILL_X);
      76         7548 :     myBottomDock = new FXDockSite(this, LAYOUT_SIDE_BOTTOM | LAYOUT_FILL_X);
      77         7548 :     myLeftDock = new FXDockSite(this, LAYOUT_SIDE_LEFT | LAYOUT_FILL_Y);
      78         7548 :     myRightDock = new FXDockSite(this, LAYOUT_SIDE_RIGHT | LAYOUT_FILL_Y);
      79              :     // avoid instance Windows twice
      80         7548 :     if (myInstance != nullptr) {
      81            0 :         throw ProcessError("MainWindow initialized twice");
      82              :     }
      83         7548 :     myInstance = this;
      84              :     //myGLVisual->setStencilSize(8); // enable stencil buffer
      85         7548 : }
      86              : 
      87              : 
      88         7529 : GUIMainWindow::~GUIMainWindow() {
      89         7529 :     delete myStaticTooltipMenu;
      90         7529 :     delete myStaticTooltipView;
      91         7529 :     delete myBoldFont;
      92         7529 :     delete myFallbackFont;
      93         7529 :     delete myTopDock;
      94         7529 :     delete myBottomDock;
      95         7529 :     delete myLeftDock;
      96         7529 :     delete myRightDock;
      97         7529 :     myInstance = nullptr;
      98         7529 : }
      99              : 
     100              : 
     101              : 
     102              : void
     103         7103 : GUIMainWindow::addGLChild(GUIGlChildWindow* child) {
     104         7103 :     myGLWindows.push_back(child);
     105         7103 : }
     106              : 
     107              : 
     108              : void
     109         7084 : GUIMainWindow::removeGLChild(GUIGlChildWindow* child) {
     110         7084 :     std::vector<GUIGlChildWindow*>::iterator i = std::find(myGLWindows.begin(), myGLWindows.end(), child);
     111         7084 :     if (i != myGLWindows.end()) {
     112         7084 :         myGLWindows.erase(i);
     113              :     }
     114         7084 : }
     115              : 
     116              : 
     117              : void
     118            0 : GUIMainWindow::addChild(FXMainWindow* child) {
     119            0 :     myTrackerLock.lock();
     120            0 :     myTrackerWindows.push_back(child);
     121            0 :     myTrackerLock.unlock();
     122            0 : }
     123              : 
     124              : 
     125              : void
     126            0 : GUIMainWindow::removeChild(FXMainWindow* child) {
     127            0 :     myTrackerLock.lock();
     128            0 :     std::vector<FXMainWindow*>::iterator i = std::find(myTrackerWindows.begin(), myTrackerWindows.end(), child);
     129            0 :     myTrackerWindows.erase(i);
     130            0 :     myTrackerLock.unlock();
     131            0 : }
     132              : 
     133              : 
     134              : FXDockSite*
     135            0 : GUIMainWindow::getTopDock() {
     136            0 :     return myTopDock;
     137              : }
     138              : 
     139              : 
     140              : std::vector<std::string>
     141           48 : GUIMainWindow::getViewIDs() const {
     142              :     std::vector<std::string> ret;
     143           96 :     for (GUIGlChildWindow* const window : myGLWindows) {
     144           96 :         ret.push_back(window->getTitle().text());
     145              :     }
     146           48 :     return ret;
     147            0 : }
     148              : 
     149              : 
     150              : GUIGlChildWindow*
     151          300 : GUIMainWindow::getViewByID(const std::string& id) const {
     152          300 :     for (GUIGlChildWindow* const window : myGLWindows) {
     153          300 :         if (std::string(window->getTitle().text()) == id) {
     154              :             return window;
     155              :         }
     156              :     }
     157              :     return nullptr;
     158              : }
     159              : 
     160              : 
     161              : void
     162            0 : GUIMainWindow::removeViewByID(const std::string& id) {
     163            0 :     for (GUIGlChildWindow* const window : myGLWindows) {
     164            0 :         if (std::string(window->getTitle().text()) == id) {
     165            0 :             window->close();
     166            0 :             removeGLChild(window);
     167              :             return;
     168              :         }
     169              :     }
     170              : }
     171              : 
     172              : 
     173              : FXFont*
     174            0 : GUIMainWindow::getBoldFont() {
     175            0 :     return myBoldFont;
     176              : }
     177              : 
     178              : FXFont*
     179            0 : GUIMainWindow::getFallbackFont() {
     180            0 :     return myFallbackFont;
     181              : }
     182              : 
     183              : const std::vector<GUIGlChildWindow*>&
     184      5830971 : GUIMainWindow::getViews() const {
     185      5830971 :     return myGLWindows;
     186              : }
     187              : 
     188              : 
     189              : void
     190      5824684 : GUIMainWindow::updateChildren(int msg) {
     191              :     // inform views
     192      5824684 :     myMDIClient->forallWindows(this, FXSEL(SEL_COMMAND, msg), nullptr);
     193              :     // inform other windows
     194      5824684 :     myTrackerLock.lock();
     195      5824684 :     for (int i = 0; i < (int)myTrackerWindows.size(); i++) {
     196            0 :         myTrackerWindows[i]->handle(this, FXSEL(SEL_COMMAND, msg), nullptr);
     197              :     }
     198      5824684 :     myTrackerLock.unlock();
     199      5824684 : }
     200              : 
     201              : 
     202              : FXGLVisual*
     203         7103 : GUIMainWindow::getGLVisual() const {
     204         7103 :     return myGLVisual;
     205              : }
     206              : 
     207              : 
     208              : MFXStaticToolTip*
     209       124155 : GUIMainWindow::getStaticTooltipMenu() const {
     210       124155 :     return myStaticTooltipMenu;
     211              : }
     212              : 
     213              : 
     214              : MFXStaticToolTip*
     215      1079410 : GUIMainWindow::getStaticTooltipView() const {
     216      1079410 :     return myStaticTooltipView;
     217              : }
     218              : 
     219              : 
     220              : FXLabel*
     221            0 : GUIMainWindow::getCartesianLabel() {
     222            0 :     return myCartesianCoordinate;
     223              : }
     224              : 
     225              : 
     226              : FXLabel*
     227            0 : GUIMainWindow::getGeoLabel() {
     228            0 :     return myGeoCoordinate;
     229              : }
     230              : 
     231              : 
     232              : FXLabel*
     233            0 : GUIMainWindow::getTestLabel() {
     234            0 :     return myTestCoordinate;
     235              : }
     236              : 
     237              : 
     238              : FXHorizontalFrame*
     239            0 : GUIMainWindow::getTestFrame() {
     240            0 :     return myTestFrame;
     241              : }
     242              : 
     243              : 
     244              : bool
     245        14238 : GUIMainWindow::isGaming() const {
     246        14238 :     return myAmGaming;
     247              : }
     248              : 
     249              : 
     250              : bool
     251            0 : GUIMainWindow::listInternal() const {
     252            0 :     return myListInternal;
     253              : }
     254              : 
     255              : 
     256              : bool
     257            0 : GUIMainWindow::listParking() const {
     258            0 :     return myListParking;
     259              : }
     260              : 
     261              : 
     262              : bool
     263            0 : GUIMainWindow::listTeleporting() const {
     264            0 :     return myListTeleporting;
     265              : }
     266              : 
     267              : 
     268              : GUIMainWindow*
     269      5831477 : GUIMainWindow::getInstance() {
     270      5831477 :     if (myInstance != nullptr) {
     271      5831429 :         return myInstance;
     272              :     }
     273           96 :     throw ProcessError("A GUIMainWindow instance was not yet constructed.");
     274              : }
     275              : 
     276              : 
     277              : GUISUMOAbstractView*
     278           45 : GUIMainWindow::getActiveView() const {
     279           45 :     GUIGlChildWindow* w = dynamic_cast<GUIGlChildWindow*>(myMDIClient->getActiveChild());
     280           45 :     if (w != nullptr) {
     281           45 :         return w->getView();
     282              :     }
     283              :     return nullptr;
     284              : }
     285              : 
     286              : 
     287              : void
     288        14650 : GUIMainWindow::setWindowSizeAndPos() {
     289        14650 :     int windowWidth = getApp()->reg().readIntEntry("SETTINGS", "width", 600);
     290        14650 :     int windowHeight = getApp()->reg().readIntEntry("SETTINGS", "height", 400);
     291        14650 :     const OptionsCont& oc = OptionsCont::getOptions();
     292        29300 :     if (oc.isSet("window-size")) {
     293           80 :         std::vector<std::string> windowSize = oc.getStringVector("window-size");
     294           40 :         if (windowSize.size() != 2) {
     295            0 :             WRITE_ERROR(TL("option window-size requires INT,INT"));
     296              :         } else {
     297              :             try {
     298           40 :                 windowWidth = StringUtils::toInt(windowSize[0]);
     299           40 :                 windowHeight = StringUtils::toInt(windowSize[1]);
     300            0 :             } catch (NumberFormatException& e) {
     301            0 :                 WRITE_ERROR("option window-size requires INT,INT " + toString(e.what()));
     302            0 :             }
     303              :         }
     304           40 :     }
     305        29300 :     if (oc.isSet("window-size") || getApp()->reg().readIntEntry("SETTINGS", "maximized", 0) == 0 || oc.isSet("window-pos")) {
     306              :         // when restoring previous pos, make sure the window fits fully onto the current screen
     307        14650 :         int x = MAX2(0, MIN2(getApp()->reg().readIntEntry("SETTINGS", "x", 150), getApp()->getRootWindow()->getWidth() - windowWidth));
     308        14650 :         int y = MAX2(50, MIN2(getApp()->reg().readIntEntry("SETTINGS", "y", 150), getApp()->getRootWindow()->getHeight() - windowHeight));
     309        29300 :         if (oc.isSet("window-pos")) {
     310           80 :             std::vector<std::string> windowPos = oc.getStringVector("window-pos");
     311           40 :             if (windowPos.size() != 2) {
     312            0 :                 WRITE_ERROR(TL("option window-pos requires INT,INT"));
     313              :             } else {
     314              :                 try {
     315           40 :                     x = StringUtils::toInt(windowPos[0]);
     316           40 :                     y = StringUtils::toInt(windowPos[1]);
     317            0 :                 } catch (NumberFormatException& e) {
     318            0 :                     WRITE_ERROR("option window-pos requires INT,INT " + toString(e.what()));
     319            0 :                 }
     320              :             }
     321           40 :         }
     322        14650 :         move(x, y);
     323        14650 :         resize(windowWidth, windowHeight);
     324              :     }
     325        14650 : }
     326              : 
     327              : void
     328         7548 : GUIMainWindow::storeWindowSizeAndPos() {
     329         7548 :     if (!myAmFullScreen) {
     330         7548 :         getApp()->reg().writeIntEntry("SETTINGS", "x", getX());
     331         7548 :         getApp()->reg().writeIntEntry("SETTINGS", "y", getY());
     332         7548 :         getApp()->reg().writeIntEntry("SETTINGS", "width", getWidth());
     333         7548 :         getApp()->reg().writeIntEntry("SETTINGS", "height", getHeight());
     334              :     }
     335         7548 : }
     336              : 
     337              : 
     338              : void
     339         7548 : GUIMainWindow::buildLanguageMenu(FXMenuBar* menuBar) {
     340         7548 :     myLanguageMenu = new FXMenuPane(this);
     341         7548 :     GUIDesigns::buildFXMenuTitle(menuBar, TL("Langua&ge"), nullptr, myLanguageMenu);
     342              : 
     343        15096 :     GUIDesigns::buildFXMenuCommandShortcut(myLanguageMenu, "English", "", TL("Change language to english. (en)"),
     344              :                                            GUIIconSubSys::getIcon(GUIIcon::LANGUAGE_EN), this, MID_LANGUAGE_EN);
     345        15096 :     GUIDesigns::buildFXMenuCommandShortcut(myLanguageMenu, "Deutsch", "", TL("Change language to german. (de)"),
     346              :                                            GUIIconSubSys::getIcon(GUIIcon::LANGUAGE_DE), this, MID_LANGUAGE_DE);
     347        15096 :     GUIDesigns::buildFXMenuCommandShortcut(myLanguageMenu, "Español", "", TL("Change language to spanish. (es)"),
     348              :                                            GUIIconSubSys::getIcon(GUIIcon::LANGUAGE_ES), this, MID_LANGUAGE_ES);
     349        15096 :     GUIDesigns::buildFXMenuCommandShortcut(myLanguageMenu, "Français", "", TL("Change language to french. (fr)"),
     350              :                                            GUIIconSubSys::getIcon(GUIIcon::LANGUAGE_FR), this, MID_LANGUAGE_FR);
     351        15096 :     GUIDesigns::buildFXMenuCommandShortcut(myLanguageMenu, "Italiano", "", TL("Change language to italian. (it)"),
     352              :                                            GUIIconSubSys::getIcon(GUIIcon::LANGUAGE_IT), this, MID_LANGUAGE_IT);
     353        15096 :     GUIDesigns::buildFXMenuCommandShortcut(myLanguageMenu, "简体中文", "", TL("简体中文 (zh)"),
     354              :                                            GUIIconSubSys::getIcon(GUIIcon::LANGUAGE_ZH), this, MID_LANGUAGE_ZH);
     355        15096 :     GUIDesigns::buildFXMenuCommandShortcut(myLanguageMenu, "繁體中文", "", TL("繁體中文 (zh-Hant)"),
     356              :                                            GUIIconSubSys::getIcon(GUIIcon::LANGUAGE_ZHT), this, MID_LANGUAGE_ZHT);
     357        15096 :     GUIDesigns::buildFXMenuCommandShortcut(myLanguageMenu, "Türkçe", "", TL("Change language to turkish. (tr)"),
     358              :                                            GUIIconSubSys::getIcon(GUIIcon::LANGUAGE_TR), this, MID_LANGUAGE_TR);
     359        15096 :     GUIDesigns::buildFXMenuCommandShortcut(myLanguageMenu, "Magyar", "", TL("Change language to hungarian. (hu)"),
     360              :                                            GUIIconSubSys::getIcon(GUIIcon::LANGUAGE_HU), this, MID_LANGUAGE_HU);
     361         7548 : }
     362              : 
     363              : 
     364              : long
     365            0 : GUIMainWindow::onCmdChangeLanguage(FXObject*, FXSelector sel, void*) {
     366              :     // set language
     367              :     std::string langID;
     368              :     std::string lang;
     369              :     // continue depending of called button
     370            0 :     switch (FXSELID(sel)) {
     371              :         case MID_LANGUAGE_DE:
     372              :             langID = "de";
     373            0 :             lang = TL("german");
     374              :             break;
     375              :         case MID_LANGUAGE_ES:
     376              :             langID = "es";
     377            0 :             lang = TL("spanish");
     378              :             break;
     379              :         case MID_LANGUAGE_FR:
     380              :             langID = "fr";
     381            0 :             lang = TL("french");
     382              :             break;
     383              :         case MID_LANGUAGE_IT:
     384              :             langID = "it";
     385            0 :             lang = TL("italian");
     386              :             break;
     387              :         case MID_LANGUAGE_ZH:
     388              :             langID = "zh";
     389            0 :             lang = TL("simplified chinese");
     390              :             break;
     391              :         case MID_LANGUAGE_ZHT:
     392              :             langID = "zh-Hant";
     393            0 :             lang = TL("traditional chinese");
     394              :             break;
     395              :         case MID_LANGUAGE_TR:
     396              :             langID = "tr";
     397            0 :             lang = TL("turkish");
     398              :             break;
     399              :         case MID_LANGUAGE_HU:
     400              :             langID = "hu";
     401            0 :             lang = TL("hungarian");
     402              :             break;
     403              :         default:
     404              :             langID = "C";
     405            0 :             lang = TL("english");
     406              :             break;
     407              :     }
     408              :     // check if change language
     409            0 :     if (langID != gLanguage) {
     410              :         // update language
     411              :         gLanguage = langID;
     412              :         // show info
     413            0 :         WRITE_MESSAGE(TL("Language changed to ") + lang);
     414              :         // show dialog
     415            0 :         const std::string header = TL("Restart needed");
     416            0 :         const std::string body = TL("Changing display language needs restart to take effect.") + std::string("\n") +
     417              : #ifdef DEBUG
     418              : #ifdef WIN32
     419              :                                  TL("For the Debug build you might also need to set the LANG environment variable.") + std::string("\n") +
     420              : #endif
     421              : #endif
     422            0 :                                  TL("Under development. You can help to improve the translation at:") + std::string("\n") +
     423              :                                  "https://hosted.weblate.org/projects/eclipse-sumo/";
     424            0 :         FXMessageBox::information(getApp(), MBOX_OK, header.c_str(), "%s", body.c_str());
     425              :         // update language in registry (common for sumo and netedit)
     426            0 :         std::string appKey = getApp()->reg().getAppKey().text();
     427            0 :         if (appKey == "SUMO GUI") {
     428              :             // registry is written again later so we have to modify the "life" version
     429            0 :             getApp()->reg().writeStringEntry("gui", "language", langID.c_str());
     430              :         } else {
     431            0 :             FXRegistry reg("SUMO GUI", "sumo-gui");
     432            0 :             reg.read();
     433            0 :             reg.writeStringEntry("gui", "language", langID.c_str());
     434            0 :             reg.write();
     435            0 :         }
     436              :     }
     437            0 :     return 1;
     438              : }
     439              : 
     440              : 
     441              : long
     442      5570175 : GUIMainWindow::onUpdChangeLanguage(FXObject* obj, FXSelector, void*) {
     443              :     // get language menu command
     444      5570175 :     FXMenuCommand* menuCommand = dynamic_cast<FXMenuCommand*>(obj);
     445      5570175 :     if (menuCommand) {
     446              :         // check if change color
     447      5570175 :         if ((gLanguage == "C") && (menuCommand->getIcon() == GUIIconSubSys::getIcon(GUIIcon::LANGUAGE_EN))) {
     448       618924 :             menuCommand->setTextColor(FXRGB(0, 0, 255));
     449      4951251 :         } else if ((gLanguage == "de") && (menuCommand->getIcon() == GUIIconSubSys::getIcon(GUIIcon::LANGUAGE_DE))) {
     450            0 :             menuCommand->setTextColor(FXRGB(0, 0, 255));
     451      4951251 :         } else if ((gLanguage == "es") && (menuCommand->getIcon() == GUIIconSubSys::getIcon(GUIIcon::LANGUAGE_ES))) {
     452            0 :             menuCommand->setTextColor(FXRGB(0, 0, 255));
     453      4951251 :         } else if ((gLanguage == "fr") && (menuCommand->getIcon() == GUIIconSubSys::getIcon(GUIIcon::LANGUAGE_FR))) {
     454            0 :             menuCommand->setTextColor(FXRGB(0, 0, 255));
     455      4951251 :         } else if ((gLanguage == "it") && (menuCommand->getIcon() == GUIIconSubSys::getIcon(GUIIcon::LANGUAGE_IT))) {
     456            0 :             menuCommand->setTextColor(FXRGB(0, 0, 255));
     457      4951251 :         } else if ((gLanguage == "zh") && (menuCommand->getIcon() == GUIIconSubSys::getIcon(GUIIcon::LANGUAGE_ZH))) {
     458            0 :             menuCommand->setTextColor(FXRGB(0, 0, 255));
     459      4951251 :         } else if ((gLanguage == "zh-Hant") && (menuCommand->getIcon() == GUIIconSubSys::getIcon(GUIIcon::LANGUAGE_ZHT))) {
     460            0 :             menuCommand->setTextColor(FXRGB(0, 0, 255));
     461      4951251 :         } else if ((gLanguage == "tr") && (menuCommand->getIcon() == GUIIconSubSys::getIcon(GUIIcon::LANGUAGE_TR))) {
     462            0 :             menuCommand->setTextColor(FXRGB(0, 0, 255));
     463      4951251 :         } else if ((gLanguage == "hu") && (menuCommand->getIcon() == GUIIconSubSys::getIcon(GUIIcon::LANGUAGE_HU))) {
     464            0 :             menuCommand->setTextColor(FXRGB(0, 0, 255));
     465              :         } else {
     466      4951251 :             menuCommand->setTextColor(FXRGB(0, 0, 0));
     467              :         }
     468              :     }
     469      5570175 :     return 1;
     470              : }
     471              : 
     472              : 
     473              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1