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-2023 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];
41
42// ===========================================================================
43// FOX callback mapping
44// ===========================================================================
45
46FXDEFMAP(GUIMessageWindow) GUIMessageWindowMap[] = {
47 FXMAPFUNC(SEL_KEYPRESS, 0, GUIMessageWindow::onKeyPress),
48};
49
50FXIMPLEMENT_ABSTRACT(GUIMessageWindow, FXText, GUIMessageWindowMap, ARRAYNUMBER(GUIMessageWindowMap))
51
52// ===========================================================================
53// method definitions
54// ===========================================================================
55GUIMessageWindow::GUIMessageWindow(FXComposite* parent, GUIMainWindow* mainWindow) :
56 FXText(parent, nullptr, 0, 0, 0, 0, 0, 50),
57 myMainWindow(mainWindow),
58 myErrorRetriever(nullptr),
59 myMessageRetriever(nullptr),
60 myWarningRetriever(nullptr) {
61 setStyled(true);
62 setEditable(false);
63 // fill styles
64 fillStyles();
65 // set styles
66 setHiliteStyles(myStyles);
67}
68
69
76
77
78const GUIGlObject*
79GUIMessageWindow::getActiveStringObject(const FXString& text, const FXint pos, const FXint lineS, const FXint lineE) const {
80 const FXint idS = MAX2(text.rfind(" '", pos), text.rfind("='", pos));
81 const FXint idE = text.find("'", pos);
82 if (idS >= 0 && idE >= 0 && idS >= lineS && idE <= lineE) {
83 FXint typeS = text.rfind(" ", idS - 1);
84 if (typeS >= 0) {
85 if (text.at(typeS + 1) == '(') {
86 typeS++;
87 }
88 std::string type(text.mid(typeS + 1, idS - typeS - 1).lower().text());
89 if (type == "tllogic") {
90 type = "tlLogic"; // see GUIGlObject.cpp
91 } else if (type == "busstop" || type == "trainstop") {
92 type = "busStop";
93 } else if (type == "containerstop") {
94 type = "containerStop";
95 } else if (type == "chargingstation") {
96 type = "chargingStation";
97 } else if (type == "overheadwiresegment") {
98 type = "overheadWireSegment";
99 } else if (type == "parkingarea") {
100 type = "parkingArea";
101 }
102 const std::string id(text.mid(idS + 2, idE - idS - 2).text());
103 const std::string typedID = type + ":" + id;
105 //std::cout << " getActiveStringObject '" << typedID << "' o=" << (o == nullptr ? "NULL" : o->getMicrosimID()) << "\n";
106 return o;
107 }
108 }
109 return nullptr;
110}
111
113GUIMessageWindow::getTimeString(const FXString& text, const FXint pos, const FXint /*lineS*/, const FXint /*lineE*/) const {
114 const FXint end = text.find(" ", pos + 1);
115 std::string time;
116 if (end >= 0) {
117 time = text.mid(pos, end - pos).text();
118 } else {
119 time = text.mid(pos, text.length() - pos).text();
120 if (time.empty()) {
121 return -1;
122 }
123 if (time.back() == '\n') {
124 time.pop_back();
125 }
126 if (time.empty()) {
127 return -1;
128 }
129 if (time.back() == '.') {
130 time.pop_back();
131 }
132 }
133 if (time.empty()) {
134 return -1;
135 }
136 if (time.front() == ' ') {
137 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 return string2time(time);
143 } catch (...) {
144 return -1;
145 }
146}
147
148
149void
150GUIMessageWindow::setCursorPos(FXint pos, FXbool notify) {
151 FXText::setCursorPos(pos, notify);
152 if (myLocateLinks) {
154 std::vector<std::string> viewIDs = main->getViewIDs();
155 if (viewIDs.empty()) {
156 return;
157 }
158 GUIGlChildWindow* const child = main->getViewByID(viewIDs[0]);
159 const FXString text = getText();
160 const GUIGlObject* const glObj = getActiveStringObject(text, pos, lineStart(pos), lineEnd(pos));
161 if (glObj != nullptr) {
162 child->setView(glObj->getGlID());
164 if (getApp()->getKeyState(KEY_Control_L)) {
166 }
167 } else {
168 const int lookback = MIN2(pos, 20);
169 const int start = MAX2(lineStart(pos), pos - lookback);
170 const FXString candidate = text.mid(start, lineEnd(pos) - start);
171 FXint timePos = candidate.find(" time") + 6;
172 SUMOTime t = -1;
173 if (pos >= 0 && pos > start + timePos) {
174 t = getTimeString(candidate, timePos, 0, candidate.length());
175 if (t >= 0) {
177 std::vector<SUMOTime> breakpoints = myMainWindow->retrieveBreakpoints();
178 if (std::find(breakpoints.begin(), breakpoints.end(), t) == breakpoints.end()) {
179 breakpoints.push_back(t);
180 std::sort(breakpoints.begin(), breakpoints.end());
181 myMainWindow->setBreakpoints(breakpoints);
182 myMainWindow->setStatusBarText("Set breakpoint at " + time2string(t));
183 }
184 }
185 }
186 }
187 }
188}
189
190
191void
192GUIMessageWindow::appendMsg(GUIEventType eType, const std::string& msg) {
193 if (!isEnabled()) {
194 show();
195 }
196 // build the styled message
197 FXint style = 1;
198 switch (eType) {
200 // color: blue
201 style = 0;
202 break;
204 // color: fuchsia
205 style = 7;
206 break;
208 // color: red
209 style = 2;
210 break;
212 // color: yellow
213 style = 3;
214 break;
216 // color: green
217 style = 1;
218 break;
219 default:
220 assert(false);
221 }
222 FXString text(msg.c_str());
223 if (myLocateLinks) {
224 FXint pos = text.find("'");
225 while (pos >= 0) {
226 const GUIGlObject* const glObj = getActiveStringObject(text, pos + 1, 0, text.length());
227 if (glObj != nullptr) {
229 FXString insText = text.left(pos + 1);
230 FXText::appendStyledText(insText, style + 1);
231 text.erase(0, pos + 1);
232 pos = text.find("'");
233 insText = text.left(pos);
234 FXText::appendStyledText(insText, style + 4);
235 text.erase(0, pos);
236 }
237 pos = text.find("'", pos + 1);
238 }
239 // find time links
240 pos = text.find(" time");
241 SUMOTime t = -1;
242 if (pos >= 0) {
243 t = getTimeString(text, pos + 6, 0, text.length());
244 }
245 if (t >= 0) {
246 FXString insText = text.left(pos + 6);
247 FXText::appendStyledText(insText, style + 1);
248 text.erase(0, pos + 6);
249 pos = text.find(" ");
250 if (pos < 0) {
251 pos = text.rfind(".");
252 }
253 insText = text.left(pos);
254 FXText::appendStyledText(insText, style + 4);
255 text.erase(0, pos);
256 }
257 }
258 // insert rest of the message
259 FXText::appendStyledText(text, style + 1, true);
260 FXText::setCursorPos(getLength() - 1);
261 FXText::setBottomLine(getLength() - 1);
262 if (isEnabled()) {
263 layout();
264 update();
265 }
266}
267
268
269void
271 std::string msg = "----------------------------------------------------------------------------------------\n";
272 FXText::appendStyledText(msg.c_str(), (FXint) msg.length(), 1, true);
273 FXText::setCursorPos(getLength() - 1);
274 FXText::setBottomLine(getLength() - 1);
275 if (isEnabled()) {
276 layout();
277 update();
278 }
279}
280
281
282void
284 if (getLength() == 0) {
285 return;
286 }
287 FXText::removeText(0, getLength() - 1, true);
288 if (isEnabled()) {
289 layout();
290 update();
291 }
292}
293
294
295void
311
312
313void
321
322
323long
324GUIMessageWindow::onKeyPress(FXObject* o, FXSelector sel, void* ptr) {
325 FXEvent* e = (FXEvent*) ptr;
326 // permit ctrl+a, ctrl+c
327 if (e->state & CONTROLMASK) {
328 return FXText::onKeyPress(o, sel, ptr);
329 }
330 return 0;
331}
332
333
334FXHiliteStyle*
338
339
340void
342 const FXColor white = FXRGB(0xff, 0xff, 0xff);
343 const FXColor blue = FXRGB(0x00, 0x00, 0x88);
344 const FXColor green = FXRGB(0x00, 0x88, 0x00);
345 const FXColor red = FXRGB(0x88, 0x00, 0x00);
346 const FXColor yellow = FXRGB(0xe6, 0x98, 0x00);
347 const FXColor fuchsia = FXRGB(0x88, 0x00, 0x88);
348 // set separator style
349 myStyles[0].normalForeColor = blue;
350 myStyles[0].normalBackColor = white;
351 myStyles[0].selectForeColor = white;
352 myStyles[0].selectBackColor = blue;
353 myStyles[0].hiliteForeColor = blue;
354 myStyles[0].hiliteBackColor = white;
355 myStyles[0].activeBackColor = white;
356 myStyles[0].style = 0;
357 // set message text style
358 myStyles[1] = myStyles[0];
359 myStyles[1].normalForeColor = green;
360 myStyles[1].selectBackColor = green;
361 myStyles[1].hiliteForeColor = green;
362 myStyles[4] = myStyles[1];
363 myStyles[4].style = STYLE_UNDERLINE;
364 // set error text style
365 myStyles[2] = myStyles[0];
366 myStyles[2].normalForeColor = red;
367 myStyles[2].selectBackColor = red;
368 myStyles[2].hiliteForeColor = red;
369 myStyles[5] = myStyles[2];
370 myStyles[5].style = STYLE_UNDERLINE;
371 // set warning text style
372 myStyles[3] = myStyles[0];
373 myStyles[3].normalForeColor = yellow;
374 myStyles[3].selectBackColor = yellow;
375 myStyles[3].hiliteForeColor = yellow;
376 myStyles[6] = myStyles[3];
377 myStyles[6].style = STYLE_UNDERLINE;
378 // set GLDebug text style
379 myStyles[7] = myStyles[0];
380 myStyles[7].normalForeColor = fuchsia;
381 myStyles[7].selectBackColor = fuchsia;
382 myStyles[7].hiliteForeColor = fuchsia;
383}
384
385/****************************************************************************/
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[]
SUMOTime string2time(const std::string &r)
convert string to SUMOTime
Definition SUMOTime.cpp:46
std::string time2string(SUMOTime t, bool humanReadable)
convert SUMOTime to string (independently of global format setting)
Definition SUMOTime.cpp:69
#define TIME2STEPS(x)
Definition SUMOTime.h:57
T MIN2(T a, T b)
Definition StdDefs.h:76
T MAX2(T a, T b)
Definition StdDefs.h:82
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.
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
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
SUMOTime getTimeString(const FXString &text, const FXint pos, const FXint lineS, const FXint lineE) const
get time string object
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
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.