LCOV - code coverage report
Current view: top level - src/utils/gui/div - GUIMessageWindow.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 71.2 % 198 141
Test Date: 2024-12-21 15:45:41 Functions: 60.0 % 15 9

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2003-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    GUIMessageWindow.cpp
      15              : /// @author  Daniel Krajzewicz
      16              : /// @author  Michael Behrisch
      17              : /// @author  Jakob Erdmann
      18              : /// @date    Tue, 25 Nov 2003
      19              : ///
      20              : // A logging window for the gui
      21              : /****************************************************************************/
      22              : #include <config.h>
      23              : 
      24              : #include <cassert>
      25              : #include <utils/common/MsgHandler.h>
      26              : #include <utils/gui/globjects/GUIGlObjectStorage.h>
      27              : #include <utils/gui/windows/GUIGlChildWindow.h>
      28              : #include <utils/gui/windows/GUIMainWindow.h>
      29              : #include <utils/gui/div/GUIGlobalSelection.h>
      30              : #include <fxkeys.h>
      31              : #include "GUIMessageWindow.h"
      32              : 
      33              : 
      34              : // ===========================================================================
      35              : // static members
      36              : // ===========================================================================
      37              : 
      38              : bool GUIMessageWindow::myLocateLinks = true;
      39              : SUMOTime GUIMessageWindow::myBreakPointOffset = TIME2STEPS(-5);
      40              : FXHiliteStyle* GUIMessageWindow::myStyles = new FXHiliteStyle[8];
      41              : std::string GUIMessageWindow::myTimeText;
      42              : std::map<std::string, std::string> GUIMessageWindow::myTypeStrings;
      43              : 
      44              : // ===========================================================================
      45              : // FOX callback mapping
      46              : // ===========================================================================
      47              : 
      48              : FXDEFMAP(GUIMessageWindow) GUIMessageWindowMap[] = {
      49              :     FXMAPFUNC(SEL_KEYPRESS, 0, GUIMessageWindow::onKeyPress),
      50              : };
      51              : 
      52      2222826 : FXIMPLEMENT_ABSTRACT(GUIMessageWindow, FXText, GUIMessageWindowMap, ARRAYNUMBER(GUIMessageWindowMap))
      53              : 
      54              : // ===========================================================================
      55              : // method definitions
      56              : // ===========================================================================
      57         7598 : GUIMessageWindow::GUIMessageWindow(FXComposite* parent, GUIMainWindow* mainWindow) :
      58              :     FXText(parent, nullptr, 0, 0, 0, 0, 0, 50),
      59         7598 :     myMainWindow(mainWindow),
      60         7598 :     myErrorRetriever(nullptr),
      61         7598 :     myMessageRetriever(nullptr),
      62         7598 :     myWarningRetriever(nullptr) {
      63         7598 :     setStyled(true);
      64         7598 :     setEditable(false);
      65              :     // fill styles
      66         7598 :     fillStyles();
      67              :     // set styles
      68         7598 :     setHiliteStyles(myStyles);
      69         7598 :     myTimeText = TL(" time");
      70              :     // see GUIGlObject.cpp
      71         7598 :     myTypeStrings[StringUtils::to_lower_case(TL("edge"))] = "edge";
      72         7598 :     myTypeStrings[StringUtils::to_lower_case(TL("lane"))] = "lane";
      73         7598 :     myTypeStrings[StringUtils::to_lower_case(TL("junction"))] = "junction";
      74         7598 :     myTypeStrings[StringUtils::to_lower_case(TL("vehicle"))] = "vehicle";
      75         7598 :     myTypeStrings[StringUtils::to_lower_case(TL("person"))] = "person";
      76         7598 :     myTypeStrings[StringUtils::to_lower_case(TL("tlLogic"))] = "tlLogic";
      77         7598 :     myTypeStrings[StringUtils::to_lower_case(TL("busStop"))] = "busStop";
      78         7598 :     myTypeStrings[StringUtils::to_lower_case(TL("trainStop"))] = "busStop";
      79         7598 :     myTypeStrings[StringUtils::to_lower_case(TL("containerStop"))] = "containerStop";
      80         7598 :     myTypeStrings[StringUtils::to_lower_case(TL("chargingStation"))] = "chargingStation";
      81         7598 :     myTypeStrings[StringUtils::to_lower_case(TL("overheadWireSegment"))] = "overheadWireSegment";
      82         7598 :     myTypeStrings[StringUtils::to_lower_case(TL("parkingArea"))] = "parkingArea";
      83         7598 : }
      84              : 
      85              : 
      86        15160 : GUIMessageWindow::~GUIMessageWindow() {
      87         7580 :     delete[] myStyles;
      88         7580 :     delete myMessageRetriever;
      89         7580 :     delete myErrorRetriever;
      90         7580 :     delete myWarningRetriever;
      91        15160 : }
      92              : 
      93              : 
      94              : const GUIGlObject*
      95        88060 : GUIMessageWindow::getActiveStringObject(const FXString& text, const FXint pos, const FXint lineS, const FXint lineE) const {
      96        88060 :     const FXint idS = MAX2(text.rfind(" '", pos), text.rfind("='", pos));
      97        88060 :     const FXint idE = text.find("'", pos);
      98        88060 :     if (idS >= 0 && idE >= 0 && idS >= lineS && idE <= lineE) {
      99        64982 :         FXint typeS = text.rfind(" ", idS - 1);
     100        64982 :         if (typeS >= 0) {
     101        63467 :             if (text.at(typeS + 1) == '(') {
     102              :                 typeS++;
     103              :             }
     104        63467 :             std::string type(text.mid(typeS + 1, idS - typeS - 1).lower().text());
     105              :             const auto& tsIt = myTypeStrings.find(type);
     106        63467 :             if (tsIt != myTypeStrings.end()) {
     107        38530 :                 type = tsIt->second;
     108              :             }
     109        63467 :             const std::string id(text.mid(idS + 2, idE - idS - 2).text());
     110        63467 :             const std::string typedID = type + ":" + id;
     111        63467 :             const GUIGlObject* o = GUIGlObjectStorage::gIDStorage.getObjectBlocking(typedID);
     112              :             //std::cout << " getActiveStringObject '" << typedID << "' o=" << (o == nullptr ? "NULL" : o->getMicrosimID()) << "\n";
     113              :             return o;
     114              :         }
     115              :     }
     116              :     return nullptr;
     117              : }
     118              : 
     119              : SUMOTime
     120        22989 : GUIMessageWindow::getTimeString(const FXString& text, const FXint pos) const {
     121        22989 :     const FXint end = text.find_first_of(" ,", pos + 1);
     122              :     std::string time;
     123        22989 :     if (end >= 0) {
     124         2796 :         time = text.mid(pos, end - pos).text();
     125              :     } else {
     126        43182 :         time = text.mid(pos, text.length() - pos).text();
     127        21591 :         if (time.empty()) {
     128              :             return -1;
     129              :         }
     130        21591 :         if (time.back() == '\n') {
     131              :             time.pop_back();
     132              :         }
     133        21591 :         if (time.empty()) {
     134              :             return -1;
     135              :         }
     136        21588 :         if (time.back() == '.') {
     137              :             time.pop_back();
     138              :         }
     139              :     }
     140        22986 :     if (time.empty()) {
     141              :         return -1;
     142              :     }
     143        21702 :     if (time.front() == ' ') {
     144        14294 :         time = time.substr(1);
     145              :     }
     146              :     //std::cout << "text='" << text.text() << "' pos=" << pos << " time='" << time << "'\n";
     147              :     try {
     148              :         //std::cout << "  SUMOTime=" << string2time(time) << "\n";
     149        21702 :         return string2time(time);
     150           82 :     } catch (...) {
     151              :         return -1;
     152           82 :     }
     153              : }
     154              : 
     155              : 
     156              : void
     157            0 : GUIMessageWindow::setCursorPos(FXint pos, FXbool notify) {
     158            0 :     FXText::setCursorPos(pos, notify);
     159            0 :     if (myLocateLinks) {
     160            0 :         std::vector<std::string> viewIDs = myMainWindow->getViewIDs();
     161            0 :         if (viewIDs.empty()) {
     162              :             return;
     163              :         }
     164            0 :         GUIGlChildWindow* const child = myMainWindow->getViewByID(viewIDs[0]);
     165            0 :         const FXString text = getText();
     166            0 :         const GUIGlObject* const glObj = getActiveStringObject(text, pos, lineStart(pos), lineEnd(pos));
     167            0 :         if (glObj != nullptr) {
     168            0 :             child->setView(glObj->getGlID());
     169            0 :             GUIGlObjectStorage::gIDStorage.unblockObject(glObj->getGlID());
     170            0 :             if (getApp()->getKeyState(KEY_Control_L)) {
     171            0 :                 gSelected.toggleSelection(glObj->getGlID());
     172              :             }
     173            0 :         } else if (gSimulation) {
     174              :             const int lookback = MIN2(pos, 20);
     175            0 :             const int start = MAX2(lineStart(pos), pos - lookback);
     176            0 :             const FXString candidate = text.mid(start, lineEnd(pos) - start);
     177            0 :             FXint timePos = candidate.find(myTimeText.c_str());
     178            0 :             if (timePos > -1) {
     179            0 :                 timePos += (int)myTimeText.size() + 1;
     180            0 :                 if (pos >= 0 && pos > start + timePos) {
     181            0 :                     const SUMOTime t = getTimeString(candidate, timePos);
     182            0 :                     if (t >= 0) {
     183            0 :                         myMainWindow->addBreakpoint(t + myBreakPointOffset);
     184              :                     }
     185              :                 }
     186              :             }
     187            0 :         }
     188            0 :     }
     189              : }
     190              : 
     191              : 
     192              : void
     193        67922 : GUIMessageWindow::appendMsg(GUIEventType eType, const std::string& msg) {
     194        67922 :     if (!isEnabled()) {
     195            0 :         show();
     196              :     }
     197              :     // build the styled message
     198              :     FXint style = 1;
     199        67922 :     switch (eType) {
     200              :         case GUIEventType::DEBUG_OCCURRED:
     201              :             // color: blue
     202              :             style = 0;
     203              :             break;
     204              :         case GUIEventType::GLDEBUG_OCCURRED:
     205              :             // color: fuchsia
     206              :             style = 7;
     207              :             break;
     208              :         case GUIEventType::ERROR_OCCURRED:
     209              :             // color: red
     210              :             style = 2;
     211              :             break;
     212              :         case GUIEventType::WARNING_OCCURRED:
     213              :             // color: yellow
     214              :             style = 3;
     215              :             break;
     216              :         case GUIEventType::MESSAGE_OCCURRED:
     217              :             // color: green
     218              :             style = 1;
     219              :             break;
     220        67922 :         default:
     221              :             assert(false);
     222              :     }
     223        67922 :     FXString text(msg.c_str());
     224        67922 :     if (myLocateLinks) {
     225        67922 :         FXint pos = text.find("'");
     226       155982 :         while (pos >= 0) {
     227        88060 :             const GUIGlObject* const glObj = getActiveStringObject(text, pos + 1, 0, text.length());
     228        88060 :             if (glObj != nullptr) {
     229        26472 :                 GUIGlObjectStorage::gIDStorage.unblockObject(glObj->getGlID());
     230        26472 :                 FXString insText = text.left(pos + 1);
     231        26472 :                 FXText::appendStyledText(insText, style + 1);
     232        26472 :                 text.erase(0, pos + 1);
     233        26472 :                 pos = text.find("'");
     234        26472 :                 insText = text.left(pos);
     235        26472 :                 FXText::appendStyledText(insText, style + 4);
     236        26472 :                 text.erase(0, pos);
     237        26472 :             }
     238        88060 :             pos = text.find("'", pos + 1);
     239              :         }
     240              :         // find time links
     241        67922 :         pos = text.find(myTimeText.c_str());
     242        67922 :         const int timeTerm = (int)myTimeText.size() + 1;
     243              :         SUMOTime t = -1;
     244        67922 :         if (pos >= 0) {
     245        22989 :             t = getTimeString(text, pos + timeTerm);
     246              :         }
     247        22989 :         if (t >= 0) {
     248        21620 :             FXString insText = text.left(pos + timeTerm);
     249        21620 :             FXText::appendStyledText(insText, style + 1);
     250        21620 :             text.erase(0, pos + timeTerm);
     251        21620 :             pos = text.find(" ");
     252        21620 :             if (pos < 0) {
     253        13132 :                 pos = text.rfind(".");
     254              :             }
     255        21620 :             insText = text.left(pos);
     256        21620 :             FXText::appendStyledText(insText, style + 4);
     257        21620 :             text.erase(0, pos);
     258        21620 :         }
     259              :     }
     260              :     // insert rest of the message
     261        67922 :     FXText::appendStyledText(text, style + 1, true);
     262        67922 :     FXText::setCursorPos(getLength() - 1);
     263        67922 :     FXText::setBottomLine(getLength() - 1);
     264        67922 :     if (isEnabled()) {
     265        67922 :         layout();
     266        67922 :         update();
     267              :     }
     268        67922 : }
     269              : 
     270              : 
     271              : void
     272        22280 : GUIMessageWindow::addSeparator() {
     273        22280 :     std::string msg = std::string(100, '-') + "\n";
     274        22280 :     FXText::appendStyledText(msg.c_str(), (FXint) msg.length(), 1, true);
     275        22280 :     FXText::setCursorPos(getLength() - 1);
     276        22280 :     FXText::setBottomLine(getLength() - 1);
     277        22280 :     if (isEnabled()) {
     278        22280 :         layout();
     279        22280 :         update();
     280              :     }
     281        22280 : }
     282              : 
     283              : 
     284              : void
     285            0 : GUIMessageWindow::clear() {
     286            0 :     if (getLength() == 0) {
     287              :         return;
     288              :     }
     289            0 :     FXText::removeText(0, getLength() - 1, true);
     290            0 :     if (isEnabled()) {
     291            0 :         layout();
     292            0 :         update();
     293              :     }
     294              : }
     295              : 
     296              : 
     297              : void
     298            0 : GUIMessageWindow::registerMsgHandlers() {
     299            0 :     if (myMessageRetriever == nullptr) {
     300              :         // initialize only if registration is requested
     301            0 :         myMessageRetriever = new MsgOutputDevice(this, GUIEventType::MESSAGE_OCCURRED);
     302            0 :         myErrorRetriever = new MsgOutputDevice(this, GUIEventType::ERROR_OCCURRED);
     303            0 :         myDebugRetriever = new MsgOutputDevice(this, GUIEventType::DEBUG_OCCURRED);
     304            0 :         myGLDebugRetriever = new MsgOutputDevice(this, GUIEventType::GLDEBUG_OCCURRED);
     305            0 :         myWarningRetriever = new MsgOutputDevice(this, GUIEventType::WARNING_OCCURRED);
     306              :     }
     307            0 :     MsgHandler::getMessageInstance()->addRetriever(myMessageRetriever);
     308            0 :     MsgHandler::getDebugInstance()->addRetriever(myDebugRetriever);
     309            0 :     MsgHandler::getGLDebugInstance()->addRetriever(myGLDebugRetriever);
     310            0 :     MsgHandler::getErrorInstance()->addRetriever(myErrorRetriever);
     311            0 :     MsgHandler::getWarningInstance()->addRetriever(myWarningRetriever);
     312            0 : }
     313              : 
     314              : 
     315              : void
     316            0 : GUIMessageWindow::unregisterMsgHandlers() {
     317            0 :     MsgHandler::getMessageInstance()->removeRetriever(myMessageRetriever);
     318            0 :     MsgHandler::getDebugInstance()->removeRetriever(myDebugRetriever);
     319            0 :     MsgHandler::getGLDebugInstance()->removeRetriever(myGLDebugRetriever);
     320            0 :     MsgHandler::getErrorInstance()->removeRetriever(myErrorRetriever);
     321            0 :     MsgHandler::getWarningInstance()->removeRetriever(myWarningRetriever);
     322            0 : }
     323              : 
     324              : 
     325              : long
     326            0 : GUIMessageWindow::onKeyPress(FXObject* o, FXSelector sel, void* ptr) {
     327              :     FXEvent* e = (FXEvent*) ptr;
     328              :     // permit ctrl+a, ctrl+c
     329            0 :     if (e->state & CONTROLMASK) {
     330            0 :         return FXText::onKeyPress(o, sel, ptr);
     331              :     }
     332              :     return 0;
     333              : }
     334              : 
     335              : 
     336              : FXHiliteStyle*
     337            0 : GUIMessageWindow::getStyles() {
     338            0 :     return myStyles;
     339              : }
     340              : 
     341              : 
     342              : void
     343         7598 : GUIMessageWindow::fillStyles() {
     344              :     const FXColor white   = FXRGB(0xff, 0xff, 0xff);
     345              :     const FXColor blue    = FXRGB(0x00, 0x00, 0x88);
     346              :     const FXColor green   = FXRGB(0x00, 0x88, 0x00);
     347              :     const FXColor red     = FXRGB(0x88, 0x00, 0x00);
     348              :     const FXColor yellow  = FXRGB(0xe6, 0x98, 0x00);
     349              :     const FXColor fuchsia = FXRGB(0x88, 0x00, 0x88);
     350              :     // set separator style
     351         7598 :     myStyles[0].normalForeColor = blue;
     352         7598 :     myStyles[0].normalBackColor = white;
     353         7598 :     myStyles[0].selectForeColor = white;
     354         7598 :     myStyles[0].selectBackColor = blue;
     355         7598 :     myStyles[0].hiliteForeColor = blue;
     356         7598 :     myStyles[0].hiliteBackColor = white;
     357         7598 :     myStyles[0].activeBackColor = white;
     358         7598 :     myStyles[0].style = 0;
     359              :     // set message text style
     360         7598 :     myStyles[1] = myStyles[0];
     361         7598 :     myStyles[1].normalForeColor = green;
     362         7598 :     myStyles[1].selectBackColor = green;
     363         7598 :     myStyles[1].hiliteForeColor = green;
     364         7598 :     myStyles[4] = myStyles[1];
     365         7598 :     myStyles[4].style = STYLE_UNDERLINE;
     366              :     // set error text style
     367         7598 :     myStyles[2] = myStyles[0];
     368         7598 :     myStyles[2].normalForeColor = red;
     369         7598 :     myStyles[2].selectBackColor = red;
     370         7598 :     myStyles[2].hiliteForeColor = red;
     371         7598 :     myStyles[5] = myStyles[2];
     372         7598 :     myStyles[5].style = STYLE_UNDERLINE;
     373              :     // set warning text style
     374         7598 :     myStyles[3] = myStyles[0];
     375         7598 :     myStyles[3].normalForeColor = yellow;
     376         7598 :     myStyles[3].selectBackColor = yellow;
     377         7598 :     myStyles[3].hiliteForeColor = yellow;
     378         7598 :     myStyles[6] = myStyles[3];
     379         7598 :     myStyles[6].style = STYLE_UNDERLINE;
     380              :     // set GLDebug text style
     381         7598 :     myStyles[7] = myStyles[0];
     382         7598 :     myStyles[7].normalForeColor = fuchsia;
     383         7598 :     myStyles[7].selectBackColor = fuchsia;
     384         7598 :     myStyles[7].hiliteForeColor = fuchsia;
     385         7598 : }
     386              : 
     387              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1