Eclipse SUMO - Simulation of Urban MObility
GUIMessageWindow.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3// Copyright (C) 2003-2022 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/****************************************************************************/
20// A logging window for the gui
21/****************************************************************************/
22#include <config.h>
23
24#include <cassert>
30#include <fxkeys.h>
31#include "GUIMessageWindow.h"
32
33
34// ===========================================================================
35// static members
36// ===========================================================================
39
40/* -------------------------------------------------------------------------
41 * GUISUMOAbstractView - FOX callback mapping
42 * ----------------------------------------------------------------------- */
43FXDEFMAP(GUIMessageWindow) GUIMessageWindowMap[] = {
44 FXMAPFUNC(SEL_KEYPRESS, 0, GUIMessageWindow::onKeyPress),
45};
46
47
48FXIMPLEMENT_ABSTRACT(GUIMessageWindow, FXText, GUIMessageWindowMap, ARRAYNUMBER(GUIMessageWindowMap))
49
50// ===========================================================================
51// method definitions
52// ===========================================================================
53GUIMessageWindow::GUIMessageWindow(FXComposite* parent, GUIMainWindow* mainWindow) :
54 FXText(parent, nullptr, 0, 0, 0, 0, 0, 50),
55 myMainWindow(mainWindow),
56 myStyles(new FXHiliteStyle[8]),
57 myErrorRetriever(nullptr),
58 myMessageRetriever(nullptr),
59 myWarningRetriever(nullptr) {
60 setStyled(true);
61 setEditable(false);
62 const FXColor white = FXRGB(0xff, 0xff, 0xff);
63 const FXColor blue = FXRGB(0x00, 0x00, 0x88);
64 const FXColor green = FXRGB(0x00, 0x88, 0x00);
65 const FXColor red = FXRGB(0x88, 0x00, 0x00);
66 const FXColor yellow = FXRGB(0xe6, 0x98, 0x00);
67 const FXColor fuchsia = FXRGB(0x88, 0x00, 0x88);
68 // set separator style
69 myStyles[0].normalForeColor = blue;
70 myStyles[0].normalBackColor = white;
71 myStyles[0].selectForeColor = white;
72 myStyles[0].selectBackColor = blue;
73 myStyles[0].hiliteForeColor = blue;
74 myStyles[0].hiliteBackColor = white;
75 myStyles[0].activeBackColor = white;
76 myStyles[0].style = 0;
77 // set message text style
78 myStyles[1] = myStyles[0];
79 myStyles[1].normalForeColor = green;
80 myStyles[1].selectBackColor = green;
81 myStyles[1].hiliteForeColor = green;
82 myStyles[4] = myStyles[1];
83 myStyles[4].style = STYLE_UNDERLINE;
84 // set error text style
85 myStyles[2] = myStyles[0];
86 myStyles[2].normalForeColor = red;
87 myStyles[2].selectBackColor = red;
88 myStyles[2].hiliteForeColor = red;
89 myStyles[5] = myStyles[2];
90 myStyles[5].style = STYLE_UNDERLINE;
91 // set warning text style
92 myStyles[3] = myStyles[0];
93 myStyles[3].normalForeColor = yellow;
94 myStyles[3].selectBackColor = yellow;
95 myStyles[3].hiliteForeColor = yellow;
96 myStyles[6] = myStyles[3];
97 myStyles[6].style = STYLE_UNDERLINE;
98 // set GLDebug text style
99 myStyles[7] = myStyles[0];
100 myStyles[7].normalForeColor = fuchsia;
101 myStyles[7].selectBackColor = fuchsia;
102 myStyles[7].hiliteForeColor = fuchsia;
103 //
104 setHiliteStyles(myStyles);
105}
106
107
109 delete[] myStyles;
110 delete myMessageRetriever;
111 delete myErrorRetriever;
112 delete myWarningRetriever;
113}
114
115
116const GUIGlObject*
117GUIMessageWindow::getActiveStringObject(const FXString& text, const FXint pos, const FXint lineS, const FXint lineE) const {
118 const FXint idS = MAX2(text.rfind(" '", pos), text.rfind("='", pos));
119 const FXint idE = text.find("'", pos);
120 if (idS >= 0 && idE >= 0 && idS >= lineS && idE <= lineE) {
121 FXint typeS = text.rfind(" ", idS - 1);
122 if (typeS >= 0) {
123 if (text.at(typeS + 1) == '(') {
124 typeS++;
125 }
126 std::string type(text.mid(typeS + 1, idS - typeS - 1).lower().text());
127 if (type == "tllogic") {
128 type = "tlLogic"; // see GUIGlObject.cpp
129 } else if (type == "busstop" || type == "trainstop") {
130 type = "busStop";
131 } else if (type == "containerstop") {
132 type = "containerStop";
133 } else if (type == "chargingstation") {
134 type = "chargingStation";
135 } else if (type == "overheadwiresegment") {
136 type = "overheadWireSegment";
137 } else if (type == "parkingarea") {
138 type = "parkingArea";
139 }
140 const std::string id(text.mid(idS + 2, idE - idS - 2).text());
141 const std::string typedID = type + ":" + id;
143 //std::cout << " getActiveStringObject '" << typedID << "' o=" << (o == nullptr ? "NULL" : o->getMicrosimID()) << "\n";
144 return o;
145 }
146 }
147 return nullptr;
148}
149
151GUIMessageWindow::getTimeString(const FXString& text, const FXint pos, const FXint /*lineS*/, const FXint /*lineE*/) const {
152 const FXint end = text.find(" ", pos + 1);
153 std::string time;
154 if (end >= 0) {
155 time = text.mid(pos, end - pos).text();
156 } else {
157 time = text.mid(pos, text.length() - pos).text();
158 if (time.empty()) {
159 return -1;
160 }
161 if (time.back() == '\n') {
162 time.pop_back();
163 }
164 if (time.empty()) {
165 return -1;
166 }
167 if (time.back() == '.') {
168 time.pop_back();
169 }
170 }
171 if (time.empty()) {
172 return -1;
173 }
174 if (time.front() == ' ') {
175 time = time.substr(1);
176 }
177 //std::cout << "text='" << text.text() << "' pos=" << pos << " time='" << time << "'\n";
178 try {
179 //std::cout << " SUMOTime=" << string2time(time) << "\n";
180 return string2time(time);
181 } catch (...) {
182 return -1;
183 }
184}
185
186
187void
188GUIMessageWindow::setCursorPos(FXint pos, FXbool notify) {
189 FXText::setCursorPos(pos, notify);
190 if (myLocateLinks) {
192 std::vector<std::string> viewIDs = main->getViewIDs();
193 if (viewIDs.empty()) {
194 return;
195 }
196 GUIGlChildWindow* const child = main->getViewByID(viewIDs[0]);
197 const FXString text = getText();
198 const GUIGlObject* const glObj = getActiveStringObject(text, pos, lineStart(pos), lineEnd(pos));
199 if (glObj != nullptr) {
200 child->setView(glObj->getGlID());
202 if (getApp()->getKeyState(KEY_Control_L)) {
204 }
205 } else {
206 const int lookback = MIN2(pos, 20);
207 const int start = MAX2(lineStart(pos), pos - lookback);
208 const FXString candidate = text.mid(start, lineEnd(pos) - start);
209 FXint timePos = candidate.find(" time") + 6;
210 SUMOTime t = -1;
211 if (pos >= 0 && pos > start + timePos) {
212 t = getTimeString(candidate, timePos, 0, candidate.length());
213 if (t >= 0) {
215 std::vector<SUMOTime> breakpoints = myMainWindow->retrieveBreakpoints();
216 if (std::find(breakpoints.begin(), breakpoints.end(), t) == breakpoints.end()) {
217 breakpoints.push_back(t);
218 std::sort(breakpoints.begin(), breakpoints.end());
219 myMainWindow->setBreakpoints(breakpoints);
220 myMainWindow->setStatusBarText("Set breakpoint at " + time2string(t));
221 }
222 }
223 }
224 }
225 }
226}
227
228
229void
230GUIMessageWindow::appendMsg(GUIEventType eType, const std::string& msg) {
231 if (!isEnabled()) {
232 show();
233 }
234 // build the styled message
235 FXint style = 1;
236 switch (eType) {
238 // color: blue
239 style = 0;
240 break;
242 // color: fuchsia
243 style = 7;
244 break;
246 // color: red
247 style = 2;
248 break;
250 // color: yellow
251 style = 3;
252 break;
254 // color: green
255 style = 1;
256 break;
257 default:
258 assert(false);
259 }
260 FXString text(msg.c_str());
261 if (myLocateLinks) {
262 FXint pos = text.find("'");
263 while (pos >= 0) {
264 const GUIGlObject* const glObj = getActiveStringObject(text, pos + 1, 0, text.length());
265 if (glObj != nullptr) {
267 FXString insText = text.left(pos + 1);
268 FXText::appendStyledText(insText, style + 1);
269 text.erase(0, pos + 1);
270 pos = text.find("'");
271 insText = text.left(pos);
272 FXText::appendStyledText(insText, style + 4);
273 text.erase(0, pos);
274 }
275 pos = text.find("'", pos + 1);
276 }
277 // find time links
278 pos = text.find(" time");
279 SUMOTime t = -1;
280 if (pos >= 0) {
281 t = getTimeString(text, pos + 6, 0, text.length());
282 }
283 if (t >= 0) {
284 FXString insText = text.left(pos + 6);
285 FXText::appendStyledText(insText, style + 1);
286 text.erase(0, pos + 6);
287 pos = text.find(" ");
288 if (pos < 0) {
289 pos = text.rfind(".");
290 }
291 insText = text.left(pos);
292 FXText::appendStyledText(insText, style + 4);
293 text.erase(0, pos);
294 }
295 }
296 // insert rest of the message
297 FXText::appendStyledText(text, style + 1, true);
298 FXText::setCursorPos(getLength() - 1);
299 FXText::setBottomLine(getLength() - 1);
300 if (isEnabled()) {
301 layout();
302 update();
303 }
304}
305
306
307void
309 std::string msg = "----------------------------------------------------------------------------------------\n";
310 FXText::appendStyledText(msg.c_str(), (FXint) msg.length(), 1, true);
311 FXText::setCursorPos(getLength() - 1);
312 FXText::setBottomLine(getLength() - 1);
313 if (isEnabled()) {
314 layout();
315 update();
316 }
317}
318
319
320void
322 if (getLength() == 0) {
323 return;
324 }
325 FXText::removeText(0, getLength() - 1, true);
326 if (isEnabled()) {
327 layout();
328 update();
329 }
330}
331
332
333void
335 if (myMessageRetriever == nullptr) {
336 // initialize only if registration is requested
342 }
348}
349
350
351void
358}
359
360long
361GUIMessageWindow::onKeyPress(FXObject* o, FXSelector sel, void* ptr) {
362 FXEvent* e = (FXEvent*) ptr;
363 // permit ctrl+a, ctrl+c
364 if (e->state & CONTROLMASK) {
365 return FXText::onKeyPress(o, sel, ptr);
366 }
367 return 0;
368}
369
370/****************************************************************************/
long long int SUMOTime
Definition: GUI.h:36
GUIEventType
Definition: GUIEvent.h:32
@ MESSAGE_OCCURRED
send when a message occured
@ GLDEBUG_OCCURRED
send when a gldebug occured
@ ERROR_OCCURRED
send when a error occured
@ DEBUG_OCCURRED
send when a debug occured
@ WARNING_OCCURRED
send when a warning occured
GUISelectedStorage gSelected
A global holder of selected objects.
FXDEFMAP(GUIMessageWindow) GUIMessageWindowMap[]
std::string time2string(SUMOTime t)
convert SUMOTime to string
Definition: SUMOTime.cpp:68
SUMOTime string2time(const std::string &r)
convert string to SUMOTime
Definition: SUMOTime.cpp:45
#define TIME2STEPS(x)
Definition: SUMOTime.h:56
T MIN2(T a, T b)
Definition: StdDefs.h:71
T MAX2(T a, T b)
Definition: StdDefs.h:77
int main(int argc, char *argv[])
void setView(GUIGlID id)
Centers the view onto the given artifact.
GUIGlID getGlID() const
Returns the numerical id of the object.
Definition: GUIGlObject.h:102
void unblockObject(GUIGlID id)
Marks an object as unblocked.
GUIGlObject * getObjectBlocking(GUIGlID id) const
Returns the object from the container locking it.
static GUIGlObjectStorage gIDStorage
A single static instance of this class.
virtual const std::vector< SUMOTime > retrieveBreakpoints() const
retrieve breakpoints if provided by the application
virtual void setBreakpoints(const std::vector< SUMOTime > &)
Sets the breakpoints of the parent application.
virtual void setStatusBarText(const std::string &)
get status bar text (can be implemented in children)
static GUIMainWindow * getInstance()
get instance
A logging window for the gui.
GUIMainWindow * myMainWindow
OutputDevice * myGLDebugRetriever
void addSeparator()
Adds a a separator to this log window.
OutputDevice * myErrorRetriever
The instances of message retriever encapsulations.
void unregisterMsgHandlers()
unregister message handlers
static SUMOTime myBreakPointOffset
Offset when creating breakpoint by clicking on time links.
void clear()
Clears the window.
SUMOTime getTimeString(const FXString &text, const FXint pos, const FXint lineS, const FXint lineE) const
static bool myLocateLinks
whether messages are linked to the GUI elements
FXHiliteStyle * myStyles
The text colors used.
void appendMsg(GUIEventType eType, const std::string &msg)
Adds new text to the window.
virtual void setCursorPos(FXint pos, FXbool notify=FALSE)
set cursor position over a certain line
OutputDevice * myWarningRetriever
OutputDevice * myMessageRetriever
OutputDevice * myDebugRetriever
~GUIMessageWindow()
Destructor.
long onKeyPress(FXObject *o, FXSelector sel, void *data)
handle keys
const GUIGlObject * getActiveStringObject(const FXString &text, const FXint pos, const FXint lineS, const FXint lineE) const
get active string object
void registerMsgHandlers()
register message handlers
void toggleSelection(GUIGlID id)
Toggles selection of an object.
virtual void addRetriever(OutputDevice *retriever)
Adds a further retriever to the instance responsible for a certain msg type.
Definition: MsgHandler.cpp:185
static MsgHandler * getGLDebugInstance()
Returns the instance to add GLdebug to.
Definition: MsgHandler.cpp:97
static MsgHandler * getErrorInstance()
Returns the instance to add errors to.
Definition: MsgHandler.cpp:79
static MsgHandler * getDebugInstance()
Returns the instance to add debug to.
Definition: MsgHandler.cpp:88
static MsgHandler * getWarningInstance()
Returns the instance to add warnings to.
Definition: MsgHandler.cpp:66
virtual void removeRetriever(OutputDevice *retriever)
Removes the retriever from the handler.
Definition: MsgHandler.cpp:193
static MsgHandler * getMessageInstance()
Returns the instance to add normal messages to.
Definition: MsgHandler.cpp:53