LCOV - code coverage report
Current view: top level - src/utils/gui/div - GUIMessageWindow.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 132 196 67.3 %
Date: 2024-05-02 15:31:40 Functions: 9 15 60.0 %

          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             : 
      42             : // ===========================================================================
      43             : // FOX callback mapping
      44             : // ===========================================================================
      45             : 
      46             : FXDEFMAP(GUIMessageWindow) GUIMessageWindowMap[] = {
      47             :     FXMAPFUNC(SEL_KEYPRESS, 0, GUIMessageWindow::onKeyPress),
      48             : };
      49             : 
      50     2688636 : FXIMPLEMENT_ABSTRACT(GUIMessageWindow, FXText, GUIMessageWindowMap, ARRAYNUMBER(GUIMessageWindowMap))
      51             : 
      52             : // ===========================================================================
      53             : // method definitions
      54             : // ===========================================================================
      55        7257 : GUIMessageWindow::GUIMessageWindow(FXComposite* parent, GUIMainWindow* mainWindow) :
      56             :     FXText(parent, nullptr, 0, 0, 0, 0, 0, 50),
      57        7257 :     myMainWindow(mainWindow),
      58        7257 :     myErrorRetriever(nullptr),
      59        7257 :     myMessageRetriever(nullptr),
      60        7257 :     myWarningRetriever(nullptr) {
      61        7257 :     setStyled(true);
      62        7257 :     setEditable(false);
      63             :     // fill styles
      64        7257 :     fillStyles();
      65             :     // set styles
      66        7257 :     setHiliteStyles(myStyles);
      67        7257 : }
      68             : 
      69             : 
      70       14496 : GUIMessageWindow::~GUIMessageWindow() {
      71        7248 :     delete[] myStyles;
      72        7248 :     delete myMessageRetriever;
      73        7248 :     delete myErrorRetriever;
      74        7248 :     delete myWarningRetriever;
      75       14496 : }
      76             : 
      77             : 
      78             : const GUIGlObject*
      79       65176 : GUIMessageWindow::getActiveStringObject(const FXString& text, const FXint pos, const FXint lineS, const FXint lineE) const {
      80       65176 :     const FXint idS = MAX2(text.rfind(" '", pos), text.rfind("='", pos));
      81       65176 :     const FXint idE = text.find("'", pos);
      82       65176 :     if (idS >= 0 && idE >= 0 && idS >= lineS && idE <= lineE) {
      83       48230 :         FXint typeS = text.rfind(" ", idS - 1);
      84       48230 :         if (typeS >= 0) {
      85       46726 :             if (text.at(typeS + 1) == '(') {
      86             :                 typeS++;
      87             :             }
      88       93452 :             std::string type(text.mid(typeS + 1, idS - typeS - 1).lower().text());
      89       46726 :             if (type == "tllogic") {
      90             :                 type = "tlLogic"; // see GUIGlObject.cpp
      91       93003 :             } else if (type == "busstop" || type == "trainstop") {
      92             :                 type = "busStop";
      93       46461 :             } else if (type == "containerstop") {
      94             :                 type = "containerStop";
      95       46449 :             } else if (type == "chargingstation") {
      96             :                 type = "chargingStation";
      97       46449 :             } else if (type == "overheadwiresegment") {
      98             :                 type = "overheadWireSegment";
      99       46449 :             } else if (type == "parkingarea") {
     100             :                 type = "parkingArea";
     101             :             }
     102       46726 :             const std::string id(text.mid(idS + 2, idE - idS - 2).text());
     103       46726 :             const std::string typedID = type + ":" + id;
     104       46726 :             const GUIGlObject* o = GUIGlObjectStorage::gIDStorage.getObjectBlocking(typedID);
     105             :             //std::cout << " getActiveStringObject '" << typedID << "' o=" << (o == nullptr ? "NULL" : o->getMicrosimID()) << "\n";
     106             :             return o;
     107             :         }
     108             :     }
     109             :     return nullptr;
     110             : }
     111             : 
     112             : SUMOTime
     113       18538 : GUIMessageWindow::getTimeString(const FXString& text, const FXint pos, const FXint /*lineS*/, const FXint /*lineE*/) const {
     114       18538 :     const FXint end = text.find(" ", pos + 1);
     115             :     std::string time;
     116       18538 :     if (end >= 0) {
     117        2522 :         time = text.mid(pos, end - pos).text();
     118             :     } else {
     119       34554 :         time = text.mid(pos, text.length() - pos).text();
     120       17277 :         if (time.empty()) {
     121             :             return -1;
     122             :         }
     123       17277 :         if (time.back() == '\n') {
     124             :             time.pop_back();
     125             :         }
     126       17277 :         if (time.empty()) {
     127             :             return -1;
     128             :         }
     129       17274 :         if (time.back() == '.') {
     130             :             time.pop_back();
     131             :         }
     132             :     }
     133       18535 :     if (time.empty()) {
     134             :         return -1;
     135             :     }
     136       17346 :     if (time.front() == ' ') {
     137       13656 :         time = time.substr(1);
     138             :     }
     139             :     //std::cout << "text='" << text.text() << "' pos=" << pos << " time='" << time << "'\n";
     140             :     try {
     141             :         //std::cout << "  SUMOTime=" << string2time(time) << "\n";
     142       17346 :         return string2time(time);
     143         129 :     } catch (...) {
     144             :         return -1;
     145         129 :     }
     146             : }
     147             : 
     148             : 
     149             : void
     150           0 : GUIMessageWindow::setCursorPos(FXint pos, FXbool notify) {
     151           0 :     FXText::setCursorPos(pos, notify);
     152           0 :     if (myLocateLinks) {
     153           0 :         GUIMainWindow* const main = GUIMainWindow::getInstance();
     154           0 :         std::vector<std::string> viewIDs = main->getViewIDs();
     155           0 :         if (viewIDs.empty()) {
     156             :             return;
     157             :         }
     158           0 :         GUIGlChildWindow* const child = main->getViewByID(viewIDs[0]);
     159           0 :         const FXString text = getText();
     160           0 :         const GUIGlObject* const glObj = getActiveStringObject(text, pos, lineStart(pos), lineEnd(pos));
     161           0 :         if (glObj != nullptr) {
     162           0 :             child->setView(glObj->getGlID());
     163           0 :             GUIGlObjectStorage::gIDStorage.unblockObject(glObj->getGlID());
     164           0 :             if (getApp()->getKeyState(KEY_Control_L)) {
     165           0 :                 gSelected.toggleSelection(glObj->getGlID());
     166             :             }
     167             :         } else {
     168             :             const int lookback = MIN2(pos, 20);
     169           0 :             const int start = MAX2(lineStart(pos), pos - lookback);
     170           0 :             const FXString candidate = text.mid(start, lineEnd(pos) - start);
     171           0 :             FXint timePos = candidate.find(TL(" time"));
     172           0 :             if (timePos > -1) {
     173           0 :                 timePos += (int)std::string(TL(" time")).size() + 1;
     174           0 :                 SUMOTime t = -1;
     175           0 :                 if (pos >= 0 && pos > start + timePos) {
     176           0 :                     t = getTimeString(candidate, timePos, 0, (int)candidate.length());
     177           0 :                     if (t >= 0) {
     178           0 :                         t += myBreakPointOffset;
     179           0 :                         std::vector<SUMOTime> breakpoints = myMainWindow->retrieveBreakpoints();
     180           0 :                         if (std::find(breakpoints.begin(), breakpoints.end(), t) == breakpoints.end()) {
     181           0 :                             breakpoints.push_back(t);
     182           0 :                             std::sort(breakpoints.begin(), breakpoints.end());
     183           0 :                             myMainWindow->setBreakpoints(breakpoints);
     184           0 :                             myMainWindow->setStatusBarText(TLF("Set breakpoint at %", time2string(t)));
     185             :                         }
     186             :                     }
     187             :                 }
     188             :             }
     189           0 :         }
     190           0 :     }
     191             : }
     192             : 
     193             : 
     194             : void
     195       56462 : GUIMessageWindow::appendMsg(GUIEventType eType, const std::string& msg) {
     196       56462 :     if (!isEnabled()) {
     197           0 :         show();
     198             :     }
     199             :     // build the styled message
     200             :     FXint style = 1;
     201       56462 :     switch (eType) {
     202             :         case GUIEventType::DEBUG_OCCURRED:
     203             :             // color: blue
     204             :             style = 0;
     205             :             break;
     206             :         case GUIEventType::GLDEBUG_OCCURRED:
     207             :             // color: fuchsia
     208             :             style = 7;
     209             :             break;
     210             :         case GUIEventType::ERROR_OCCURRED:
     211             :             // color: red
     212             :             style = 2;
     213             :             break;
     214             :         case GUIEventType::WARNING_OCCURRED:
     215             :             // color: yellow
     216             :             style = 3;
     217             :             break;
     218             :         case GUIEventType::MESSAGE_OCCURRED:
     219             :             // color: green
     220             :             style = 1;
     221             :             break;
     222       56462 :         default:
     223             :             assert(false);
     224             :     }
     225      112924 :     FXString text(msg.c_str());
     226       56462 :     if (myLocateLinks) {
     227       56462 :         FXint pos = text.find("'");
     228      121638 :         while (pos >= 0) {
     229       65176 :             const GUIGlObject* const glObj = getActiveStringObject(text, pos + 1, 0, text.length());
     230       65176 :             if (glObj != nullptr) {
     231       20495 :                 GUIGlObjectStorage::gIDStorage.unblockObject(glObj->getGlID());
     232       20495 :                 FXString insText = text.left(pos + 1);
     233       20495 :                 FXText::appendStyledText(insText, style + 1);
     234       20495 :                 text.erase(0, pos + 1);
     235       20495 :                 pos = text.find("'");
     236       20495 :                 insText = text.left(pos);
     237       20495 :                 FXText::appendStyledText(insText, style + 4);
     238       20495 :                 text.erase(0, pos);
     239       20495 :             }
     240       65176 :             pos = text.find("'", pos + 1);
     241             :         }
     242             :         // find time links
     243       56462 :         pos = text.find(TL(" time"));
     244       56462 :         const int timeTerm = (int)std::string(TL(" time")).size() + 1;
     245             :         SUMOTime t = -1;
     246       56462 :         if (pos >= 0) {
     247       18538 :             t = getTimeString(text, pos + timeTerm, 0, text.length());
     248             :         }
     249       18538 :         if (t >= 0) {
     250       17217 :             FXString insText = text.left(pos + timeTerm);
     251       17217 :             FXText::appendStyledText(insText, style + 1);
     252       17217 :             text.erase(0, pos + timeTerm);
     253       17217 :             pos = text.find(" ");
     254       17217 :             if (pos < 0) {
     255        9233 :                 pos = text.rfind(".");
     256             :             }
     257       17217 :             insText = text.left(pos);
     258       17217 :             FXText::appendStyledText(insText, style + 4);
     259       17217 :             text.erase(0, pos);
     260       17217 :         }
     261             :     }
     262             :     // insert rest of the message
     263       56462 :     FXText::appendStyledText(text, style + 1, true);
     264       56462 :     FXText::setCursorPos(getLength() - 1);
     265       56462 :     FXText::setBottomLine(getLength() - 1);
     266       56462 :     if (isEnabled()) {
     267       56462 :         layout();
     268       56462 :         update();
     269             :     }
     270       56462 : }
     271             : 
     272             : 
     273             : void
     274       21292 : GUIMessageWindow::addSeparator() {
     275       21292 :     std::string msg = "----------------------------------------------------------------------------------------\n";
     276       21292 :     FXText::appendStyledText(msg.c_str(), (FXint) msg.length(), 1, true);
     277       21292 :     FXText::setCursorPos(getLength() - 1);
     278       21292 :     FXText::setBottomLine(getLength() - 1);
     279       21292 :     if (isEnabled()) {
     280       21292 :         layout();
     281       21292 :         update();
     282             :     }
     283       21292 : }
     284             : 
     285             : 
     286             : void
     287           0 : GUIMessageWindow::clear() {
     288           0 :     if (getLength() == 0) {
     289             :         return;
     290             :     }
     291           0 :     FXText::removeText(0, getLength() - 1, true);
     292           0 :     if (isEnabled()) {
     293           0 :         layout();
     294           0 :         update();
     295             :     }
     296             : }
     297             : 
     298             : 
     299             : void
     300           0 : GUIMessageWindow::registerMsgHandlers() {
     301           0 :     if (myMessageRetriever == nullptr) {
     302             :         // initialize only if registration is requested
     303           0 :         myMessageRetriever = new MsgOutputDevice(this, GUIEventType::MESSAGE_OCCURRED);
     304           0 :         myErrorRetriever = new MsgOutputDevice(this, GUIEventType::ERROR_OCCURRED);
     305           0 :         myDebugRetriever = new MsgOutputDevice(this, GUIEventType::DEBUG_OCCURRED);
     306           0 :         myGLDebugRetriever = new MsgOutputDevice(this, GUIEventType::GLDEBUG_OCCURRED);
     307           0 :         myWarningRetriever = new MsgOutputDevice(this, GUIEventType::WARNING_OCCURRED);
     308             :     }
     309           0 :     MsgHandler::getMessageInstance()->addRetriever(myMessageRetriever);
     310           0 :     MsgHandler::getDebugInstance()->addRetriever(myDebugRetriever);
     311           0 :     MsgHandler::getGLDebugInstance()->addRetriever(myGLDebugRetriever);
     312           0 :     MsgHandler::getErrorInstance()->addRetriever(myErrorRetriever);
     313           0 :     MsgHandler::getWarningInstance()->addRetriever(myWarningRetriever);
     314           0 : }
     315             : 
     316             : 
     317             : void
     318           0 : GUIMessageWindow::unregisterMsgHandlers() {
     319           0 :     MsgHandler::getMessageInstance()->removeRetriever(myMessageRetriever);
     320           0 :     MsgHandler::getDebugInstance()->removeRetriever(myDebugRetriever);
     321           0 :     MsgHandler::getGLDebugInstance()->removeRetriever(myGLDebugRetriever);
     322           0 :     MsgHandler::getErrorInstance()->removeRetriever(myErrorRetriever);
     323           0 :     MsgHandler::getWarningInstance()->removeRetriever(myWarningRetriever);
     324           0 : }
     325             : 
     326             : 
     327             : long
     328           0 : GUIMessageWindow::onKeyPress(FXObject* o, FXSelector sel, void* ptr) {
     329             :     FXEvent* e = (FXEvent*) ptr;
     330             :     // permit ctrl+a, ctrl+c
     331           0 :     if (e->state & CONTROLMASK) {
     332           0 :         return FXText::onKeyPress(o, sel, ptr);
     333             :     }
     334             :     return 0;
     335             : }
     336             : 
     337             : 
     338             : FXHiliteStyle*
     339           0 : GUIMessageWindow::getStyles() {
     340           0 :     return myStyles;
     341             : }
     342             : 
     343             : 
     344             : void
     345        7257 : GUIMessageWindow::fillStyles() {
     346             :     const FXColor white   = FXRGB(0xff, 0xff, 0xff);
     347             :     const FXColor blue    = FXRGB(0x00, 0x00, 0x88);
     348             :     const FXColor green   = FXRGB(0x00, 0x88, 0x00);
     349             :     const FXColor red     = FXRGB(0x88, 0x00, 0x00);
     350             :     const FXColor yellow  = FXRGB(0xe6, 0x98, 0x00);
     351             :     const FXColor fuchsia = FXRGB(0x88, 0x00, 0x88);
     352             :     // set separator style
     353        7257 :     myStyles[0].normalForeColor = blue;
     354        7257 :     myStyles[0].normalBackColor = white;
     355        7257 :     myStyles[0].selectForeColor = white;
     356        7257 :     myStyles[0].selectBackColor = blue;
     357        7257 :     myStyles[0].hiliteForeColor = blue;
     358        7257 :     myStyles[0].hiliteBackColor = white;
     359        7257 :     myStyles[0].activeBackColor = white;
     360        7257 :     myStyles[0].style = 0;
     361             :     // set message text style
     362        7257 :     myStyles[1] = myStyles[0];
     363        7257 :     myStyles[1].normalForeColor = green;
     364        7257 :     myStyles[1].selectBackColor = green;
     365        7257 :     myStyles[1].hiliteForeColor = green;
     366        7257 :     myStyles[4] = myStyles[1];
     367        7257 :     myStyles[4].style = STYLE_UNDERLINE;
     368             :     // set error text style
     369        7257 :     myStyles[2] = myStyles[0];
     370        7257 :     myStyles[2].normalForeColor = red;
     371        7257 :     myStyles[2].selectBackColor = red;
     372        7257 :     myStyles[2].hiliteForeColor = red;
     373        7257 :     myStyles[5] = myStyles[2];
     374        7257 :     myStyles[5].style = STYLE_UNDERLINE;
     375             :     // set warning text style
     376        7257 :     myStyles[3] = myStyles[0];
     377        7257 :     myStyles[3].normalForeColor = yellow;
     378        7257 :     myStyles[3].selectBackColor = yellow;
     379        7257 :     myStyles[3].hiliteForeColor = yellow;
     380        7257 :     myStyles[6] = myStyles[3];
     381        7257 :     myStyles[6].style = STYLE_UNDERLINE;
     382             :     // set GLDebug text style
     383        7257 :     myStyles[7] = myStyles[0];
     384        7257 :     myStyles[7].normalForeColor = fuchsia;
     385        7257 :     myStyles[7].selectBackColor = fuchsia;
     386        7257 :     myStyles[7].hiliteForeColor = fuchsia;
     387        7257 : }
     388             : 
     389             : /****************************************************************************/

Generated by: LCOV version 1.14