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