Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
GUIMessageWindow.cpp
Go to the documentation of this file.
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/****************************************************************************/
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// ===========================================================================
37
40FXHiliteStyle* GUIMessageWindow::myStyles = new FXHiliteStyle[8];
42std::map<std::string, std::string> GUIMessageWindow::myTypeStrings;
43
44// ===========================================================================
45// FOX callback mapping
46// ===========================================================================
47
48FXDEFMAP(GUIMessageWindow) GUIMessageWindowMap[] = {
49 FXMAPFUNC(SEL_KEYPRESS, 0, GUIMessageWindow::onKeyPress),
50};
51
52FXIMPLEMENT_ABSTRACT(GUIMessageWindow, FXText, GUIMessageWindowMap, ARRAYNUMBER(GUIMessageWindowMap))
53
54// ===========================================================================
55// method definitions
56// ===========================================================================
57GUIMessageWindow::GUIMessageWindow(FXComposite* parent, GUIMainWindow* mainWindow) :
58 FXText(parent, nullptr, 0, 0, 0, 0, 0, 50),
59 myMainWindow(mainWindow),
60 myErrorRetriever(nullptr),
61 myMessageRetriever(nullptr),
62 myWarningRetriever(nullptr) {
63 setStyled(true);
64 setEditable(false);
65 // fill styles
66 fillStyles();
67 // set styles
68 setHiliteStyles(myStyles);
69 myTimeText = TL(" time");
70 // see GUIGlObject.cpp
71 myTypeStrings[StringUtils::to_lower_case(TL("edge"))] = "edge";
72 myTypeStrings[StringUtils::to_lower_case(TL("lane"))] = "lane";
73 myTypeStrings[StringUtils::to_lower_case(TL("junction"))] = "junction";
74 myTypeStrings[StringUtils::to_lower_case(TL("vehicle"))] = "vehicle";
75 myTypeStrings[StringUtils::to_lower_case(TL("person"))] = "person";
76 myTypeStrings[StringUtils::to_lower_case(TL("tlLogic"))] = "tlLogic";
77 myTypeStrings[StringUtils::to_lower_case(TL("busStop"))] = "busStop";
78 myTypeStrings[StringUtils::to_lower_case(TL("trainStop"))] = "busStop";
79 myTypeStrings[StringUtils::to_lower_case(TL("containerStop"))] = "containerStop";
80 myTypeStrings[StringUtils::to_lower_case(TL("chargingStation"))] = "chargingStation";
81 myTypeStrings[StringUtils::to_lower_case(TL("overheadWireSegment"))] = "overheadWireSegment";
82 myTypeStrings[StringUtils::to_lower_case(TL("parkingArea"))] = "parkingArea";
83}
84
85
92
93
94const GUIGlObject*
95GUIMessageWindow::getActiveStringObject(const FXString& text, const FXint pos, const FXint lineS, const FXint lineE) const {
96 const FXint idS = MAX2(text.rfind(" '", pos), text.rfind("='", pos));
97 const FXint idE = text.find("'", pos);
98 if (idS >= 0 && idE >= 0 && idS >= lineS && idE <= lineE) {
99 FXint typeS = text.rfind(" ", idS - 1);
100 if (typeS >= 0) {
101 if (text.at(typeS + 1) == '(') {
102 typeS++;
103 }
104 std::string type(text.mid(typeS + 1, idS - typeS - 1).lower().text());
105 const auto& tsIt = myTypeStrings.find(type);
106 if (tsIt != myTypeStrings.end()) {
107 type = tsIt->second;
108 }
109 const std::string id(text.mid(idS + 2, idE - idS - 2).text());
110 const std::string typedID = type + ":" + id;
112 //std::cout << " getActiveStringObject '" << typedID << "' o=" << (o == nullptr ? "NULL" : o->getMicrosimID()) << "\n";
113 return o;
114 }
115 }
116 return nullptr;
117}
118
120GUIMessageWindow::getTimeString(const FXString& text, const FXint pos) const {
121 const FXint end = text.find_first_of(" ,", pos + 1);
122 std::string time;
123 if (end >= 0) {
124 time = text.mid(pos, end - pos).text();
125 } else {
126 time = text.mid(pos, text.length() - pos).text();
127 if (time.empty()) {
128 return -1;
129 }
130 if (time.back() == '\n') {
131 time.pop_back();
132 }
133 if (time.empty()) {
134 return -1;
135 }
136 if (time.back() == '.') {
137 time.pop_back();
138 }
139 }
140 if (time.empty()) {
141 return -1;
142 }
143 if (time.front() == ' ') {
144 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 return string2time(time);
150 } catch (...) {
151 return -1;
152 }
153}
154
155
156void
157GUIMessageWindow::setCursorPos(FXint pos, FXbool notify) {
158 FXText::setCursorPos(pos, notify);
159 if (myLocateLinks) {
160 std::vector<std::string> viewIDs = myMainWindow->getViewIDs();
161 if (viewIDs.empty()) {
162 return;
163 }
164 GUIGlChildWindow* const child = myMainWindow->getViewByID(viewIDs[0]);
165 const FXString text = getText();
166 const GUIGlObject* const glObj = getActiveStringObject(text, pos, lineStart(pos), lineEnd(pos));
167 if (glObj != nullptr) {
168 child->setView(glObj->getGlID());
170 if (getApp()->getKeyState(KEY_Control_L)) {
172 }
173 } else if (gSimulation) {
174 const int lookback = MIN2(pos, 20);
175 const int start = MAX2(lineStart(pos), pos - lookback);
176 const FXString candidate = text.mid(start, lineEnd(pos) - start);
177 FXint timePos = candidate.find(myTimeText.c_str());
178 if (timePos > -1) {
179 timePos += (int)myTimeText.size() + 1;
180 if (pos >= 0 && pos > start + timePos) {
181 const SUMOTime t = getTimeString(candidate, timePos);
182 if (t >= 0) {
184 }
185 }
186 }
187 }
188 }
189}
190
191
192void
193GUIMessageWindow::appendMsg(GUIEventType eType, const std::string& msg) {
194 if (!isEnabled()) {
195 show();
196 }
197 // build the styled message
198 FXint style = 1;
199 switch (eType) {
201 // color: blue
202 style = 0;
203 break;
205 // color: fuchsia
206 style = 7;
207 break;
209 // color: red
210 style = 2;
211 break;
213 // color: yellow
214 style = 3;
215 break;
217 // color: green
218 style = 1;
219 break;
220 default:
221 assert(false);
222 }
223 FXString text(msg.c_str());
224 if (myLocateLinks) {
225 FXint pos = text.find("'");
226 while (pos >= 0) {
227 const GUIGlObject* const glObj = getActiveStringObject(text, pos + 1, 0, text.length());
228 if (glObj != nullptr) {
230 FXString insText = text.left(pos + 1);
231 FXText::appendStyledText(insText, style + 1);
232 text.erase(0, pos + 1);
233 pos = text.find("'");
234 insText = text.left(pos);
235 FXText::appendStyledText(insText, style + 4);
236 text.erase(0, pos);
237 }
238 pos = text.find("'", pos + 1);
239 }
240 // find time links
241 pos = text.find(myTimeText.c_str());
242 const int timeTerm = (int)myTimeText.size() + 1;
243 SUMOTime t = -1;
244 if (pos >= 0) {
245 t = getTimeString(text, pos + timeTerm);
246 }
247 if (t >= 0) {
248 FXString insText = text.left(pos + timeTerm);
249 FXText::appendStyledText(insText, style + 1);
250 text.erase(0, pos + timeTerm);
251 pos = text.find(" ");
252 if (pos < 0) {
253 pos = text.rfind(".");
254 }
255 insText = text.left(pos);
256 FXText::appendStyledText(insText, style + 4);
257 text.erase(0, pos);
258 }
259 }
260 // insert rest of the message
261 FXText::appendStyledText(text, style + 1, true);
262 FXText::setCursorPos(getLength() - 1);
263 FXText::setBottomLine(getLength() - 1);
264 if (isEnabled()) {
265 layout();
266 update();
267 }
268}
269
270
271void
273 std::string msg = std::string(100, '-') + "\n";
274 FXText::appendStyledText(msg.c_str(), (FXint) msg.length(), 1, true);
275 FXText::setCursorPos(getLength() - 1);
276 FXText::setBottomLine(getLength() - 1);
277 if (isEnabled()) {
278 layout();
279 update();
280 }
281}
282
283
284void
286 if (getLength() == 0) {
287 return;
288 }
289 FXText::removeText(0, getLength() - 1, true);
290 if (isEnabled()) {
291 layout();
292 update();
293 }
294}
295
296
297void
313
314
315void
323
324
325long
326GUIMessageWindow::onKeyPress(FXObject* o, FXSelector sel, void* ptr) {
327 FXEvent* e = (FXEvent*) ptr;
328 // permit ctrl+a, ctrl+c
329 if (e->state & CONTROLMASK) {
330 return FXText::onKeyPress(o, sel, ptr);
331 }
332 return 0;
333}
334
335
336FXHiliteStyle*
340
341
342void
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 myStyles[0].normalForeColor = blue;
352 myStyles[0].normalBackColor = white;
353 myStyles[0].selectForeColor = white;
354 myStyles[0].selectBackColor = blue;
355 myStyles[0].hiliteForeColor = blue;
356 myStyles[0].hiliteBackColor = white;
357 myStyles[0].activeBackColor = white;
358 myStyles[0].style = 0;
359 // set message text style
360 myStyles[1] = myStyles[0];
361 myStyles[1].normalForeColor = green;
362 myStyles[1].selectBackColor = green;
363 myStyles[1].hiliteForeColor = green;
364 myStyles[4] = myStyles[1];
365 myStyles[4].style = STYLE_UNDERLINE;
366 // set error text style
367 myStyles[2] = myStyles[0];
368 myStyles[2].normalForeColor = red;
369 myStyles[2].selectBackColor = red;
370 myStyles[2].hiliteForeColor = red;
371 myStyles[5] = myStyles[2];
372 myStyles[5].style = STYLE_UNDERLINE;
373 // set warning text style
374 myStyles[3] = myStyles[0];
375 myStyles[3].normalForeColor = yellow;
376 myStyles[3].selectBackColor = yellow;
377 myStyles[3].hiliteForeColor = yellow;
378 myStyles[6] = myStyles[3];
379 myStyles[6].style = STYLE_UNDERLINE;
380 // set GLDebug text style
381 myStyles[7] = myStyles[0];
382 myStyles[7].normalForeColor = fuchsia;
383 myStyles[7].selectBackColor = fuchsia;
384 myStyles[7].hiliteForeColor = fuchsia;
385}
386
387/****************************************************************************/
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[]
#define TL(string)
Definition MsgHandler.h:315
SUMOTime string2time(const std::string &r)
convert string to SUMOTime
Definition SUMOTime.cpp:46
#define TIME2STEPS(x)
Definition SUMOTime.h:57
bool gSimulation
Definition StdDefs.cpp:30
T MIN2(T a, T b)
Definition StdDefs.h:76
T MAX2(T a, T b)
Definition StdDefs.h:82
void setView(GUIGlID id)
Centers the view onto the given artifact.
GUIGlID getGlID() const
Returns the numerical id of the object.
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 void addBreakpoint(SUMOTime)
add breakpoint to the application
GUIGlChildWindow * getViewByID(const std::string &id) const
get specific view by ID
std::vector< std::string > getViewIDs() const
get view IDs
A logging window for the gui.
GUIMainWindow * myMainWindow
main window
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.
void fillStyles()
fill styles
static std::string myTimeText
The time text to look for.
static FXHiliteStyle * myStyles
The text colors used.
static bool myLocateLinks
whether messages are linked to the GUI elements
void appendMsg(GUIEventType eType, const std::string &msg)
Adds new text to the window.
static FXHiliteStyle * getStyles()
The text colors used.
virtual void setCursorPos(FXint pos, FXbool notify=FALSE)
set cursor position over a certain line
SUMOTime getTimeString(const FXString &text, const FXint pos) const
get time string object
static std::map< std::string, std::string > myTypeStrings
The translated type strings text to look for.
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.
static MsgHandler * getGLDebugInstance()
Returns the instance to add GLdebug to.
static MsgHandler * getErrorInstance()
Returns the instance to add errors to.
static MsgHandler * getDebugInstance()
Returns the instance to add debug to.
static MsgHandler * getWarningInstance()
Returns the instance to add warnings to.
virtual void removeRetriever(OutputDevice *retriever)
Removes the retriever from the handler.
static MsgHandler * getMessageInstance()
Returns the instance to add normal messages to.
static std::string to_lower_case(const std::string &str)
Transfers the content to lower case.