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.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 
40 FXHiliteStyle* GUIMessageWindow::myStyles = new FXHiliteStyle[8];
42 std::map<std::string, std::string> GUIMessageWindow::myTypeStrings;
43 
44 // ===========================================================================
45 // FOX callback mapping
46 // ===========================================================================
47 
48 FXDEFMAP(GUIMessageWindow) GUIMessageWindowMap[] = {
49  FXMAPFUNC(SEL_KEYPRESS, 0, GUIMessageWindow::onKeyPress),
50 };
51 
52 FXIMPLEMENT_ABSTRACT(GUIMessageWindow, FXText, GUIMessageWindowMap, ARRAYNUMBER(GUIMessageWindowMap))
53 
54 // ===========================================================================
55 // method definitions
56 // ===========================================================================
57 GUIMessageWindow::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 
87  delete[] myStyles;
88  delete myMessageRetriever;
89  delete myErrorRetriever;
90  delete myWarningRetriever;
91 }
92 
93 
94 const GUIGlObject*
95 GUIMessageWindow::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 
119 SUMOTime
120 GUIMessageWindow::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 
156 void
157 GUIMessageWindow::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 
192 void
193 GUIMessageWindow::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 
271 void
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 
284 void
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 
297 void
299  if (myMessageRetriever == nullptr) {
300  // initialize only if registration is requested
306  }
312 }
313 
314 
315 void
322 }
323 
324 
325 long
326 GUIMessageWindow::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 
336 FXHiliteStyle*
338  return myStyles;
339 }
340 
341 
342 void
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:35
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.
Definition: GUIGlObject.h:104
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.
GUIGlChildWindow * getViewByID(const std::string &id) const
get specific view by ID
std::vector< std::string > getViewIDs() const
get view IDs
virtual void addBreakpoint(const SUMOTime)
add breakpoint to the application
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.
Definition: MsgHandler.cpp:237
static MsgHandler * getGLDebugInstance()
Returns the instance to add GLdebug to.
Definition: MsgHandler.cpp:110
static MsgHandler * getErrorInstance()
Returns the instance to add errors to.
Definition: MsgHandler.cpp:92
static MsgHandler * getDebugInstance()
Returns the instance to add debug to.
Definition: MsgHandler.cpp:101
static MsgHandler * getWarningInstance()
Returns the instance to add warnings to.
Definition: MsgHandler.cpp:79
virtual void removeRetriever(OutputDevice *retriever)
Removes the retriever from the handler.
Definition: MsgHandler.cpp:245
static MsgHandler * getMessageInstance()
Returns the instance to add normal messages to.
Definition: MsgHandler.cpp:66
static std::string to_lower_case(const std::string &str)
Transfers the content to lower case.
Definition: StringUtils.cpp:79