1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2003-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
10 /// @file    GUIMessageWindow.cpp
11 /// @author  Daniel Krajzewicz
12 /// @author  Michael Behrisch
13 /// @author  Jakob Erdmann
14 /// @date    Tue, 25 Nov 2003
15 /// @version $Id$
16 ///
17 // A logging window for the gui
18 /****************************************************************************/
19 
20 
21 // ===========================================================================
22 // included modules
23 // ===========================================================================
24 #include <config.h>
25 
26 #include <cassert>
27 #include <utils/common/MsgHandler.h>
28 #include <utils/gui/globjects/GUIGlObjectStorage.h>
29 #include <utils/gui/windows/GUIGlChildWindow.h>
30 #include <utils/gui/windows/GUIMainWindow.h>
31 #include <utils/gui/div/GUIGlobalSelection.h>
32 #include <fxkeys.h>
33 #include "GUIMessageWindow.h"
34 
35 
36 // ===========================================================================
37 // static members
38 // ===========================================================================
39 bool GUIMessageWindow::myLocateLinks = true;
40 
41 
42 // ===========================================================================
43 // method definitions
44 // ===========================================================================
GUIMessageWindow(FXComposite * parent)45 GUIMessageWindow::GUIMessageWindow(FXComposite* parent) :
46     FXText(parent, nullptr, 0, 0, 0, 0, 0, 50),
47     myStyles(new FXHiliteStyle[8]),
48     myErrorRetriever(nullptr),
49     myMessageRetriever(nullptr),
50     myWarningRetriever(nullptr) {
51     setStyled(true);
52     setEditable(false);
53     const FXColor white   = FXRGB(0xff, 0xff, 0xff);
54     const FXColor blue    = FXRGB(0x00, 0x00, 0x88);
55     const FXColor green   = FXRGB(0x00, 0x88, 0x00);
56     const FXColor red     = FXRGB(0x88, 0x00, 0x00);
57     const FXColor yellow  = FXRGB(0xe6, 0x98, 0x00);
58     const FXColor fuchsia = FXRGB(0x88, 0x00, 0x88);
59     // set separator style
60     myStyles[0].normalForeColor = blue;
61     myStyles[0].normalBackColor = white;
62     myStyles[0].selectForeColor = white;
63     myStyles[0].selectBackColor = blue;
64     myStyles[0].hiliteForeColor = blue;
65     myStyles[0].hiliteBackColor = white;
66     myStyles[0].activeBackColor = white;
67     myStyles[0].style = 0;
68     // set message text style
69     myStyles[1] = myStyles[0];
70     myStyles[1].normalForeColor = green;
71     myStyles[1].selectBackColor = green;
72     myStyles[1].hiliteForeColor = green;
73     myStyles[4] = myStyles[1];
74     myStyles[4].style = STYLE_UNDERLINE;
75     // set error text style
76     myStyles[2] = myStyles[0];
77     myStyles[2].normalForeColor = red;
78     myStyles[2].selectBackColor = red;
79     myStyles[2].hiliteForeColor = red;
80     myStyles[5] = myStyles[2];
81     myStyles[5].style = STYLE_UNDERLINE;
82     // set warning text style
83     myStyles[3] = myStyles[0];
84     myStyles[3].normalForeColor = yellow;
85     myStyles[3].selectBackColor = yellow;
86     myStyles[3].hiliteForeColor = yellow;
87     myStyles[6] = myStyles[3];
88     myStyles[6].style = STYLE_UNDERLINE;
89     // set GLDebug text style
90     myStyles[7] = myStyles[0];
91     myStyles[7].normalForeColor = fuchsia;
92     myStyles[7].selectBackColor = fuchsia;
93     myStyles[7].hiliteForeColor = fuchsia;
94     //
95     setHiliteStyles(myStyles);
96 }
97 
98 
~GUIMessageWindow()99 GUIMessageWindow::~GUIMessageWindow() {
100     delete[] myStyles;
101     delete myMessageRetriever;
102     delete myErrorRetriever;
103     delete myWarningRetriever;
104 }
105 
106 
107 const GUIGlObject*
getActiveStringObject(const FXString & text,const FXint pos,const FXint lineS,const FXint lineE) const108 GUIMessageWindow::getActiveStringObject(const FXString& text, const FXint pos, const FXint lineS, const FXint lineE) const {
109     const FXint idS = MAX2(text.rfind(" '", pos), text.rfind("='", pos));
110     const FXint idE = text.find("'", pos);
111     if (idS >= 0 && idE >= 0 && idS >= lineS && idE <= lineE) {
112         const FXint typeS = text.rfind(" ", idS - 1);
113         if (typeS >= 0) {
114             std::string type(text.mid(typeS + 1, idS - typeS - 1).lower().text());
115             if (type == "tllogic") {
116                 type = "tlLogic"; // see GUIGlObject.cpp
117             } else if (type == "busstop") {
118                 type = "busStop";
119             } else if (type == "containerstop") {
120                 type = "containerStop";
121             } else if (type == "chargingstation") {
122                 type = "chargingStation";
123             } else if (type == "parkingarea") {
124                 type = "parkingArea";
125             }
126             const std::string id(text.mid(idS + 2, idE - idS - 2).text());
127             return GUIGlObjectStorage::gIDStorage.getObjectBlocking(type + ":" + id);
128         }
129     }
130     return nullptr;
131 }
132 
133 
134 void
setCursorPos(FXint pos,FXbool notify)135 GUIMessageWindow::setCursorPos(FXint pos, FXbool notify) {
136     FXText::setCursorPos(pos, notify);
137     if (myLocateLinks) {
138         GUIMainWindow* const main = GUIMainWindow::getInstance();
139         std::vector<std::string> viewIDs = main->getViewIDs();
140         if (viewIDs.empty()) {
141             return;
142         }
143         GUIGlChildWindow* const child = main->getViewByID(viewIDs[0]);
144         const FXString text = getText();
145         const GUIGlObject* const glObj = getActiveStringObject(text, pos, lineStart(pos), lineEnd(pos));
146         if (glObj != nullptr) {
147             child->setView(glObj->getGlID());
148             GUIGlObjectStorage::gIDStorage.unblockObject(glObj->getGlID());
149             if (getApp()->getKeyState(KEY_Control_L)) {
150                 gSelected.toggleSelection(glObj->getGlID());
151             }
152         }
153     }
154 }
155 
156 
157 void
appendMsg(GUIEventType eType,const std::string & msg)158 GUIMessageWindow::appendMsg(GUIEventType eType, const std::string& msg) {
159     if (!isEnabled()) {
160         show();
161     }
162     // build the styled message
163     FXint style = 1;
164     switch (eType) {
165         case EVENT_DEBUG_OCCURRED:
166             // color: blue
167             style = 0;
168             break;
169         case EVENT_GLDEBUG_OCCURRED:
170             // color: fuchsia
171             style = 7;
172             break;
173         case EVENT_ERROR_OCCURRED:
174             // color: red
175             style = 2;
176             break;
177         case EVENT_WARNING_OCCURRED:
178             // color: yellow
179             style = 3;
180             break;
181         case EVENT_MESSAGE_OCCURRED:
182             // color: green
183             style = 1;
184             break;
185         default:
186             assert(false);
187     }
188     FXString text(msg.c_str());
189     if (myLocateLinks) {
190         FXint pos = text.find("'");
191         while (pos >= 0) {
192             const GUIGlObject* const glObj = getActiveStringObject(text, pos + 1, 0, text.length());
193             if (glObj != nullptr) {
194                 GUIGlObjectStorage::gIDStorage.unblockObject(glObj->getGlID());
195                 FXString insText = text.left(pos + 1);
196                 FXText::appendStyledText(insText, style + 1);
197                 text.erase(0, pos + 1);
198                 pos = text.find("'");
199                 insText = text.left(pos);
200                 FXText::appendStyledText(insText, style + 4);
201                 text.erase(0, pos);
202             }
203             pos = text.find("'", pos + 1);
204         }
205     }
206     // insert rest of the message
207     FXText::appendStyledText(text, style + 1, true);
208     FXText::setCursorPos(getLength() - 1);
209     FXText::setBottomLine(getLength() - 1);
210     if (isEnabled()) {
211         layout();
212         update();
213     }
214 }
215 
216 
217 void
addSeparator()218 GUIMessageWindow::addSeparator() {
219     std::string msg = "----------------------------------------------------------------------------------------\n";
220     FXText::appendStyledText(msg.c_str(), (FXint) msg.length(), 1, true);
221     FXText::setCursorPos(getLength() - 1);
222     FXText::setBottomLine(getLength() - 1);
223     if (isEnabled()) {
224         layout();
225         update();
226     }
227 }
228 
229 
230 void
clear()231 GUIMessageWindow::clear() {
232     if (getLength() == 0) {
233         return;
234     }
235     FXText::removeText(0, getLength() - 1, true);
236     if (isEnabled()) {
237         layout();
238         update();
239     }
240 }
241 
242 
243 void
registerMsgHandlers()244 GUIMessageWindow::registerMsgHandlers() {
245     if (myMessageRetriever == nullptr) {
246         // initialize only if registration is requested
247         myMessageRetriever = new MsgOutputDevice(this, EVENT_MESSAGE_OCCURRED);
248         myErrorRetriever = new MsgOutputDevice(this, EVENT_ERROR_OCCURRED);
249         myDebugRetriever = new MsgOutputDevice(this, EVENT_DEBUG_OCCURRED);
250         myGLDebugRetriever = new MsgOutputDevice(this, EVENT_GLDEBUG_OCCURRED);
251         myWarningRetriever = new MsgOutputDevice(this, EVENT_WARNING_OCCURRED);
252     }
253     MsgHandler::getMessageInstance()->addRetriever(myMessageRetriever);
254     MsgHandler::getDebugInstance()->addRetriever(myDebugRetriever);
255     MsgHandler::getGLDebugInstance()->addRetriever(myGLDebugRetriever);
256     MsgHandler::getErrorInstance()->addRetriever(myErrorRetriever);
257     MsgHandler::getWarningInstance()->addRetriever(myWarningRetriever);
258 }
259 
260 
261 void
unregisterMsgHandlers()262 GUIMessageWindow::unregisterMsgHandlers() {
263     MsgHandler::getMessageInstance()->removeRetriever(myMessageRetriever);
264     MsgHandler::getDebugInstance()->removeRetriever(myDebugRetriever);
265     MsgHandler::getGLDebugInstance()->removeRetriever(myGLDebugRetriever);
266     MsgHandler::getErrorInstance()->removeRetriever(myErrorRetriever);
267     MsgHandler::getWarningInstance()->removeRetriever(myWarningRetriever);
268 }
269 
270 
271 /****************************************************************************/
272 
273